diff --git a/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs b/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs index f020991224..f38654d2ad 100644 --- a/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs +++ b/Content.Client/Construction/UI/FlatpackCreatorMenu.xaml.cs @@ -79,8 +79,7 @@ public sealed partial class FlatpackCreatorMenu : FancyWindow else if (_currentBoard != null) { Dictionary cost; - if (_entityManager.TryGetComponent(_currentBoard, out machineBoardComp) && - machineBoardComp.Prototype is not null) + if (_entityManager.TryGetComponent(_currentBoard, out machineBoardComp)) cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker), (_currentBoard.Value, machineBoardComp)); else cost = _flatpack.GetFlatpackCreationCost((_owner, flatpacker)); diff --git a/Content.IntegrationTests/Tests/MachineBoardTest.cs b/Content.IntegrationTests/Tests/MachineBoardTest.cs index 097f38af42..3fcded1e5d 100644 --- a/Content.IntegrationTests/Tests/MachineBoardTest.cs +++ b/Content.IntegrationTests/Tests/MachineBoardTest.cs @@ -51,12 +51,11 @@ public sealed class MachineBoardTest Assert.Multiple(() => { - Assert.That(mId, Is.Not.Null, $"Machine board {p.ID} does not have a corresponding machine."); Assert.That(protoMan.TryIndex(mId, out var mProto), $"Machine board {p.ID}'s corresponding machine has an invalid prototype."); Assert.That(mProto.TryGetComponent(out var mComp, compFact), $"Machine board {p.ID}'s corresponding machine {mId} does not have MachineComponent"); - Assert.That(mComp.BoardPrototype, Is.EqualTo(p.ID), + Assert.That(mComp.Board, Is.EqualTo(p.ID), $"Machine {mId}'s BoardPrototype is not equal to it's corresponding machine board, {p.ID}"); }); } @@ -104,4 +103,40 @@ public sealed class MachineBoardTest await pair.CleanReturnAsync(); } + + /// + /// Ensures that every single computer board's corresponding entity + /// is a computer that can be properly deconstructed to the correct board + /// + [Test] + public async Task TestValidateBoardComponentRequirements() + { + await using var pair = await PoolManager.GetServerClient(); + var server = pair.Server; + + var entMan = server.ResolveDependency(); + var protoMan = server.ResolveDependency(); + + await server.WaitAssertion(() => + { + foreach (var p in protoMan.EnumeratePrototypes() + .Where(p => !p.Abstract) + .Where(p => !pair.IsTestPrototype(p)) + .Where(p => !_ignoredPrototypes.Contains(p.ID))) + { + if (!p.TryGetComponent(out var board, entMan.ComponentFactory)) + continue; + + Assert.Multiple(() => + { + foreach (var component in board.ComponentRequirements.Keys) + { + Assert.That(entMan.ComponentFactory.TryGetRegistration(component, out _), $"Invalid component requirement {component} specified on machine board entity {p}"); + } + }); + } + }); + + await pair.CleanReturnAsync(); + } } diff --git a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs index d113b539c4..c48afd819b 100644 --- a/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs +++ b/Content.IntegrationTests/Tests/MaterialArbitrageTest.cs @@ -61,7 +61,8 @@ public sealed class MaterialArbitrageTest } // Lets assume the possible lathe for resource multipliers: - var multiplier = MathF.Pow(LatheComponent.DefaultPartRatingMaterialUseMultiplier, MachinePartComponent.MaxRating - 1); + // TODO: each recipe can technically have its own cost multiplier associated with it, so this test needs redone to factor that in. + var multiplier = MathF.Pow(0.85f, 3); // create construction dictionary Dictionary constructionRecipes = new(); diff --git a/Content.Server/Construction/Components/IRefreshParts.cs b/Content.Server/Construction/Components/IRefreshParts.cs deleted file mode 100644 index 714ca72c97..0000000000 --- a/Content.Server/Construction/Components/IRefreshParts.cs +++ /dev/null @@ -1,10 +0,0 @@ -using Content.Shared.Construction.Components; - -namespace Content.Server.Construction.Components -{ - [RequiresExplicitImplementation] - public interface IRefreshParts - { - void RefreshParts(IEnumerable parts); - } -} diff --git a/Content.Server/Construction/Components/MachineComponent.cs b/Content.Server/Construction/Components/MachineComponent.cs index 42c85e6d0b..b62eb7b776 100644 --- a/Content.Server/Construction/Components/MachineComponent.cs +++ b/Content.Server/Construction/Components/MachineComponent.cs @@ -1,27 +1,26 @@ -using Robust.Shared.Containers; +using Content.Shared.Construction.Components; +using Robust.Shared.Containers; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -namespace Content.Server.Construction.Components +namespace Content.Server.Construction.Components; + +[RegisterComponent] +public sealed partial class MachineComponent : Component { - [RegisterComponent, ComponentProtoName("Machine")] - public sealed partial class MachineComponent : Component - { - [DataField("board", customTypeSerializer: typeof(PrototypeIdSerializer))] - public string? BoardPrototype { get; private set; } + [DataField] + public EntProtoId? Board { get; private set; } - [ViewVariables] - public Container BoardContainer = default!; - [ViewVariables] - public Container PartContainer = default!; - } - - /// - /// The different types of scaling that are available for machine upgrades - /// - public enum MachineUpgradeScalingType : byte - { - Linear, - Exponential - } + [ViewVariables] + public Container BoardContainer = default!; + [ViewVariables] + public Container PartContainer = default!; +} + +/// +/// The different types of scaling that are available for machine upgrades +/// +public enum MachineUpgradeScalingType : byte +{ + Linear, + Exponential } diff --git a/Content.Server/Construction/Components/MachineFrameComponent.cs b/Content.Server/Construction/Components/MachineFrameComponent.cs index 75cc486f24..c9adbdbaa5 100644 --- a/Content.Server/Construction/Components/MachineFrameComponent.cs +++ b/Content.Server/Construction/Components/MachineFrameComponent.cs @@ -1,47 +1,48 @@ using Content.Shared.Construction.Components; using Content.Shared.Construction.Prototypes; +using Content.Shared.Stacks; +using Content.Shared.Tag; using Robust.Shared.Containers; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; +using Robust.Shared.Prototypes; -namespace Content.Server.Construction.Components +namespace Content.Server.Construction.Components; + +[RegisterComponent] +public sealed partial class MachineFrameComponent : Component { - [RegisterComponent] - public sealed partial class MachineFrameComponent : Component - { - public const string PartContainerName = "machine_parts"; - public const string BoardContainerName = "machine_board"; + public const string PartContainerName = "machine_parts"; + public const string BoardContainerName = "machine_board"; - [ViewVariables] - public bool HasBoard => BoardContainer?.ContainedEntities.Count != 0; + [ViewVariables] + public bool HasBoard => BoardContainer.ContainedEntities.Count != 0; - [DataField("progress", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] - public Dictionary Progress = new(); + [ViewVariables] + public readonly Dictionary, int> MachinePartProgress = new(); - [ViewVariables] - public readonly Dictionary MaterialProgress = new(); + [ViewVariables] + public readonly Dictionary, int> MaterialProgress = new(); - [ViewVariables] - public readonly Dictionary ComponentProgress = new(); + [ViewVariables] + public readonly Dictionary ComponentProgress = new(); - [ViewVariables] - public readonly Dictionary TagProgress = new(); + [ViewVariables] + public readonly Dictionary, int> TagProgress = new(); - [DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] - public Dictionary Requirements = new(); + [ViewVariables] + public Dictionary, int> MachinePartRequirements = new(); - [ViewVariables] - public Dictionary MaterialRequirements = new(); + [ViewVariables] + public Dictionary, int> MaterialRequirements = new(); - [ViewVariables] - public Dictionary ComponentRequirements = new(); + [ViewVariables] + public Dictionary ComponentRequirements = new(); - [ViewVariables] - public Dictionary TagRequirements = new(); + [ViewVariables] + public Dictionary, GenericPartInfo> TagRequirements = new(); - [ViewVariables] - public Container BoardContainer = default!; + [ViewVariables] + public Container BoardContainer = default!; - [ViewVariables] - public Container PartContainer = default!; - } + [ViewVariables] + public Container PartContainer = default!; } diff --git a/Content.Server/Construction/Components/PartExchangerComponent.cs b/Content.Server/Construction/Components/PartExchangerComponent.cs index a2579c92e8..090af98e7a 100644 --- a/Content.Server/Construction/Components/PartExchangerComponent.cs +++ b/Content.Server/Construction/Components/PartExchangerComponent.cs @@ -8,7 +8,7 @@ public sealed partial class PartExchangerComponent : Component /// /// How long it takes to exchange the parts /// - [DataField("exchangeDuration")] + [DataField] public float ExchangeDuration = 3; /// @@ -19,10 +19,10 @@ public sealed partial class PartExchangerComponent : Component /// I fucking hate BRPED and if you ever add it /// i will personally kill your dog. /// - [DataField("doDistanceCheck")] + [DataField] public bool DoDistanceCheck = true; - [DataField("exchangeSound")] + [DataField] public SoundSpecifier ExchangeSound = new SoundPathSpecifier("/Audio/Items/rped.ogg"); public EntityUid? AudioStream; diff --git a/Content.Server/Construction/Conditions/MachineFrameComplete.cs b/Content.Server/Construction/Conditions/MachineFrameComplete.cs index fbba5eca99..b866729c5e 100644 --- a/Content.Server/Construction/Conditions/MachineFrameComplete.cs +++ b/Content.Server/Construction/Conditions/MachineFrameComplete.cs @@ -2,6 +2,7 @@ using Content.Server.Construction.Components; using Content.Shared.Construction; using Content.Shared.Examine; using JetBrains.Annotations; +using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Server.Construction.Conditions @@ -17,7 +18,7 @@ namespace Content.Server.Construction.Conditions public SpriteSpecifier? GuideIconBoard { get; private set; } [DataField("guideIconParts")] - public SpriteSpecifier? GuideIconPart { get; private set; } + public SpriteSpecifier? GuideIconParts { get; private set; } public bool Condition(EntityUid uid, IEntityManager entityManager) @@ -33,6 +34,8 @@ namespace Content.Server.Construction.Conditions var entity = args.Examined; var entityManager = IoCManager.Resolve(); + var protoManager = IoCManager.Resolve(); + var constructionSys = entityManager.System(); if (!entityManager.TryGetComponent(entity, out MachineFrameComponent? machineFrame)) return false; @@ -47,16 +50,19 @@ namespace Content.Server.Construction.Conditions return false; args.PushMarkup(Loc.GetString("construction-condition-machine-frame-requirement-label")); - foreach (var (part, required) in machineFrame.Requirements) + + foreach (var (machinePartId, required) in machineFrame.MachinePartRequirements) { - var amount = required - machineFrame.Progress[part]; + var amount = required - machineFrame.MachinePartRequirements[machinePartId]; if(amount == 0) continue; + var machinePart = protoManager.Index(machinePartId); + args.PushMarkup(Loc.GetString("construction-condition-machine-frame-required-element-entry", - ("amount", amount), - ("elementName", Loc.GetString(part)))); + ("amount", amount), + ("elementName", machinePart.Name))); } foreach (var (material, required) in machineFrame.MaterialRequirements) @@ -66,9 +72,12 @@ namespace Content.Server.Construction.Conditions if(amount == 0) continue; + var stack = protoManager.Index(material); + var stackEnt = protoManager.Index(stack.Spawn); + args.PushMarkup(Loc.GetString("construction-condition-machine-frame-required-element-entry", ("amount", amount), - ("elementName", Loc.GetString(material)))); + ("elementName", stackEnt.Name))); } foreach (var (compName, info) in machineFrame.ComponentRequirements) @@ -78,9 +87,10 @@ namespace Content.Server.Construction.Conditions if(amount == 0) continue; + var examineName = constructionSys.GetExamineName(info); args.PushMarkup(Loc.GetString("construction-condition-machine-frame-required-element-entry", ("amount", info.Amount), - ("elementName", Loc.GetString(info.ExamineName)))); + ("elementName", examineName))); } foreach (var (tagName, info) in machineFrame.TagRequirements) @@ -90,9 +100,10 @@ namespace Content.Server.Construction.Conditions if(amount == 0) continue; + var examineName = constructionSys.GetExamineName(info); args.PushMarkup(Loc.GetString("construction-condition-machine-frame-required-element-entry", ("amount", info.Amount), - ("elementName", Loc.GetString(info.ExamineName))) + ("elementName", examineName)) + "\n"); } @@ -111,7 +122,7 @@ namespace Content.Server.Construction.Conditions yield return new ConstructionGuideEntry() { Localization = "construction-step-condition-machine-frame-parts", - Icon = GuideIconPart, + Icon = GuideIconParts, EntryNumber = 0, // Set this to anything so the guide generation takes this as a numbered step. }; } diff --git a/Content.Server/Construction/ConstructionSystem.Graph.cs b/Content.Server/Construction/ConstructionSystem.Graph.cs index f612f3e7e4..ec8fe049c9 100644 --- a/Content.Server/Construction/ConstructionSystem.Graph.cs +++ b/Content.Server/Construction/ConstructionSystem.Graph.cs @@ -51,7 +51,7 @@ namespace Content.Server.Construction // If the set graph prototype does not exist, also return null. This could be due to admemes changing values // in ViewVariables, so even though the construction state is invalid, just return null. - return _prototypeManager.TryIndex(construction.Graph, out ConstructionGraphPrototype? graph) ? graph : null; + return PrototypeManager.TryIndex(construction.Graph, out ConstructionGraphPrototype? graph) ? graph : null; } /// @@ -301,7 +301,7 @@ namespace Content.Server.Construction } // Exit if the new entity's prototype is the same as the original, or the prototype is invalid - if (newEntity == metaData.EntityPrototype?.ID || !_prototypeManager.HasIndex(newEntity)) + if (newEntity == metaData.EntityPrototype?.ID || !PrototypeManager.HasIndex(newEntity)) return null; // [Optional] Exit if the new entity's prototype is a parent of the original @@ -311,7 +311,7 @@ namespace Content.Server.Construction if (GetCurrentNode(uid, construction)?.DoNotReplaceInheritingEntities == true && metaData.EntityPrototype?.ID != null) { - var parents = _prototypeManager.EnumerateParents(metaData.EntityPrototype.ID)?.ToList(); + var parents = PrototypeManager.EnumerateParents(metaData.EntityPrototype.ID)?.ToList(); if (parents != null && parents.Any(x => x.ID == newEntity)) return null; @@ -446,7 +446,7 @@ namespace Content.Server.Construction if (!Resolve(uid, ref construction)) return false; - if (!_prototypeManager.TryIndex(graphId, out var graph)) + if (!PrototypeManager.TryIndex(graphId, out var graph)) return false; if(GetNodeFromGraph(graph, nodeId) is not {}) diff --git a/Content.Server/Construction/ConstructionSystem.Guided.cs b/Content.Server/Construction/ConstructionSystem.Guided.cs index e096bc02c3..157e421158 100644 --- a/Content.Server/Construction/ConstructionSystem.Guided.cs +++ b/Content.Server/Construction/ConstructionSystem.Guided.cs @@ -25,7 +25,7 @@ namespace Content.Server.Construction private void OnGuideRequested(RequestConstructionGuide msg, EntitySessionEventArgs args) { - if (!_prototypeManager.TryIndex(msg.ConstructionId, out ConstructionPrototype? prototype)) + if (!PrototypeManager.TryIndex(msg.ConstructionId, out ConstructionPrototype? prototype)) return; if(GetGuide(prototype) is {} guide) @@ -41,7 +41,7 @@ namespace Content.Server.Construction component.Node == component.DeconstructionNode) return; - if (!_prototypeManager.TryIndex(component.Graph, out ConstructionGraphPrototype? graph)) + if (!PrototypeManager.TryIndex(component.Graph, out ConstructionGraphPrototype? graph)) return; if (component.DeconstructionNode == null) @@ -145,7 +145,7 @@ namespace Content.Server.Construction return guide; // If the graph doesn't actually exist, do nothing. - if (!_prototypeManager.TryIndex(construction.Graph, out ConstructionGraphPrototype? graph)) + if (!PrototypeManager.TryIndex(construction.Graph, out ConstructionGraphPrototype? graph)) return null; // If either the start node or the target node are missing, do nothing. diff --git a/Content.Server/Construction/ConstructionSystem.Initial.cs b/Content.Server/Construction/ConstructionSystem.Initial.cs index bf7b3e415f..dae9162554 100644 --- a/Content.Server/Construction/ConstructionSystem.Initial.cs +++ b/Content.Server/Construction/ConstructionSystem.Initial.cs @@ -325,13 +325,13 @@ namespace Content.Server.Construction // LEGACY CODE. See warning at the top of the file! public async Task TryStartItemConstruction(string prototype, EntityUid user) { - if (!_prototypeManager.TryIndex(prototype, out ConstructionPrototype? constructionPrototype)) + if (!PrototypeManager.TryIndex(prototype, out ConstructionPrototype? constructionPrototype)) { Log.Error($"Tried to start construction of invalid recipe '{prototype}'!"); return false; } - if (!_prototypeManager.TryIndex(constructionPrototype.Graph, + if (!PrototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype? constructionGraph)) { Log.Error( @@ -404,14 +404,14 @@ namespace Content.Server.Construction // LEGACY CODE. See warning at the top of the file! private async void HandleStartStructureConstruction(TryStartStructureConstructionMessage ev, EntitySessionEventArgs args) { - if (!_prototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype? constructionPrototype)) + if (!PrototypeManager.TryIndex(ev.PrototypeName, out ConstructionPrototype? constructionPrototype)) { Log.Error($"Tried to start construction of invalid recipe '{ev.PrototypeName}'!"); RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack)); return; } - if (!_prototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype? constructionGraph)) + if (!PrototypeManager.TryIndex(constructionPrototype.Graph, out ConstructionGraphPrototype? constructionGraph)) { Log.Error($"Invalid construction graph '{constructionPrototype.Graph}' in recipe '{ev.PrototypeName}'!"); RaiseNetworkEvent(new AckStructureConstructionMessage(ev.Ack)); diff --git a/Content.Server/Construction/ConstructionSystem.Machine.cs b/Content.Server/Construction/ConstructionSystem.Machine.cs index 65b0b70476..e32c1be6fd 100644 --- a/Content.Server/Construction/ConstructionSystem.Machine.cs +++ b/Content.Server/Construction/ConstructionSystem.Machine.cs @@ -5,7 +5,7 @@ using Content.Shared.Construction.Components; using Content.Shared.Construction.Prototypes; using Content.Shared.Verbs; using Robust.Shared.Containers; -using Robust.Shared.Map.Components; +using Robust.Shared.Prototypes; using Robust.Shared.Utility; namespace Content.Server.Construction; @@ -40,12 +40,13 @@ public sealed partial class ConstructionSystem var markup = new FormattedMessage(); RaiseLocalEvent(uid, new UpgradeExamineEvent(ref markup)); + if (markup.IsEmpty) return; // Not upgradable. - markup = FormattedMessage.FromMarkup(markup.ToMarkup().TrimEnd('\n')); // Cursed workaround to https://github.com/space-wizards/RobustToolbox/issues/3371 + markup = FormattedMessage.FromMarkupOrThrow(markup.ToMarkup().TrimEnd('\n')); - var verb = new ExamineVerb() + var verb = new ExamineVerb { Act = () => { @@ -81,10 +82,10 @@ public sealed partial class ConstructionSystem return parts; } - public Dictionary GetPartsRatings(List parts) + public Dictionary, float> GetPartsRatings(List parts) { - var output = new Dictionary(); - foreach (var type in _prototypeManager.EnumeratePrototypes()) + var output = new Dictionary, float>(); + foreach (var type in PrototypeManager.EnumeratePrototypes()) { var amount = 0f; var sumRating = 0f; @@ -93,6 +94,7 @@ public sealed partial class ConstructionSystem amount++; sumRating += part.Rating; } + var rating = amount != 0 ? sumRating / amount : 0; output.Add(type.ID, rating); } @@ -103,11 +105,13 @@ public sealed partial class ConstructionSystem public void RefreshParts(EntityUid uid, MachineComponent component) { var parts = GetAllParts(component); - EntityManager.EventBus.RaiseLocalEvent(uid, new RefreshPartsEvent + var ev = new RefreshPartsEvent { Parts = parts, PartRatings = GetPartsRatings(parts), - }, true); + }; + + RaiseLocalEvent(uid, ev, true); } private void CreateBoardAndStockParts(EntityUid uid, MachineComponent component) @@ -116,54 +120,45 @@ public sealed partial class ConstructionSystem var boardContainer = _container.EnsureContainer(uid, MachineFrameComponent.BoardContainerName); var partContainer = _container.EnsureContainer(uid, MachineFrameComponent.PartContainerName); - if (string.IsNullOrEmpty(component.BoardPrototype)) + if (string.IsNullOrEmpty(component.Board)) return; // We're done here, let's suppose all containers are correct just so we don't screw SaveLoadSave. if (boardContainer.ContainedEntities.Count > 0) return; - var board = EntityManager.SpawnEntity(component.BoardPrototype, Transform(uid).Coordinates); - - if (!_container.Insert(board, component.BoardContainer)) - { - throw new Exception($"Couldn't insert board with prototype {component.BoardPrototype} to machine with prototype {MetaData(uid).EntityPrototype?.ID ?? "N/A"}!"); - } + var xform = Transform(uid); + if (!TrySpawnInContainer(component.Board, uid, MachineFrameComponent.BoardContainerName, out var board)) + throw new Exception($"Couldn't insert board with prototype {component.Board} to machine with prototype {Prototype(uid)?.ID ?? "N/A"}!"); if (!TryComp(board, out var machineBoard)) - { - throw new Exception($"Entity with prototype {component.BoardPrototype} doesn't have a {nameof(MachineBoardComponent)}!"); - } + throw new Exception($"Entity with prototype {component.Board} doesn't have a {nameof(MachineBoardComponent)}!"); - var xform = Transform(uid); - foreach (var (part, amount) in machineBoard.Requirements) + foreach (var (machinePartId, amount) in machineBoard.MachinePartRequirements) { - var partProto = _prototypeManager.Index(part); + var machinePart = PrototypeManager.Index(machinePartId); for (var i = 0; i < amount; i++) { - var p = EntityManager.SpawnEntity(partProto.StockPartPrototype, xform.Coordinates); + var p = EntityManager.SpawnEntity(machinePart.StockPartPrototype, xform.Coordinates); if (!_container.Insert(p, partContainer)) - throw new Exception($"Couldn't insert machine part of type {part} to machine with prototype {partProto.StockPartPrototype ?? "N/A"}!"); + throw new Exception($"Couldn't insert machine part of type {machinePartId} to machine with prototype {machinePart.StockPartPrototype}!"); } } - foreach (var (stackType, amount) in machineBoard.MaterialRequirements) + foreach (var (stackType, amount) in machineBoard.StackRequirements) { - var stack = _stackSystem.Spawn(amount, stackType, Transform(uid).Coordinates); - + var stack = _stackSystem.Spawn(amount, stackType, xform.Coordinates); if (!_container.Insert(stack, partContainer)) - throw new Exception($"Couldn't insert machine material of type {stackType} to machine with prototype {MetaData(uid).EntityPrototype?.ID ?? "N/A"}"); + throw new Exception($"Couldn't insert machine material of type {stackType} to machine with prototype {Prototype(uid)?.ID ?? "N/A"}"); } foreach (var (compName, info) in machineBoard.ComponentRequirements) { for (var i = 0; i < info.Amount; i++) { - var c = EntityManager.SpawnEntity(info.DefaultPrototype, Transform(uid).Coordinates); - - if(!_container.Insert(c, partContainer)) - throw new Exception($"Couldn't insert machine component part with default prototype '{compName}' to machine with prototype {MetaData(uid).EntityPrototype?.ID ?? "N/A"}"); + if(!TrySpawnInContainer(info.DefaultPrototype, uid, MachineFrameComponent.PartContainerName, out _)) + throw new Exception($"Couldn't insert machine component part with default prototype '{compName}' to machine with prototype {Prototype(uid)?.ID ?? "N/A"}"); } } @@ -171,10 +166,8 @@ public sealed partial class ConstructionSystem { for (var i = 0; i < info.Amount; i++) { - var c = EntityManager.SpawnEntity(info.DefaultPrototype, Transform(uid).Coordinates); - - if(!_container.Insert(c, partContainer)) - throw new Exception($"Couldn't insert machine component part with default prototype '{tagName}' to machine with prototype {MetaData(uid).EntityPrototype?.ID ?? "N/A"}"); + if(!TrySpawnInContainer(info.DefaultPrototype, uid, MachineFrameComponent.PartContainerName, out _)) + throw new Exception($"Couldn't insert machine component part with default prototype '{tagName}' to machine with prototype {Prototype(uid)?.ID ?? "N/A"}"); } } } @@ -184,45 +177,44 @@ public sealed class RefreshPartsEvent : EntityEventArgs { public IReadOnlyList Parts = new List(); - public Dictionary PartRatings = new Dictionary(); + public Dictionary, float> PartRatings = new(); } -public sealed class UpgradeExamineEvent : EntityEventArgs +public sealed class UpgradeExamineEvent(ref FormattedMessage message) : EntityEventArgs { - private FormattedMessage Message; - - public UpgradeExamineEvent(ref FormattedMessage message) - { - Message = message; - } + private readonly FormattedMessage _message = message; /// /// Add a line to the upgrade examine tooltip with a percentage-based increase or decrease. /// - public void AddPercentageUpgrade(string upgradedLocId, float multiplier) + public void AddPercentageUpgrade(LocId upgraded, float multiplier) { var percent = Math.Round(100 * MathF.Abs(multiplier - 1), 2); - var locId = multiplier switch { + var locId = multiplier switch + { < 1 => "machine-upgrade-decreased-by-percentage", 1 or float.NaN => "machine-upgrade-not-upgraded", - > 1 => "machine-upgrade-increased-by-percentage", + > 1 => "machine-upgrade-increased-by-percentage" }; - var upgraded = Loc.GetString(upgradedLocId); - this.Message.AddMarkup(Loc.GetString(locId, ("upgraded", upgraded), ("percent", percent)) + '\n'); + + var markup = Loc.GetString(locId, ("upgraded", Loc.GetString(upgraded)), ("percent", percent)) + '\n'; + _message.AddMarkupOrThrow(markup); } /// /// Add a line to the upgrade examine tooltip with a numeric increase or decrease. /// - public void AddNumberUpgrade(string upgradedLocId, int number) + public void AddNumberUpgrade(LocId upgraded, int number) { var difference = Math.Abs(number); - var locId = number switch { + var locId = number switch + { < 0 => "machine-upgrade-decreased-by-amount", 0 => "machine-upgrade-not-upgraded", > 0 => "machine-upgrade-increased-by-amount", }; - var upgraded = Loc.GetString(upgradedLocId); - this.Message.AddMarkup(Loc.GetString(locId, ("upgraded", upgraded), ("difference", difference)) + '\n'); + + var markup = Loc.GetString(locId, ("upgraded", Loc.GetString(upgraded)), ("difference", difference)) + '\n'; + _message.AddMarkupOrThrow(markup); } } diff --git a/Content.Server/Construction/ConstructionSystem.cs b/Content.Server/Construction/ConstructionSystem.cs index 44c6318b78..9d881dcef0 100644 --- a/Content.Server/Construction/ConstructionSystem.cs +++ b/Content.Server/Construction/ConstructionSystem.cs @@ -16,7 +16,6 @@ namespace Content.Server.Construction [UsedImplicitly] public sealed partial class ConstructionSystem : SharedConstructionSystem { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly SharedDoAfterSystem _doAfterSystem = default!; [Dependency] private readonly ContainerSystem _container = default!; diff --git a/Content.Server/Construction/MachineFrameSystem.cs b/Content.Server/Construction/MachineFrameSystem.cs index e20c36d849..49ada12fb9 100644 --- a/Content.Server/Construction/MachineFrameSystem.cs +++ b/Content.Server/Construction/MachineFrameSystem.cs @@ -1,13 +1,14 @@ using Content.Server.Construction.Components; using Content.Server.Stack; using Content.Shared.Construction.Components; +using Content.Shared.Construction.Prototypes; using Content.Shared.Examine; using Content.Shared.Interaction; using Content.Shared.Stacks; using Content.Shared.Tag; using Content.Shared.Popups; using Robust.Shared.Containers; -using Robust.Shared.Utility; +using Robust.Shared.Prototypes; namespace Content.Server.Construction; @@ -62,24 +63,14 @@ public sealed class MachineFrameSystem : EntitySystem // If this changes in the future, then RegenerateProgress() also needs to be updated. // Note that one entity is ALLOWED to satisfy more than one kind of component or tag requirements. This is // necessary in order to avoid weird entity-ordering shenanigans in RegenerateProgress(). - var stack = CompOrNull(args.Used); - var machinePart = CompOrNull(args.Used); - if (stack != null && machinePart != null) - { - if (TryInsertPartStack(uid, args.Used, component, machinePart, stack)) - args.Handled = true; - return; - } - - // Handle parts - if (machinePart != null) + if (TryComp(args.Used, out var machinePart)) { if (TryInsertPart(uid, args.Used, component, machinePart)) args.Handled = true; return; } - if (stack != null) + if (TryComp(args.Used, out var stack)) { if (TryInsertStack(uid, args.Used, component, stack)) args.Handled = true; @@ -173,60 +164,34 @@ public sealed class MachineFrameSystem : EntitySystem } /// Whether or not the function had any effect. Does not indicate success. - private bool TryInsertPart(EntityUid uid, EntityUid used, MachineFrameComponent component, MachinePartComponent machinePart) + private bool TryInsertPart(EntityUid uid, EntityUid? used, MachineFrameComponent component, MachinePartComponent machinePart) { - DebugTools.Assert(!HasComp(uid)); - if (!component.Requirements.ContainsKey(machinePart.PartType)) + if (!component.MachinePartRequirements.TryGetValue(machinePart.PartType, out var requirement)) return false; - if (component.Progress[machinePart.PartType] >= component.Requirements[machinePart.PartType]) - return false; - - if (!_container.TryRemoveFromContainer(used)) - return false; - - if (!_container.Insert(used, component.PartContainer)) - return true; - - component.Progress[machinePart.PartType]++; - if (IsComplete(component)) - _popupSystem.PopupEntity(Loc.GetString("machine-frame-component-on-complete"), uid); - - return true; - } - - /// Whether or not the function had any effect. Does not indicate success. - private bool TryInsertPartStack(EntityUid uid, EntityUid used, MachineFrameComponent component, MachinePartComponent machinePart, StackComponent stack) - { - if (!component.Requirements.ContainsKey(machinePart.PartType)) - return false; - - var progress = component.Progress[machinePart.PartType]; - var requirement = component.Requirements[machinePart.PartType]; - + var progress = component.MachinePartProgress[machinePart.PartType]; var needed = requirement - progress; + if (needed <= 0) return false; - var count = stack.Count; - if (count < needed) - { - if (!_container.Insert(used, component.PartContainer)) - return true; + var count = 1; - component.Progress[machinePart.PartType] += count; - return true; + if (TryComp(used, out var stack)) + { + count = stack.Count; + + if (count > needed) + used = _stack.Split(used.Value, needed, Transform(uid).Coordinates, stack); } - var splitStack = _stack.Split(used, needed, Transform(uid).Coordinates, stack); - - if (splitStack == null) + if (used == null) return false; - if (!_container.Insert(splitStack.Value, component.PartContainer)) + if (!_container.Insert(used.Value, component.PartContainer)) return true; - component.Progress[machinePart.PartType] += needed; + component.MachinePartProgress[machinePart.PartType] += count; if (IsComplete(component)) _popupSystem.PopupEntity(Loc.GetString("machine-frame-component-on-complete"), uid); @@ -281,9 +246,9 @@ public sealed class MachineFrameSystem : EntitySystem if (!component.HasBoard) return false; - foreach (var (part, amount) in component.Requirements) + foreach (var (part, amount) in component.MachinePartRequirements) { - if (component.Progress[part] < amount) + if (component.MachinePartProgress[part] < amount) return false; } @@ -310,19 +275,19 @@ public sealed class MachineFrameSystem : EntitySystem public void ResetProgressAndRequirements(MachineFrameComponent component, MachineBoardComponent machineBoard) { - component.Requirements = new Dictionary(machineBoard.Requirements); - component.MaterialRequirements = new Dictionary(machineBoard.MaterialIdRequirements); + component.MachinePartRequirements = new Dictionary, int>(machineBoard.MachinePartRequirements); + component.MaterialRequirements = new Dictionary, int>(machineBoard.StackRequirements); component.ComponentRequirements = new Dictionary(machineBoard.ComponentRequirements); - component.TagRequirements = new Dictionary(machineBoard.TagRequirements); + component.TagRequirements = new Dictionary, GenericPartInfo>(machineBoard.TagRequirements); - component.Progress.Clear(); + component.MachinePartProgress.Clear(); component.MaterialProgress.Clear(); component.ComponentProgress.Clear(); component.TagProgress.Clear(); - foreach (var (machinePart, _) in component.Requirements) + foreach (var (machinePartId, _) in component.MachinePartRequirements) { - component.Progress[machinePart] = 0; + component.MachinePartProgress[machinePartId] = 0; } foreach (var (stackType, _) in component.MaterialRequirements) @@ -345,11 +310,11 @@ public sealed class MachineFrameSystem : EntitySystem { if (!component.HasBoard) { - component.TagRequirements.Clear(); + component.MachinePartRequirements.Clear(); component.MaterialRequirements.Clear(); component.ComponentRequirements.Clear(); component.TagRequirements.Clear(); - component.Progress.Clear(); + component.MachinePartProgress.Clear(); component.MaterialProgress.Clear(); component.ComponentProgress.Clear(); component.TagProgress.Clear(); @@ -371,13 +336,13 @@ public sealed class MachineFrameSystem : EntitySystem if (TryComp(part, out var machinePart)) { // Check this is part of the requirements... - if (!component.Requirements.ContainsKey(machinePart.PartType)) + if (!component.MachinePartRequirements.ContainsKey(machinePart.PartType)) continue; - if (!component.Progress.ContainsKey(machinePart.PartType)) - component.Progress[machinePart.PartType] = 1; - else - component.Progress[machinePart.PartType]++; + var count = CompOrNull(part)?.Count ?? 1; + if (!component.MachinePartProgress.TryAdd(machinePart.PartType, count)) + component.MachinePartProgress[machinePart.PartType] += count; + continue; } @@ -388,9 +353,7 @@ public sealed class MachineFrameSystem : EntitySystem if (!component.MaterialRequirements.ContainsKey(type)) continue; - if (!component.MaterialProgress.ContainsKey(type)) - component.MaterialProgress[type] = stack.Count; - else + if (!component.MaterialProgress.TryAdd(type, stack.Count)) component.MaterialProgress[type] += stack.Count; continue; @@ -404,9 +367,7 @@ public sealed class MachineFrameSystem : EntitySystem if (!HasComp(part, registration.Type)) continue; - if (!component.ComponentProgress.ContainsKey(compName)) - component.ComponentProgress[compName] = 1; - else + if (!component.ComponentProgress.TryAdd(compName, 1)) component.ComponentProgress[compName]++; } @@ -419,18 +380,17 @@ public sealed class MachineFrameSystem : EntitySystem if (!_tag.HasTag(tagComp, tagName)) continue; - if (!component.TagProgress.ContainsKey(tagName)) - component.TagProgress[tagName] = 1; - else + if (!component.TagProgress.TryAdd(tagName, 1)) component.TagProgress[tagName]++; } } } private void OnMachineFrameExamined(EntityUid uid, MachineFrameComponent component, ExaminedEvent args) { - if (!args.IsInDetailsRange) + if (!args.IsInDetailsRange || !component.HasBoard) return; - if (component.HasBoard) - args.PushMarkup(Loc.GetString("machine-frame-component-on-examine-label", ("board", EntityManager.GetComponent(component.BoardContainer.ContainedEntities[0]).EntityName))); + + var board = component.BoardContainer.ContainedEntities[0]; + args.PushMarkup(Loc.GetString("machine-frame-component-on-examine-label", ("board", Name(board)))); } } diff --git a/Content.Server/Construction/PartExchangerSystem.cs b/Content.Server/Construction/PartExchangerSystem.cs index 97de3ee486..93072e49fd 100644 --- a/Content.Server/Construction/PartExchangerSystem.cs +++ b/Content.Server/Construction/PartExchangerSystem.cs @@ -10,7 +10,6 @@ using Content.Shared.Storage; using Robust.Shared.Containers; using Robust.Shared.Utility; using Content.Shared.Wires; -using Robust.Shared.Audio; using Robust.Shared.Audio.Systems; using Robust.Shared.Collections; @@ -25,7 +24,6 @@ public sealed class PartExchangerSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly StorageSystem _storage = default!; - /// public override void Initialize() { SubscribeLocalEvent(OnAfterInteract); @@ -40,14 +38,11 @@ public sealed class PartExchangerSystem : EntitySystem return; } - if (args.Handled || args.Args.Target == null) + if (args.Handled || args.Args.Target == null || !TryComp(uid, out var storage)) return; - if (!TryComp(uid, out var storage) || storage.Container == null) - return; //the parts are stored in here - var machinePartQuery = GetEntityQuery(); - var machineParts = new List<(EntityUid, MachinePartComponent)>(); + var machineParts = new List>(); foreach (var item in storage.Container.ContainedEntities) //get parts in RPED { @@ -61,7 +56,7 @@ public sealed class PartExchangerSystem : EntitySystem args.Handled = true; } - private void TryExchangeMachineParts(EntityUid uid, EntityUid storageUid, List<(EntityUid part, MachinePartComponent partComp)> machineParts) + private void TryExchangeMachineParts(EntityUid uid, EntityUid storageUid, List> machineParts) { if (!TryComp(uid, out var machine)) return; @@ -69,41 +64,41 @@ public sealed class PartExchangerSystem : EntitySystem var machinePartQuery = GetEntityQuery(); var board = machine.BoardContainer.ContainedEntities.FirstOrNull(); - if (board == null || !TryComp(board, out var macBoardComp)) + if (!TryComp(board, out var macBoardComp)) return; foreach (var item in new ValueList(machine.PartContainer.ContainedEntities)) //clone so don't modify during enumeration { - if (machinePartQuery.TryGetComponent(item, out var part)) - { - machineParts.Add((item, part)); - _container.RemoveEntity(uid, item); - } + if (!machinePartQuery.TryGetComponent(item, out var part)) + continue; + + machineParts.Add((item, part)); + _container.RemoveEntity(uid, item); } - machineParts.Sort((x, y) => y.partComp.Rating.CompareTo(x.partComp.Rating)); + machineParts.Sort((x, y) => x.Comp.Rating.CompareTo(y.Comp.Rating)); - var updatedParts = new List<(EntityUid part, MachinePartComponent partComp)>(); - foreach (var (type, amount) in macBoardComp.Requirements) + var updatedParts = new List>(); + foreach (var (machinePartId, amount) in macBoardComp.MachinePartRequirements) { - var target = machineParts.Where(p => p.partComp.PartType == type).Take(amount); + var target = machineParts.Where(p => p.Comp.PartType == machinePartId).Take(amount); updatedParts.AddRange(target); } + foreach (var part in updatedParts) { - _container.Insert(part.part, machine.PartContainer); + _container.Insert(part.Owner, machine.PartContainer); machineParts.Remove(part); } //put the unused parts back into rped. (this also does the "swapping") foreach (var (unused, _) in machineParts) - { _storage.Insert(storageUid, unused, out _, playSound: false); - } + _construction.RefreshParts(uid, machine); } - private void TryConstructMachineParts(EntityUid uid, EntityUid storageEnt, List<(EntityUid part, MachinePartComponent partComp)> machineParts) + private void TryConstructMachineParts(EntityUid uid, EntityUid storageEnt, List> machineParts) { if (!TryComp(uid, out var machine)) return; @@ -111,76 +106,71 @@ public sealed class PartExchangerSystem : EntitySystem var machinePartQuery = GetEntityQuery(); var board = machine.BoardContainer.ContainedEntities.FirstOrNull(); - if (!machine.HasBoard || !TryComp(board, out var macBoardComp)) + if (!TryComp(board, out var macBoardComp)) return; foreach (var item in new ValueList(machine.PartContainer.ContainedEntities)) //clone so don't modify during enumeration { - if (machinePartQuery.TryGetComponent(item, out var part)) - { - machineParts.Add((item, part)); - _container.RemoveEntity(uid, item); - machine.Progress[part.PartType]--; - } - } - - machineParts.Sort((x, y) => y.partComp.Rating.CompareTo(x.partComp.Rating)); - - var updatedParts = new List<(EntityUid part, MachinePartComponent partComp)>(); - foreach (var (type, amount) in macBoardComp.Requirements) - { - var target = machineParts.Where(p => p.partComp.PartType == type).Take(amount); - updatedParts.AddRange(target); - } - foreach (var pair in updatedParts) - { - var part = pair.partComp; - var partEnt = pair.part; - - if (!machine.Requirements.ContainsKey(part.PartType)) + if (!machinePartQuery.TryGetComponent(item, out var part)) continue; - _container.Insert(partEnt, machine.PartContainer); - machine.Progress[part.PartType]++; + machineParts.Add((item, part)); + _container.RemoveEntity(uid, item); + machine.MachinePartProgress[part.PartType]--; + } + + machineParts.Sort((x, y) => y.Comp.Rating.CompareTo(x.Comp.Rating)); + + var updatedParts = new List>(); + foreach (var (machinePartId, amount) in macBoardComp.MachinePartRequirements) + { + var target = machineParts.Where(p => p.Comp.PartType == machinePartId).Take(amount); + updatedParts.AddRange(target); + } + + foreach (var pair in updatedParts) + { + if (!machine.MachinePartRequirements.ContainsKey(pair.Comp.PartType)) + continue; + + _container.Insert(pair.Owner, machine.PartContainer); + machine.MachinePartProgress[pair.Comp.PartType]++; machineParts.Remove(pair); } //put the unused parts back into rped. (this also does the "swapping") foreach (var (unused, _) in machineParts) - { _storage.Insert(storageEnt, unused, out _, playSound: false); - } } private void OnAfterInteract(EntityUid uid, PartExchangerComponent component, AfterInteractEvent args) { - if (component.DoDistanceCheck && !args.CanReach) - return; - - if (args.Target == null) - return; - - if (!HasComp(args.Target) && !HasComp(args.Target)) + if (component.DoDistanceCheck && !args.CanReach + || args.Target == null + || !HasComp(args.Target) && !HasComp(args.Target)) return; if (TryComp(args.Target, out var panel) && !panel.Open) { - _popup.PopupEntity(Loc.GetString("construction-step-condition-wire-panel-open"), - args.Target.Value); + _popup.PopupEntity(Loc.GetString("construction-step-condition-wire-panel-open"), args.Target.Value); return; } - var audioStream = _audio.PlayPvs(component.ExchangeSound, uid); + component.AudioStream = _audio.PlayPvs(component.ExchangeSound, uid)?.Entity; - if (audioStream == null) - return; - - component.AudioStream = audioStream!.Value.Entity; - - _doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, component.ExchangeDuration, new ExchangerDoAfterEvent(), uid, target: args.Target, used: uid) + var doAfter = new DoAfterArgs( + EntityManager, + args.User, + component.ExchangeDuration, + new ExchangerDoAfterEvent(), + uid, + target: args.Target, + used: uid) { BreakOnDamage = true, BreakOnMove = true - }); + }; + + _doAfter.TryStartDoAfter(doAfter); } } diff --git a/Content.Server/Power/Components/UpgradePowerDrawComponent.cs b/Content.Server/Power/Components/UpgradePowerDrawComponent.cs index 23db4905cc..39d2949d84 100644 --- a/Content.Server/Power/Components/UpgradePowerDrawComponent.cs +++ b/Content.Server/Power/Components/UpgradePowerDrawComponent.cs @@ -37,5 +37,3 @@ public sealed partial class UpgradePowerDrawComponent : Component [DataField(required: true), ViewVariables(VVAccess.ReadWrite)] public MachineUpgradeScalingType Scaling; } - - diff --git a/Content.Server/Stack/StackSystem.cs b/Content.Server/Stack/StackSystem.cs index e34592b45f..bac789716c 100644 --- a/Content.Server/Stack/StackSystem.cs +++ b/Content.Server/Stack/StackSystem.cs @@ -71,6 +71,15 @@ namespace Content.Server.Stack return entity; } + /// + /// Spawns a stack of a certain stack type. See . + /// + public EntityUid Spawn(int amount, ProtoId id, EntityCoordinates spawnPosition) + { + var proto = _prototypeManager.Index(id); + return Spawn(amount, proto, spawnPosition); + } + /// /// Spawns a stack of a certain stack type. See . /// diff --git a/Content.Shared/Construction/Components/MachineBoardComponent.cs b/Content.Shared/Construction/Components/MachineBoardComponent.cs index dbca316061..ea5c65e768 100644 --- a/Content.Shared/Construction/Components/MachineBoardComponent.cs +++ b/Content.Shared/Construction/Components/MachineBoardComponent.cs @@ -1,54 +1,54 @@ using Content.Shared.Construction.Prototypes; using Content.Shared.Stacks; +using Content.Shared.Tag; using Robust.Shared.GameStates; using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary; -namespace Content.Shared.Construction.Components +namespace Content.Shared.Construction.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class MachineBoardComponent : Component { - [RegisterComponent, NetworkedComponent] - public sealed partial class MachineBoardComponent : Component - { - [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + /// + /// Machine parts needed to construct this machine + /// + [DataField] + public Dictionary, int> MachinePartRequirements = new(); - [DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer))] - public Dictionary Requirements = new(); + /// + /// The stacks needed to construct this machine + /// + [DataField] + public Dictionary, int> StackRequirements = new(); - [DataField("materialRequirements")] - public Dictionary MaterialIdRequirements = new(); + /// + /// Entities needed to construct this machine, discriminated by tag. + /// + [DataField] + public Dictionary, GenericPartInfo> TagRequirements = new(); - [DataField("tagRequirements")] - public Dictionary TagRequirements = new(); + /// + /// Entities needed to construct this machine, discriminated by component. + /// + [DataField] + public Dictionary ComponentRequirements = new(); - [DataField("componentRequirements")] - public Dictionary ComponentRequirements = new(); - - [ViewVariables(VVAccess.ReadWrite)] - [DataField("prototype")] - public string? Prototype { get; private set; } - - public IEnumerable> MaterialRequirements - { - get - { - foreach (var (materialId, amount) in MaterialIdRequirements) - { - var material = _prototypeManager.Index(materialId); - yield return new KeyValuePair(material, amount); - } - } - } - } - - [Serializable] - [DataDefinition] - public partial struct GenericPartInfo - { - [DataField("Amount")] - public int Amount; - [DataField("ExamineName")] - public string ExamineName; - [DataField("DefaultPrototype")] - public string DefaultPrototype; - } + /// + /// The machine that's constructed when this machine board is completed. + /// + [DataField(required: true)] + public EntProtoId Prototype; +} + +[DataDefinition, Serializable] +public partial struct GenericPartInfo +{ + [DataField(required: true)] + public int Amount; + + [DataField(required: true)] + public EntProtoId DefaultPrototype; + + [DataField] + public LocId? ExamineName; } diff --git a/Content.Shared/Construction/Components/MachinePartComponent.cs b/Content.Shared/Construction/Components/MachinePartComponent.cs index a68e3495e2..efa2b735b5 100644 --- a/Content.Shared/Construction/Components/MachinePartComponent.cs +++ b/Content.Shared/Construction/Components/MachinePartComponent.cs @@ -1,24 +1,15 @@ using Content.Shared.Construction.Prototypes; using Robust.Shared.GameStates; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Prototypes; -namespace Content.Shared.Construction.Components +namespace Content.Shared.Construction.Components; + +[RegisterComponent, NetworkedComponent] +public sealed partial class MachinePartComponent : Component { - [RegisterComponent, NetworkedComponent] - public sealed partial class MachinePartComponent : Component - { - [DataField("part", required: true, customTypeSerializer: typeof(PrototypeIdSerializer))] - public string PartType { get; private set; } = default!; + [DataField(required: true)] + public ProtoId PartType; - [ViewVariables(VVAccess.ReadWrite)] - [DataField("rating")] - public int Rating { get; private set; } = 1; - - /// - /// This number is used in tests to ensure that you can't use high quality machines for arbitrage. In - /// principle there is nothing wrong with using higher quality parts, but you have to be careful to not - /// allow them to be put into a lathe or something like that. - /// - public const int MaxRating = 4; - } + [DataField] + public int Rating = 1; } diff --git a/Content.Shared/Construction/MachinePartSystem.cs b/Content.Shared/Construction/MachinePartSystem.cs index c19e1390c4..51caedef22 100644 --- a/Content.Shared/Construction/MachinePartSystem.cs +++ b/Content.Shared/Construction/MachinePartSystem.cs @@ -1,10 +1,8 @@ using System.Linq; using Content.Shared.Construction.Components; -using Content.Shared.Construction.Prototypes; using Content.Shared.Examine; using Content.Shared.Lathe; using Content.Shared.Materials; -using Content.Shared.Stacks; using Robust.Shared.Prototypes; namespace Content.Shared.Construction @@ -16,6 +14,7 @@ namespace Content.Shared.Construction { [Dependency] private readonly IPrototypeManager _prototype = default!; [Dependency] private readonly SharedLatheSystem _lathe = default!; + [Dependency] private readonly SharedConstructionSystem _construction = default!; public override void Initialize() { @@ -32,32 +31,39 @@ namespace Content.Shared.Construction using (args.PushGroup(nameof(MachineBoardComponent))) { args.PushMarkup(Loc.GetString("machine-board-component-on-examine-label")); - foreach (var (part, amount) in component.Requirements) + foreach (var (machinePartId, amount) in component.MachinePartRequirements) { + var machinePart = _prototype.Index(machinePartId); + args.PushMarkup(Loc.GetString("machine-board-component-required-element-entry-text", ("amount", amount), - ("requiredElement", Loc.GetString(_prototype.Index(part).Name)))); + ("requiredElement", Loc.GetString(machinePart.Name)))); } - foreach (var (material, amount) in component.MaterialRequirements) + foreach (var (material, amount) in component.StackRequirements) { + var stack = _prototype.Index(material); + var name = _prototype.Index(stack.Spawn).Name; + args.PushMarkup(Loc.GetString("machine-board-component-required-element-entry-text", ("amount", amount), - ("requiredElement", Loc.GetString(material.Name)))); + ("requiredElement", Loc.GetString(name)))); } foreach (var (_, info) in component.ComponentRequirements) { + var examineName = _construction.GetExamineName(info); args.PushMarkup(Loc.GetString("machine-board-component-required-element-entry-text", ("amount", info.Amount), - ("requiredElement", Loc.GetString(info.ExamineName)))); + ("requiredElement", examineName))); } foreach (var (_, info) in component.TagRequirements) { + var examineName = _construction.GetExamineName(info); args.PushMarkup(Loc.GetString("machine-board-component-required-element-entry-text", ("amount", info.Amount), - ("requiredElement", Loc.GetString(info.ExamineName)))); + ("requiredElement", examineName))); } } } @@ -71,8 +77,8 @@ namespace Content.Shared.Construction { args.PushMarkup(Loc.GetString("machine-part-component-on-examine-rating-text", ("rating", component.Rating))); - args.PushMarkup(Loc.GetString("machine-part-component-on-examine-type-text", ("type", - Loc.GetString(_prototype.Index(component.PartType).Name)))); + args.PushMarkup(Loc.GetString("machine-part-component-on-examine-type-text", + ("type", Loc.GetString(_prototype.Index(component.PartType).Name)))); } } @@ -81,11 +87,11 @@ namespace Content.Shared.Construction var (_, comp) = entity; var materials = new Dictionary(); - foreach (var (partId, amount) in comp.Requirements) + foreach (var (machinePartId, amount) in comp.MachinePartRequirements) { - var partProto = _prototype.Index(partId); + var machinePart = _prototype.Index(machinePartId); - if (!_lathe.TryGetRecipesFromEntity(partProto.StockPartPrototype, out var recipes)) + if (!_lathe.TryGetRecipesFromEntity(machinePart.StockPartPrototype, out var recipes)) continue; var partRecipe = recipes[0]; @@ -99,11 +105,12 @@ namespace Content.Shared.Construction } } - foreach (var (stackId, amount) in comp.MaterialIdRequirements) + foreach (var (stackId, amount) in comp.StackRequirements) { - var stackProto = _prototype.Index(stackId); - if (_prototype.TryIndex(stackProto.Spawn, out var defaultProto) && - defaultProto.TryGetComponent(out var physComp)) + var stackProto = _prototype.Index(stackId); + var defaultProto = _prototype.Index(stackProto.Spawn); + + if (defaultProto.TryGetComponent(out var physComp, EntityManager.ComponentFactory)) { foreach (var (mat, matAmount) in physComp.MaterialComposition) { @@ -144,7 +151,7 @@ namespace Content.Shared.Construction } } else if (_prototype.TryIndex(defaultProtoId, out var defaultProto) && - defaultProto.TryGetComponent(out var physComp)) + defaultProto.TryGetComponent(out var physComp, EntityManager.ComponentFactory)) { foreach (var (mat, matAmount) in physComp.MaterialComposition) { diff --git a/Content.Shared/Construction/Prototypes/MachinePartPrototype.cs b/Content.Shared/Construction/Prototypes/MachinePartPrototype.cs index 7a080c94a3..06be733726 100644 --- a/Content.Shared/Construction/Prototypes/MachinePartPrototype.cs +++ b/Content.Shared/Construction/Prototypes/MachinePartPrototype.cs @@ -1,5 +1,5 @@ -using Robust.Shared.Prototypes; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Content.Shared.Construction.Components; +using Robust.Shared.Prototypes; namespace Content.Shared.Construction.Prototypes; @@ -10,19 +10,18 @@ namespace Content.Shared.Construction.Prototypes; [Prototype("machinePart")] public sealed partial class MachinePartPrototype : IPrototype { - /// [IdDataField] public string ID { get; private set; } = default!; /// /// A human-readable name for the machine part type. /// - [DataField("name")] - public string Name = string.Empty; + [DataField(required: true)] + public LocId Name; /// /// A stock part entity based on the machine part. /// - [DataField("stockPartPrototype", customTypeSerializer: typeof(PrototypeIdSerializer), required: true)] - public string StockPartPrototype = string.Empty; + [DataField(required: true)] + public EntProtoId StockPartPrototype = string.Empty; } diff --git a/Content.Shared/Construction/SharedConstructionSystem.cs b/Content.Shared/Construction/SharedConstructionSystem.cs index 069290d143..901b2f834d 100644 --- a/Content.Shared/Construction/SharedConstructionSystem.cs +++ b/Content.Shared/Construction/SharedConstructionSystem.cs @@ -1,5 +1,7 @@ using System.Linq; +using Content.Shared.Construction.Components; using Robust.Shared.Map; +using Robust.Shared.Prototypes; using static Content.Shared.Interaction.SharedInteractionSystem; namespace Content.Shared.Construction @@ -7,6 +9,7 @@ namespace Content.Shared.Construction public abstract class SharedConstructionSystem : EntitySystem { [Dependency] private readonly IMapManager _mapManager = default!; + [Dependency] protected readonly IPrototypeManager PrototypeManager = default!; /// /// Get predicate for construction obstruction checks. @@ -22,5 +25,13 @@ namespace Content.Shared.Construction var ignored = grid.GetAnchoredEntities(coords).ToHashSet(); return e => ignored.Contains(e); } + + public string GetExamineName(GenericPartInfo info) + { + if (info.ExamineName is not null) + return Loc.GetString(info.ExamineName.Value); + + return PrototypeManager.Index(info.DefaultPrototype).Name; + } } } diff --git a/Content.Shared/Construction/SharedFlatpackSystem.cs b/Content.Shared/Construction/SharedFlatpackSystem.cs index 8b21bca52a..62d2089fb7 100644 --- a/Content.Shared/Construction/SharedFlatpackSystem.cs +++ b/Content.Shared/Construction/SharedFlatpackSystem.cs @@ -1,4 +1,3 @@ -using System.Numerics; using Content.Shared.Construction.Components; using Content.Shared.Administration.Logs; using Content.Shared.Database; @@ -9,7 +8,6 @@ using Content.Shared.Popups; using Content.Shared.Tools.Systems; using Robust.Shared.Audio.Systems; using Robust.Shared.Containers; -using Robust.Shared.Map; using Robust.Shared.Map.Components; using Robust.Shared.Network; using Robust.Shared.Physics.Components; @@ -88,7 +86,8 @@ public abstract class SharedFlatpackSystem : EntitySystem if (_net.IsServer) { var spawn = Spawn(comp.Entity, _map.GridTileToLocal(grid, gridComp, buildPos)); - _adminLogger.Add(LogType.Construction, LogImpact.Low, + _adminLogger.Add(LogType.Construction, + LogImpact.Low, $"{ToPrettyString(args.User):player} unpacked {ToPrettyString(spawn):entity} at {xform.Coordinates} from {ToPrettyString(uid):entity}"); QueueDel(uid); } @@ -115,9 +114,7 @@ public abstract class SharedFlatpackSystem : EntitySystem return; var machinePrototypeId = new EntProtoId(); - if (TryComp(board, out var machineBoard) && machineBoard.Prototype is not null) - machinePrototypeId = machineBoard.Prototype; - else if (TryComp(board, out var computerBoard) && computerBoard.Prototype is not null) + if (TryComp(board, out var computerBoard) && computerBoard.Prototype is not null) machinePrototypeId = computerBoard.Prototype; var comp = ent.Comp!; diff --git a/Content.Shared/Lathe/LatheComponent.cs b/Content.Shared/Lathe/LatheComponent.cs index ab3d59b642..9f609bab31 100644 --- a/Content.Shared/Lathe/LatheComponent.cs +++ b/Content.Shared/Lathe/LatheComponent.cs @@ -68,8 +68,6 @@ namespace Content.Shared.Lathe /// [DataField, ViewVariables(VVAccess.ReadWrite), AutoNetworkedField] public float MaterialUseMultiplier = 1; - - public const float DefaultPartRatingMaterialUseMultiplier = 0.85f; #endregion } diff --git a/Resources/Locale/en-US/construction/steps/arbitrary-insert-construction-graph-step.ftl b/Resources/Locale/en-US/construction/steps/arbitrary-insert-construction-graph-step.ftl index 0f5f87e694..a9f6fa38a8 100644 --- a/Resources/Locale/en-US/construction/steps/arbitrary-insert-construction-graph-step.ftl +++ b/Resources/Locale/en-US/construction/steps/arbitrary-insert-construction-graph-step.ftl @@ -1,5 +1,11 @@ # Shown when examining an in-construction object construction-insert-arbitrary-entity = Next, insert {$stepName}. +construction-insert-info-examine-name-instrument-brass = brass instrument +construction-insert-info-examine-name-instrument-keyed = keyed instrument +construction-insert-info-examine-name-instrument-percussion = percussion instrument +construction-insert-info-examine-name-instrument-string = string intrument +construction-insert-info-examine-name-instrument-woodwind = woodwind instrument +construction-insert-info-examine-name-knife = knife +construction-insert-info-examine-name-utensil = utensil construction-insert-info-examine-name-laser-cannon = high power laser weapon -construction-insert-info-examine-name-power-cell = power cell \ No newline at end of file diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/cannons.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/cannons.yml index c269906a29..959979b967 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/cannons.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/cannons.yml @@ -11,7 +11,7 @@ state: security - type: MachineBoard prototype: ShuttleGunSvalinnMachineGun - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 4 materialRequirements: @@ -33,7 +33,7 @@ state: security - type: MachineBoard prototype: ShuttleGunPerforator - requirements: + machinePartRequirements: MatterBin: 4 Manipulator: 6 materialRequirements: @@ -55,7 +55,7 @@ state: security - type: MachineBoard prototype: ShuttleGunFriendship - requirements: + machinePartRequirements: MatterBin: 3 Manipulator: 2 materialRequirements: @@ -77,7 +77,7 @@ state: security - type: MachineBoard prototype: ShuttleGunDuster - requirements: + machinePartRequirements: MatterBin: 6 Manipulator: 4 materialRequirements: @@ -100,7 +100,7 @@ state: security - type: MachineBoard prototype: ShuttleGunKinetic - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 3 materialRequirements: diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/particle_accelerator.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/particle_accelerator.yml index 1e3d28ceb6..f1b03f97c2 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/particle_accelerator.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/particle_accelerator.yml @@ -8,7 +8,7 @@ state: engineering - type: MachineBoard prototype: ParticleAcceleratorEndCapUnfinished - materialRequirements: + stackRequirements: Glass: 15 Steel: 15 @@ -24,10 +24,9 @@ prototype: ParticleAcceleratorFuelChamberUnfinished componentRequirements: AmeFuelContainer: - Amount: 1 - DefaultPrototype: AmeJar - ExamineName: AME Fuel Jar - materialRequirements: + amount: 1 + defaultPrototype: AmeJar + stackRequirements: Glass: 10 Steel: 10 @@ -41,7 +40,7 @@ state: engineering - type: MachineBoard prototype: ParticleAcceleratorPowerBoxUnfinished - materialRequirements: + stackRequirements: Glass: 5 Steel: 5 @@ -57,7 +56,7 @@ state: engineering - type: MachineBoard prototype: ParticleAcceleratorEmitterStarboardUnfinished - materialRequirements: + stackRequirements: Glass: 5 Steel: 5 @@ -71,7 +70,7 @@ state: engineering - type: MachineBoard prototype: ParticleAcceleratorEmitterForeUnfinished - materialRequirements: + stackRequirements: Glass: 5 Steel: 5 @@ -85,6 +84,6 @@ state: engineering - type: MachineBoard prototype: ParticleAcceleratorEmitterPortUnfinished - materialRequirements: + stackRequirements: Glass: 5 Steel: 5 diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml index 9c4db0028b..4949e61cdd 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -6,7 +6,7 @@ components: - type: MachineBoard prototype: Autolathe - requirements: + machinePartRequirements: MatterBin: 3 Manipulator: 1 materialRequirements: @@ -20,15 +20,14 @@ components: - type: MachineBoard prototype: AutolatheHyperConvection - requirements: + machinePartRequirements: MatterBin: 3 materialRequirements: Glass: 1 tagRequirements: Igniter: - Amount: 1 - DefaultPrototype: Igniter - ExamineName: Igniter + amount: 1 + defaultPrototype: Igniter - type: ReverseEngineering # Delta difficulty: 2 recipes: @@ -42,14 +41,13 @@ components: - type: MachineBoard prototype: Protolathe - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: entity parent: BaseMachineCircuitboard @@ -59,17 +57,15 @@ components: - type: MachineBoard prototype: ProtolatheHyperConvection - requirements: + machinePartRequirements: MatterBin: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker Igniter: - Amount: 1 - DefaultPrototype: Igniter - ExamineName: Igniter + amount: 1 + defaultPrototype: Igniter - type: ReverseEngineering # Delta difficulty: 2 recipes: @@ -83,7 +79,7 @@ components: - type: MachineBoard prototype: Biofabricator - requirements: + machinePartRequirements: MatterBin: 4 materialRequirements: Glass: 1 @@ -102,14 +98,13 @@ state: security - type: MachineBoard prototype: SecurityTechFab - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: entity id: AmmoTechFabCircuitboard @@ -121,7 +116,7 @@ state: security - type: MachineBoard prototype: AmmoTechFab - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 1 @@ -135,14 +130,13 @@ state: medical - type: MachineBoard prototype: MedicalTechFab - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: StealTarget stealGroup: MedicalTechFabCircuitboard @@ -155,14 +149,13 @@ state: science - type: MachineBoard prototype: CircuitImprinter - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 1 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: entity parent: BaseMachineCircuitboard @@ -174,17 +167,15 @@ state: science - type: MachineBoard prototype: CircuitImprinterHyperConvection - requirements: + machinePartRequirements: MatterBin: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker Igniter: - Amount: 1 - DefaultPrototype: Igniter - ExamineName: Igniter + amount: 1 + defaultPrototype: Igniter - type: entity id: ExosuitFabricatorMachineCircuitboard @@ -195,7 +186,7 @@ state: science - type: MachineBoard prototype: ExosuitFabricator - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 3 materialRequirements: @@ -229,7 +220,7 @@ components: - type: MachineBoard prototype: UniformPrinter - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 2 @@ -242,16 +233,15 @@ state: medical - type: MachineBoard prototype: Vaccinator - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 1 materialRequirements: Cable: 5 tagRequirements: GlassBeaker: - Amount: 1 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 1 + defaultPrototype: Beaker - type: ReverseEngineering # Nyano difficulty: 2 recipes: @@ -270,14 +260,12 @@ Cable: 5 tagRequirements: GlassBeaker: - Amount: 1 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 1 + defaultPrototype: Beaker componentRequirements: - DiseaseSwab: - Amount: 1 - DefaultPrototype: DiseaseSwab - ExamineName: Swab + BotanySwab: + amount: 1 + defaultPrototype: DiseaseSwab - type: ReverseEngineering # Nyano difficulty: 2 recipes: @@ -293,7 +281,7 @@ state: science - type: MachineBoard prototype: MachineArtifactAnalyzer - requirements: + machinePartRequirements: Manipulator: 3 Capacitor: 1 materialRequirements: @@ -313,7 +301,7 @@ state: science - type: MachineBoard prototype: MachineArtifactCrusher - requirements: + machinePartRequirements: Manipulator: 2 materialRequirements: Glass: 1 @@ -333,7 +321,7 @@ state: science - type: MachineBoard prototype: MachineAnomalyVessel - requirements: + machinePartRequirements: Capacitor: 3 materialRequirements: Cable: 1 @@ -353,7 +341,7 @@ state: science - type: MachineBoard prototype: MachineAnomalyVesselExperimental - requirements: + machinePartRequirements: Capacitor: 3 materialRequirements: Cable: 5 @@ -374,7 +362,7 @@ state: science - type: MachineBoard prototype: MachineAnomalySynchronizer - requirements: + machinePartRequirements: Manipulator: 2 Capacitor: 5 materialRequirements: @@ -395,7 +383,7 @@ state: science - type: MachineBoard prototype: MachineAPE - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Cable: 1 @@ -415,7 +403,7 @@ state: engineering - type: MachineBoard prototype: GasThermoMachineFreezer - requirements: + machinePartRequirements: MatterBin: 2 Capacitor: 2 materialRequirements: @@ -439,7 +427,7 @@ state: engineering - type: MachineBoard prototype: GasThermoMachineHeater - requirements: + machinePartRequirements: MatterBin: 2 Capacitor: 2 materialRequirements: @@ -459,7 +447,7 @@ state: engineering - type: MachineBoard prototype: GasThermoMachineHellfireFreezer - requirements: + machinePartRequirements: MatterBin: 2 Capacitor: 2 materialRequirements: @@ -483,7 +471,7 @@ state: engineering - type: MachineBoard prototype: GasThermoMachineHellfireHeater - requirements: + machinePartRequirements: MatterBin: 2 Capacitor: 2 materialRequirements: @@ -503,7 +491,7 @@ state: engineering - type: MachineBoard prototype: BaseGasCondenser - requirements: + machinePartRequirements: MatterBin: 1 materialRequirements: Glass: 1 @@ -518,7 +506,7 @@ state: engineering - type: MachineBoard prototype: PortableScrubber - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 2 materialRequirements: @@ -538,7 +526,7 @@ state: engineering - type: MachineBoard prototype: SpaceHeater - requirements: + machinePartRequirements: MatterBin: 1 Capacitor: 2 materialRequirements: @@ -554,7 +542,7 @@ state: medical - type: MachineBoard prototype: CloningPod - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 materialRequirements: @@ -575,7 +563,7 @@ state: medical - type: MachineBoard prototype: MetempsychoticMachine - requirements: + machinePartRequirements: Capacitor: 2 Manipulator: 2 materialRequirements: @@ -596,7 +584,7 @@ state: medical - type: MachineBoard prototype: MedicalScanner - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Glass: 5 @@ -646,16 +634,15 @@ state: medical - type: MachineBoard prototype: ChemMaster - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Glass: 1 Cable: 1 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: entity id: ChemDispenserMachineCircuitboard @@ -667,16 +654,15 @@ state: medical - type: MachineBoard prototype: ChemDispenserEmpty - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Glass: 1 Steel: 3 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: entity id: BiomassReclaimerMachineCircuitboard @@ -686,14 +672,14 @@ components: - type: MachineBoard prototype: BiomassReclaimer - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 1 tagRequirements: Knife: - Amount: 2 - DefaultPrototype: KitchenKnife - ExamineName: Knife + amount: 2 + defaultPrototype: KitchenKnife + examineName: construction-insert-info-examine-name-knife materialRequirements: Steel: 5 - type: ReverseEngineering # Nyano @@ -717,9 +703,8 @@ Cable: 2 tagRequirements: GlassBeaker: - Amount: 2 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 2 + defaultPrototype: Beaker - type: ReverseEngineering # Nyano difficulty: 2 recipes: @@ -735,7 +720,7 @@ state: service - type: MachineBoard prototype: SeedExtractor - requirements: + machinePartRequirements: Manipulator: 2 Capacitor: 1 materialRequirements: @@ -758,7 +743,7 @@ state: power_mod - type: MachineBoard prototype: SMESBasicEmpty - requirements: + machinePartRequirements: Capacitor: 1 PowerCell: 4 materialRequirements: @@ -775,7 +760,7 @@ state: power_mod - type: MachineBoard prototype: SMESAdvancedEmpty - requirements: + machinePartRequirements: Capacitor: 2 PowerCell: 4 materialRequirements: @@ -792,7 +777,7 @@ state: charger_APC - type: MachineBoard prototype: PowerCellRecharger - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Cable: 5 @@ -814,7 +799,7 @@ state: charger_APC - type: MachineBoard prototype: PowerCageRecharger - requirements: + machinePartRequirements: Capacitor: 4 materialRequirements: Steel: 5 @@ -837,7 +822,7 @@ state: charger_APC - type: MachineBoard prototype: BorgCharger - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Cable: 5 @@ -859,7 +844,7 @@ state: charger_APC - type: MachineBoard prototype: WeaponCapacitorRecharger - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: CableMV: 5 @@ -881,7 +866,7 @@ state: charger_APC - type: MachineBoard prototype: TurboItemRecharger - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: CableMV: 5 @@ -902,7 +887,7 @@ components: - type: MachineBoard prototype: SubstationBasicEmpty - requirements: + machinePartRequirements: Capacitor: 1 PowerCell: 1 materialRequirements: @@ -929,25 +914,25 @@ tagRequirements: # One instrument to bring them all and in the darkness bind them... KeyedInstrument: - Amount: 1 - DefaultPrototype: SynthesizerInstrument - ExamineName: Keyed Instrument + amount: 1 + defaultPrototype: SynthesizerInstrument + examineName: construction-insert-info-examine-name-instrument-keyed StringInstrument: - Amount: 1 - DefaultPrototype: AcousticGuitarInstrument - ExamineName: String Instrument + amount: 1 + defaultPrototype: AcousticGuitarInstrument + examineName: construction-insert-info-examine-name-instrument-string PercussionInstrument: - Amount: 1 - DefaultPrototype: GlockenspielInstrument - ExamineName: Percussion Instrument + amount: 1 + defaultPrototype: GlockenspielInstrument + examineName: construction-insert-info-examine-name-instrument-percussion BrassInstrument: - Amount: 1 - DefaultPrototype: TrumpetInstrument - ExamineName: Brass Instrument + amount: 1 + defaultPrototype: TrumpetInstrument + examineName: construction-insert-info-examine-name-instrument-brass WoodwindInstrument: - Amount: 1 - DefaultPrototype: SaxophoneInstrument - ExamineName: Woodwind Instrument + amount: 1 + defaultPrototype: SaxophoneInstrument + examineName: construction-insert-info-examine-name-instrument-woodwind - type: ReverseEngineering # Nyano difficulty: 2 recipes: @@ -962,7 +947,7 @@ state: engineering - type: MachineBoard prototype: PortableGeneratorPacman - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: CableHV: 5 @@ -985,7 +970,7 @@ components: - type: MachineBoard prototype: Thruster - requirements: + machinePartRequirements: Capacitor: 4 materialRequirements: Steel: 5 @@ -1001,7 +986,7 @@ components: - type: MachineBoard prototype: Gyroscope - requirements: + machinePartRequirements: Manipulator: 2 Capacitor: 1 materialRequirements: @@ -1020,7 +1005,7 @@ state: engineering - type: MachineBoard prototype: PortableGeneratorSuperPacman - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: CableHV: 10 @@ -1045,7 +1030,7 @@ state: engineering - type: MachineBoard prototype: PortableGeneratorJrPacman - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Cable: 10 @@ -1069,14 +1054,13 @@ components: - type: MachineBoard prototype: KitchenReagentGrinder - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 tagRequirements: GlassBeaker: - Amount: 1 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 1 + defaultPrototype: Beaker - type: ReverseEngineering # Nyano difficulty: 2 recipes: @@ -1090,7 +1074,7 @@ components: - type: MachineBoard prototype: ChemistryHotplate - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Glass: 1 @@ -1107,7 +1091,7 @@ components: - type: MachineBoard prototype: KitchenElectricGrill - requirements: + machinePartRequirements: Capacitor: 4 materialRequirements: Glass: 2 @@ -1126,7 +1110,7 @@ state: medical - type: MachineBoard prototype: StasisBed - requirements: + machinePartRequirements: Capacitor: 1 Manipulator: 1 materialRequirements: @@ -1147,7 +1131,7 @@ state: medical - type: MachineBoard prototype: MachineElectrolysisUnit - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Cable: 1 @@ -1162,7 +1146,7 @@ state: medical - type: MachineBoard prototype: MachineCentrifuge - requirements: + machinePartRequirements: Manipulator: 1 materialRequirements: Steel: 1 @@ -1176,7 +1160,7 @@ state: supply - type: MachineBoard prototype: MaterialReclaimer - requirements: + machinePartRequirements: Manipulator: 2 materialRequirements: Steel: 5 @@ -1195,7 +1179,7 @@ state: supply - type: MachineBoard prototype: OreProcessor - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 3 materialRequirements: @@ -1210,7 +1194,7 @@ state: supply - type: MachineBoard prototype: OreProcessorIndustrial - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 3 materialRequirements: @@ -1227,7 +1211,7 @@ components: - type: MachineBoard prototype: Sheetifier - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 1 @@ -1240,7 +1224,7 @@ state: service - type: MachineBoard prototype: KitchenMicrowave - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Glass: 2 @@ -1258,7 +1242,7 @@ state: service - type: MachineBoard prototype: SyndicateMicrowave - requirements: + machinePartRequirements: Capacitor: 1 materialRequirements: Glass: 2 @@ -1273,13 +1257,13 @@ state: service - type: MachineBoard prototype: FatExtractor - requirements: + machinePartRequirements: Manipulator: 1 componentRequirements: Utensil: - Amount: 1 - DefaultPrototype: ForkPlastic - ExamineName: Utensil + amount: 1 + defaultPrototype: ForkPlastic + examineName: construction-insert-info-examine-name-utensil - type: ReverseEngineering # Delta difficulty: 2 recipes: @@ -1292,7 +1276,7 @@ components: - type: MachineBoard prototype: MachineFlatpacker - requirements: + machinePartRequirements: Manipulator: 2 MatterBin: 1 materialRequirements: @@ -1311,7 +1295,7 @@ state: engineering - type: MachineBoard prototype: Emitter - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: CableHV: 5 @@ -1392,7 +1376,7 @@ components: - type: MachineBoard prototype: GasRecycler - requirements: + machinePartRequirements: Capacitor: 1 Manipulator: 1 materialRequirements: @@ -1417,9 +1401,8 @@ Steel: 5 tagRequirements: GlassBeaker: - Amount: 1 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 1 + defaultPrototype: Beaker - type: entity id: CargoTelepadMachineCircuitboard @@ -1431,7 +1414,7 @@ state: supply - type: MachineBoard prototype: CargoTelepad - requirements: + machinePartRequirements: Capacitor: 2 materialRequirements: Steel: 5 @@ -1455,9 +1438,8 @@ Steel: 5 tagRequirements: GlassBeaker: - Amount: 1 - DefaultPrototype: Beaker - ExamineName: Glass Beaker + amount: 1 + defaultPrototype: Beaker - type: entity id: TelecomServerCircuitboard @@ -1482,7 +1464,7 @@ components: - type: MachineBoard prototype: SalvageMagnet - requirements: + machinePartRequirements: Capacitor: 4 materialRequirements: Steel: 5 @@ -1500,7 +1482,7 @@ components: - type: MachineBoard prototype: GravityGeneratorMini - requirements: + machinePartRequirements: Capacitor: 4 MatterBin: 3 materialRequirements: @@ -1520,7 +1502,7 @@ components: - type: MachineBoard prototype: StationAnchor - requirements: + machinePartRequirements: Capacitor: 4 MatterBin: 3 materialRequirements: @@ -1536,7 +1518,7 @@ components: - type: MachineBoard prototype: ReagentGrinderIndustrial - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 3 materialRequirements: @@ -1591,7 +1573,7 @@ state: supply - type: MachineBoard prototype: MaterialSilo - requirements: + machinePartRequirements: MatterBin: 10 materialRequirements: Steel: 5 @@ -1606,6 +1588,6 @@ components: - type: MachineBoard prototype: BookPress - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 2 diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/turrets.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/turrets.yml index b6ee73a550..518e442024 100644 --- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/turrets.yml +++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/Machine/turrets.yml @@ -8,17 +8,16 @@ state: security - type: MachineBoard prototype: WeaponEnergyTurretStation - requirements: + machinePartRequirements: PowerCell: 1 tagRequirements: TurretCompatibleWeapon: - Amount: 1 - DefaultPrototype: WeaponLaserCannon - ExamineName: Laser Cannon + amount: 1 + defaultPrototype: WeaponLaserCannon + examineName: construction-insert-info-examine-name-laser-cannon ProximitySensor: - Amount: 1 - DefaultPrototype: ProximitySensor - ExamineName: Proximity Sensor + amount: 1 + defaultPrototype: ProximitySensor - type: entity id: WeaponEnergyTurretAIMachineCircuitboard @@ -29,4 +28,4 @@ - type: Sprite state: command - type: MachineBoard - prototype: WeaponEnergyTurretAI \ No newline at end of file + prototype: WeaponEnergyTurretAI diff --git a/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml b/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml index 173c2c043d..b843aca85e 100644 --- a/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml +++ b/Resources/Prototypes/Entities/Objects/Misc/machine_parts.yml @@ -1,4 +1,6 @@ -- type: entity +# Rating 1 + +- type: entity id: BaseStockPart name: stock part parent: BaseItem @@ -11,11 +13,11 @@ size: Tiny - type: Stack count: 1 - - type: PhysicalComposition #Goobstation - Recycle update + - type: PhysicalComposition materialComposition: Steel: 12 Plastic: 12 - - type: StockPart # Goobstation + - type: StockPart - type: entity id: CapacitorStockPart @@ -27,11 +29,11 @@ - type: Sprite state: capacitor - type: MachinePart - part: Capacitor + partType: Capacitor rating: 1 - - type: ReverseEngineering # Nyano + - type: ReverseEngineering recipes: - - CapacitorStockPart + - CapacitorStockPart - type: Tag tags: - CapacitorStockPart @@ -52,13 +54,13 @@ - type: Sprite state: micro_mani - type: MachinePart - part: Manipulator + partType: Manipulator rating: 1 - - type: Stack - stackType: MicroManipulator - - type: ReverseEngineering # Nyano + - type: ReverseEngineering recipes: - - MicroManipulatorStockPart + - MicroManipulatorStockPart + - type: Stack + stackType: Manipulator - type: entity id: MatterBinStockPart @@ -70,13 +72,13 @@ - type: Sprite state: matter_bin - type: MachinePart - part: MatterBin + partType: MatterBin rating: 1 + - type: ReverseEngineering + recipes: + - MatterBinStockPart - type: Stack stackType: MatterBin - - type: ReverseEngineering # Nyano - recipes: - - MatterBinStockPart # Rating 2 @@ -87,14 +89,16 @@ description: An advanced capacitor used in the construction of a variety of devices. suffix: Rating 2 components: - - type: Sprite - state: adv_capacitor - - type: MachinePart - rating: 2 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - AdvancedCapacitorStockPart + - type: Sprite + state: adv_capacitor + - type: MachinePart + rating: 2 + - type: ReverseEngineering + difficulty: 2 + recipes: + - AdvancedCapacitorStockPart + - type: Stack + stackType: AdvancedCapacitor - type: entity id: NanoManipulatorStockPart @@ -103,14 +107,16 @@ description: An advanced manipulator used in the construction of a variety of devices. suffix: Rating 2 components: - - type: Sprite - state: nano_mani - - type: MachinePart - rating: 2 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - NanoManipulatorStockPart + - type: Sprite + state: nano_mani + - type: MachinePart + rating: 2 + - type: ReverseEngineering + difficulty: 2 + recipes: + - NanoManipulatorStockPart + - type: Stack + stackType: AdvancedManipulator - type: entity id: AdvancedMatterBinStockPart @@ -119,14 +125,16 @@ description: An advanced matter bin used in the construction of a variety of devices. suffix: Rating 2 components: - - type: Sprite - state: advanced_matter_bin - - type: MachinePart - rating: 2 - - type: ReverseEngineering # Nyano - difficulty: 2 - recipes: - - AdvancedMatterBinStockPart + - type: Sprite + state: advanced_matter_bin + - type: MachinePart + rating: 2 + - type: ReverseEngineering + difficulty: 2 + recipes: + - AdvancedMatterBinStockPart + - type: Stack + stackType: AdvancedMatterBin # Rating 3 @@ -137,14 +145,16 @@ description: A super capacitor used in the construction of a variety of devices. suffix: Rating 3 components: - - type: Sprite - state: super_capacitor - - type: MachinePart - rating: 3 - - type: ReverseEngineering # Nyano - difficulty: 3 - recipes: - - SuperCapacitorStockPart + - type: Sprite + state: super_capacitor + - type: MachinePart + rating: 3 + - type: ReverseEngineering + difficulty: 3 + recipes: + - SuperCapacitorStockPart + - type: Stack + stackType: SuperCapacitor - type: entity id: PicoManipulatorStockPart @@ -153,14 +163,16 @@ description: A super manipulator used in the construction of a variety of devices. suffix: Rating 3 components: - - type: Sprite - state: pico_mani - - type: MachinePart - rating: 3 - - type: ReverseEngineering # Nyano - difficulty: 3 - recipes: - - PicoManipulatorStockPart + - type: Sprite + state: pico_mani + - type: MachinePart + rating: 3 + - type: ReverseEngineering + difficulty: 3 + recipes: + - PicoManipulatorStockPart + - type: Stack + stackType: SuperManipulator - type: entity id: SuperMatterBinStockPart @@ -169,14 +181,16 @@ description: A super matter bin used in the construction of a variety of devices. suffix: Rating 3 components: - - type: Sprite - state: super_matter_bin - - type: MachinePart - rating: 3 - - type: ReverseEngineering # Nyano - difficulty: 3 - recipes: - - SuperMatterBinStockPart + - type: Sprite + state: super_matter_bin + - type: MachinePart + rating: 3 + - type: ReverseEngineering + difficulty: 3 + recipes: + - SuperMatterBinStockPart + - type: Stack + stackType: SuperMatterBin # Rating 4 @@ -187,14 +201,16 @@ description: A bluespace capacitor used in the construction of a variety of devices. suffix: Rating 4 components: - - type: Sprite - state: quadratic_capacitor - - type: MachinePart - rating: 4 - - type: ReverseEngineering # Nyano - difficulty: 4 - recipes: - - BluespaceCapacitorStockPart + - type: Sprite + state: quadratic_capacitor + - type: MachinePart + rating: 4 + - type: ReverseEngineering + difficulty: 4 + recipes: + - BluespaceCapacitorStockPart + - type: Stack + stackType: BluespaceCapacitor - type: entity id: BluespaceManipulatorStockPart @@ -203,14 +219,16 @@ description: A bluespace manipulator used in the construction of a variety of devices. suffix: Rating 4 components: - - type: Sprite - state: femto_mani - - type: MachinePart - rating: 4 - - type: ReverseEngineering # Nyano - difficulty: 4 - recipes: - - BluespaceManipulatorStockPart + - type: Sprite + state: femto_mani + - type: MachinePart + rating: 4 + - type: ReverseEngineering + difficulty: 4 + recipes: + - BluespaceManipulatorStockPart + - type: Stack + stackType: BluespaceManipulator - type: entity id: BluespaceMatterBinStockPart @@ -219,11 +237,13 @@ description: A bluespace matter bin used in the construction of a variety of devices. suffix: Rating 4 components: - - type: Sprite - state: bluespace_matter_bin - - type: MachinePart - rating: 4 - - type: ReverseEngineering # Nyano - difficulty: 4 - recipes: - - BluespaceMatterBinStockPart + - type: Sprite + state: bluespace_matter_bin + - type: MachinePart + rating: 4 + - type: ReverseEngineering + difficulty: 4 + recipes: + - BluespaceMatterBinStockPart + - type: Stack + stackType: BluespaceMatterBin diff --git a/Resources/Prototypes/Entities/Objects/Power/powercells.yml b/Resources/Prototypes/Entities/Objects/Power/powercells.yml index 41535d254d..d5f77bbb28 100644 --- a/Resources/Prototypes/Entities/Objects/Power/powercells.yml +++ b/Resources/Prototypes/Entities/Objects/Power/powercells.yml @@ -74,7 +74,7 @@ maxCharge: 360 startingCharge: 360 - type: MachinePart - part: PowerCell + partType: PowerCell rating: 1 - type: Tag tags: @@ -115,7 +115,7 @@ maxCharge: 720 startingCharge: 720 - type: MachinePart - part: PowerCell + partType: PowerCell rating: 2 - type: entity @@ -153,7 +153,7 @@ maxCharge: 1080 startingCharge: 1080 - type: MachinePart - part: PowerCell + partType: PowerCell rating: 3 - type: entity @@ -191,7 +191,7 @@ maxCharge: 1800 startingCharge: 1800 - type: MachinePart - part: PowerCell + partType: PowerCell rating: 4 - type: entity diff --git a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml index 2ed4a594e3..bb5a85c868 100644 --- a/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml +++ b/Resources/Prototypes/Nyanotrasen/Entities/Objects/Devices/CircuitBoards/production.yml @@ -8,7 +8,7 @@ state: engineering - type: MachineBoard prototype: ReverseEngineeringMachine - requirements: + machinePartRequirements: MatterBin: 1 Manipulator: 1 materialRequirements: @@ -16,9 +16,8 @@ PlasmaGlass: 5 tagRequirements: BorgArm: - Amount: 3 - DefaultPrototype: LeftArmBorg - ExamineName: borg arm + amount: 3 + defaultPrototype: LeftArmBorg - type: ReverseEngineering difficulty: 3 recipes: @@ -33,7 +32,7 @@ state: service - type: MachineBoard prototype: KitchenDeepFryer - requirements: + machinePartRequirements: Capacitor: 1 MatterBin: 1 materialRequirements: @@ -53,7 +52,7 @@ state: supply - type: MachineBoard prototype: MailTeleporter - requirements: + machinePartRequirements: Capacitor: 1 MatterBin: 1 materialRequirements: diff --git a/Resources/Prototypes/Stacks/science_stacks.yml b/Resources/Prototypes/Stacks/science_stacks.yml index bf58fad915..ba6ddc386d 100644 --- a/Resources/Prototypes/Stacks/science_stacks.yml +++ b/Resources/Prototypes/Stacks/science_stacks.yml @@ -4,6 +4,10 @@ spawn: ArtifactFragment1 maxCount: 30 +# Machine Part + +# Rating 1 + - type: stack id: Capacitor name: capacitor @@ -11,8 +15,8 @@ maxCount: 10 - type: stack - id: MicroManipulator - name: micro manipulator + id: Manipulator + name: manipulator spawn: MicroManipulatorStockPart maxCount: 10 @@ -21,3 +25,63 @@ name: matter bin spawn: MatterBinStockPart maxCount: 10 + +# Rating 2 + +- type: stack + id: AdvancedCapacitor + name: advanced capacitor + spawn: AdvancedCapacitorStockPart + maxCount: 10 + +- type: stack + id: AdvancedManipulator + name: advanced manipulator + spawn: NanoManipulatorStockPart + maxCount: 10 + +- type: stack + id: AdvancedMatterBin + name: advanced matter bin + spawn: AdvancedMatterBinStockPart + maxCount: 10 + +# Rating 3 + +- type: stack + id: SuperCapacitor + name: super capacitor + spawn: SuperCapacitorStockPart + maxCount: 10 + +- type: stack + id: SuperManipulator + name: super manipulator + spawn: PicoManipulatorStockPart + maxCount: 10 + +- type: stack + id: SuperMatterBin + name: super matter bin + spawn: SuperMatterBinStockPart + maxCount: 10 + +# Rating 4 + +- type: stack + id: BluespaceCapacitor + name: bluespace capacitor + spawn: BluespaceCapacitorStockPart + maxCount: 10 + +- type: stack + id: BluespaceManipulator + name: bluespace manipulator + spawn: BluespaceManipulatorStockPart + maxCount: 10 + +- type: stack + id: BluespaceMatterBin + name: bluespace matter bin + spawn: BluespaceMatterBinStockPart + maxCount: 10 diff --git a/Resources/Prototypes/_Shitmed/Entities/Objects/Devices/Circuitboards/Machine/production.yml b/Resources/Prototypes/_Shitmed/Entities/Objects/Devices/Circuitboards/Machine/production.yml index b0d7a937ed..f52f123de8 100644 --- a/Resources/Prototypes/_Shitmed/Entities/Objects/Devices/Circuitboards/Machine/production.yml +++ b/Resources/Prototypes/_Shitmed/Entities/Objects/Devices/Circuitboards/Machine/production.yml @@ -6,16 +6,15 @@ components: - type: MachineBoard prototype: Autodoc - requirements: + machinePartRequirements: Manipulator: 4 materialRequirements: Cable: 3 Steel: 10 tagRequirements: BorgArm: - Amount: 3 - ExamineName: "Borg Arm" - DefaultPrototype: LeftArmBorg + amount: 3 + defaultPrototype: LeftArmBorg - type: entity parent: AutodocCircuitboard @@ -48,6 +47,6 @@ state: medical - type: MachineBoard prototype: MedicalBiofabricator - requirements: + machinePartRequirements: MatterBin: 2 Manipulator: 2 diff --git a/Resources/Prototypes/MachineParts/machine_parts.yml b/Resources/Prototypes/machine_parts.yml similarity index 99% rename from Resources/Prototypes/MachineParts/machine_parts.yml rename to Resources/Prototypes/machine_parts.yml index 317e4b8086..a4ed0ef334 100644 --- a/Resources/Prototypes/MachineParts/machine_parts.yml +++ b/Resources/Prototypes/machine_parts.yml @@ -12,9 +12,8 @@ id: MatterBin name: machine-part-name-matter-bin stockPartPrototype: MatterBinStockPart - + - type: machinePart id: PowerCell name: machine-part-name-power-cell stockPartPrototype: PowerCellSmall -