Machine upgrading framework [NO CONTENT YET] (#11528)
* upgrading parts baseline * don't hardcode prototypes * 0xsomethingsomething review i sorry i forgot your name
This commit is contained in:
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Piping.Unary.Components;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
{
|
||||
@@ -55,7 +57,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
/// </summary>
|
||||
[DataField("baseMinTemperature")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float BaseMinTemperature = 96.625f; // Selected so that tier-1 parts can reach 73.15k
|
||||
public float BaseMinTemperature = 96.625f; // Selected so that tier-1 parts can reach 73.15k
|
||||
|
||||
/// <summary>
|
||||
/// Maximum temperature the device can reach with a 0 total laser quality. Usually the quality will be at
|
||||
@@ -78,5 +80,17 @@ namespace Content.Server.Atmos.Piping.Unary.Components
|
||||
[DataField("maxTemperatureDelta")]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public float MaxTemperatureDelta = 300;
|
||||
|
||||
/// <summary>
|
||||
/// The machine part that affects the heat capacity.
|
||||
/// </summary>
|
||||
[DataField("machinePartHeatCapacity", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
|
||||
public string MachinePartHeatCapacity = "MatterBin";
|
||||
|
||||
/// <summary>
|
||||
/// The machine part that affects the temperature range.
|
||||
/// </summary>
|
||||
[DataField("machinePartTemperature", customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
|
||||
public string MachinePartTemperature = "Laser";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
[UsedImplicitly]
|
||||
public sealed class GasThermoMachineSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||
|
||||
@@ -33,14 +34,12 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
|
||||
private void OnThermoMachineUpdated(EntityUid uid, GasThermoMachineComponent thermoMachine, AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(thermoMachine.Owner);
|
||||
|
||||
if (!thermoMachine.Enabled
|
||||
|| !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|
||||
|| !nodeContainer.TryGetNode(thermoMachine.InletName, out PipeNode? inlet))
|
||||
{
|
||||
DirtyUI(uid, thermoMachine);
|
||||
appearance?.SetData(ThermoMachineVisuals.Enabled, false);
|
||||
_appearance.SetData(uid, ThermoMachineVisuals.Enabled, false);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -49,7 +48,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
|
||||
if (!MathHelper.CloseTo(combinedHeatCapacity, 0, 0.001f))
|
||||
{
|
||||
appearance?.SetData(ThermoMachineVisuals.Enabled, true);
|
||||
_appearance.SetData(uid, ThermoMachineVisuals.Enabled, true);
|
||||
var combinedEnergy = thermoMachine.HeatCapacity * thermoMachine.TargetTemperature + airHeatCapacity * inlet.Air.Temperature;
|
||||
inlet.Air.Temperature = combinedEnergy / combinedHeatCapacity;
|
||||
}
|
||||
@@ -59,38 +58,15 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
|
||||
|
||||
private void OnThermoMachineLeaveAtmosphere(EntityUid uid, GasThermoMachineComponent component, AtmosDeviceDisabledEvent args)
|
||||
{
|
||||
if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance))
|
||||
{
|
||||
appearance.SetData(ThermoMachineVisuals.Enabled, false);
|
||||
}
|
||||
_appearance.SetData(uid, ThermoMachineVisuals.Enabled, false);
|
||||
|
||||
DirtyUI(uid, component);
|
||||
}
|
||||
|
||||
private void OnGasThermoRefreshParts(EntityUid uid, GasThermoMachineComponent component, RefreshPartsEvent args)
|
||||
{
|
||||
// Here we evaluate the average quality of relevant machine parts.
|
||||
var nLasers = 0;
|
||||
var nBins= 0;
|
||||
var matterBinRating = 0;
|
||||
var laserRating = 0;
|
||||
|
||||
foreach (var part in args.Parts)
|
||||
{
|
||||
switch (part.PartType)
|
||||
{
|
||||
case MachinePart.MatterBin:
|
||||
nBins += 1;
|
||||
matterBinRating += part.Rating;
|
||||
break;
|
||||
case MachinePart.Laser:
|
||||
nLasers += 1;
|
||||
laserRating += part.Rating;
|
||||
break;
|
||||
}
|
||||
}
|
||||
laserRating /= nLasers;
|
||||
matterBinRating /= nBins;
|
||||
var matterBinRating = args.PartRatings[component.MachinePartHeatCapacity];
|
||||
var laserRating = args.PartRatings[component.MachinePartTemperature];
|
||||
|
||||
component.HeatCapacity = 5000 * MathF.Pow(matterBinRating, 2);
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
|
||||
namespace Content.Server.Construction.Components
|
||||
{
|
||||
@@ -9,8 +11,8 @@ namespace Content.Server.Construction.Components
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("requirements")]
|
||||
public readonly Dictionary<MachinePart, int> Requirements = new();
|
||||
[DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>))]
|
||||
public readonly Dictionary<string, int> Requirements = new();
|
||||
|
||||
[ViewVariables]
|
||||
[DataField("materialRequirements")]
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Server.Stack;
|
||||
using Content.Shared.Construction;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Tag;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
|
||||
namespace Content.Server.Construction.Components
|
||||
{
|
||||
@@ -16,8 +18,8 @@ namespace Content.Server.Construction.Components
|
||||
[ViewVariables]
|
||||
public bool HasBoard => BoardContainer?.ContainedEntities.Count != 0;
|
||||
|
||||
[ViewVariables]
|
||||
public readonly Dictionary<MachinePart, int> Progress = new();
|
||||
[DataField("progress", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>)), ViewVariables]
|
||||
public readonly Dictionary<string, int> Progress = new();
|
||||
|
||||
[ViewVariables]
|
||||
public readonly Dictionary<string, int> MaterialProgress = new();
|
||||
@@ -28,8 +30,8 @@ namespace Content.Server.Construction.Components
|
||||
[ViewVariables]
|
||||
public readonly Dictionary<string, int> TagProgress = new();
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<MachinePart, int> Requirements = new();
|
||||
[DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>)),ViewVariables]
|
||||
public Dictionary<string, int> Requirements = new();
|
||||
|
||||
[ViewVariables]
|
||||
public Dictionary<string, int> MaterialRequirements = new();
|
||||
|
||||
@@ -1,25 +1,14 @@
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Construction.Components
|
||||
{
|
||||
[RegisterComponent]
|
||||
public sealed class MachinePartComponent : Component
|
||||
{
|
||||
// I'm so sorry for hard-coding this. But trust me, it should make things less painful.
|
||||
public static IReadOnlyDictionary<MachinePart, string> Prototypes { get; } = new Dictionary<MachinePart, string>()
|
||||
{
|
||||
{MachinePart.Capacitor, "CapacitorStockPart"},
|
||||
{MachinePart.ScanningModule, "ScanningModuleStockPart"},
|
||||
{MachinePart.Manipulator, "MicroManipulatorStockPart"},
|
||||
{MachinePart.Laser, "MicroLaserStockPart"},
|
||||
{MachinePart.MatterBin, "MatterBinStockPart"},
|
||||
{MachinePart.Ansible, "AnsibleSubspaceStockPart"},
|
||||
{MachinePart.Filter, "FilterSubspaceStockPart"},
|
||||
{MachinePart.Amplifier, "AmplifierSubspaceStockPart"},
|
||||
{MachinePart.Treatment, "TreatmentSubspaceStockPart"},
|
||||
{MachinePart.Analyzer, "AnalyzerSubspaceStockPart"},
|
||||
{MachinePart.Crystal, "CrystalSubspaceStockPart"},
|
||||
{MachinePart.Transmitter, "TransmitterSubspaceStockPart"}
|
||||
};
|
||||
[ViewVariables] [DataField("part")] public MachinePart PartType { get; private set; } = MachinePart.Capacitor;
|
||||
[ViewVariables]
|
||||
[DataField("part", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
|
||||
public string PartType { get; private set; } = default!;
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("rating")]
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Construction.Components;
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Robust.Shared.Containers;
|
||||
|
||||
namespace Content.Server.Construction;
|
||||
@@ -36,11 +38,32 @@ public sealed partial class ConstructionSystem
|
||||
return parts;
|
||||
}
|
||||
|
||||
public Dictionary<string, float> GetPartsRatings(List<MachinePartComponent> parts)
|
||||
{
|
||||
var output = new Dictionary<string, float>();
|
||||
foreach (var type in _prototypeManager.EnumeratePrototypes<MachinePartPrototype>())
|
||||
{
|
||||
var amount = 0;
|
||||
var sumRating = 0;
|
||||
foreach (var part in parts.Where(part => part.PartType == type.ID))
|
||||
{
|
||||
amount++;
|
||||
sumRating += part.Rating;
|
||||
}
|
||||
var rating = amount != 0 ? sumRating / amount : 0;
|
||||
output.Add(type.ID, rating);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
public void RefreshParts(MachineComponent component)
|
||||
{
|
||||
EntityManager.EventBus.RaiseLocalEvent(component.Owner, new RefreshPartsEvent()
|
||||
var parts = GetAllParts(component);
|
||||
EntityManager.EventBus.RaiseLocalEvent(component.Owner, new RefreshPartsEvent
|
||||
{
|
||||
Parts = GetAllParts(component),
|
||||
Parts = parts,
|
||||
PartRatings = GetPartsRatings(parts),
|
||||
}, true);
|
||||
}
|
||||
|
||||
@@ -69,14 +92,16 @@ public sealed partial class ConstructionSystem
|
||||
throw new Exception($"Entity with prototype {component.BoardPrototype} doesn't have a {nameof(MachineBoardComponent)}!");
|
||||
}
|
||||
|
||||
var xform = Transform(component.Owner);
|
||||
foreach (var (part, amount) in machineBoard.Requirements)
|
||||
{
|
||||
var partProto = _prototypeManager.Index<MachinePartPrototype>(part);
|
||||
for (var i = 0; i < amount; i++)
|
||||
{
|
||||
var p = EntityManager.SpawnEntity(MachinePartComponent.Prototypes[part], Transform(component.Owner).Coordinates);
|
||||
var p = EntityManager.SpawnEntity(partProto.StockPartPrototype, xform.Coordinates);
|
||||
|
||||
if (!partContainer.Insert(p))
|
||||
throw new Exception($"Couldn't insert machine part of type {part} to machine with prototype {MetaData(component.Owner).EntityPrototype?.ID ?? "N/A"}!");
|
||||
throw new Exception($"Couldn't insert machine part of type {part} to machine with prototype {partProto.StockPartPrototype ?? "N/A"}!");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,4 +140,6 @@ public sealed partial class ConstructionSystem
|
||||
public sealed class RefreshPartsEvent : EntityEventArgs
|
||||
{
|
||||
public IReadOnlyList<MachinePartComponent> Parts = new List<MachinePartComponent>();
|
||||
|
||||
public Dictionary<string, float> PartRatings = new Dictionary<string, float>();
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ public sealed class MachineFrameSystem : EntitySystem
|
||||
|
||||
public void ResetProgressAndRequirements(MachineFrameComponent component, MachineBoardComponent machineBoard)
|
||||
{
|
||||
component.Requirements = new Dictionary<MachinePart, int>(machineBoard.Requirements);
|
||||
component.Requirements = new Dictionary<string, int>(machineBoard.Requirements);
|
||||
component.MaterialRequirements = new Dictionary<string, int>(machineBoard.MaterialIdRequirements);
|
||||
component.ComponentRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.ComponentRequirements);
|
||||
component.TagRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.TagRequirements);
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
namespace Content.Server.Construction
|
||||
{
|
||||
public enum MachinePart : byte
|
||||
{
|
||||
Capacitor,
|
||||
ScanningModule,
|
||||
Manipulator,
|
||||
Laser,
|
||||
MatterBin,
|
||||
|
||||
// Subspace parts.
|
||||
Ansible,
|
||||
Filter,
|
||||
Amplifier,
|
||||
Treatment,
|
||||
Analyzer,
|
||||
Crystal,
|
||||
Transmitter,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Shared.Construction.Prototypes;
|
||||
|
||||
/// <summary>
|
||||
/// This is a prototype for categorizing
|
||||
/// different types of machine parts.
|
||||
/// </summary>
|
||||
[Prototype("machinePart")]
|
||||
public sealed class MachinePartPrototype : IPrototype
|
||||
{
|
||||
/// <inheritdoc/>
|
||||
[IdDataField]
|
||||
public string ID { get; } = default!;
|
||||
|
||||
/// <summary>
|
||||
/// A stock part entity based on the machine part.
|
||||
/// </summary>
|
||||
[DataField("stockPartPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string? StockPartPrototype { get; }
|
||||
}
|
||||
47
Resources/Prototypes/MachineParts/machine_parts.yml
Normal file
47
Resources/Prototypes/MachineParts/machine_parts.yml
Normal file
@@ -0,0 +1,47 @@
|
||||
- type: machinePart
|
||||
id: Capacitor
|
||||
stockPartPrototype: CapacitorStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: ScanningModule
|
||||
stockPartPrototype: ScanningModuleStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Manipulator
|
||||
stockPartPrototype: MicroManipulatorStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Laser
|
||||
stockPartPrototype: MicroLaserStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: MatterBin
|
||||
stockPartPrototype: MatterBinStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Ansible
|
||||
stockPartPrototype: AnsibleSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Filter
|
||||
stockPartPrototype: FilterSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Amplifier
|
||||
stockPartPrototype: AmplifierSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Treatment
|
||||
stockPartPrototype: TreatmentSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Analyzer
|
||||
stockPartPrototype: AnalyzerSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Crystal
|
||||
stockPartPrototype: CrystalSubspaceStockPart
|
||||
|
||||
- type: machinePart
|
||||
id: Transmitter
|
||||
stockPartPrototype: TransmitterSubspaceStockPart
|
||||
Reference in New Issue
Block a user