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:
Nemanja
2022-09-26 16:18:31 -04:00
committed by GitHub
parent 4b4538ee86
commit 3774a00a5c
10 changed files with 138 additions and 79 deletions

View File

@@ -1,5 +1,7 @@
using Content.Shared.Atmos; using Content.Shared.Atmos;
using Content.Shared.Atmos.Piping.Unary.Components; 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 namespace Content.Server.Atmos.Piping.Unary.Components
{ {
@@ -55,7 +57,7 @@ namespace Content.Server.Atmos.Piping.Unary.Components
/// </summary> /// </summary>
[DataField("baseMinTemperature")] [DataField("baseMinTemperature")]
[ViewVariables(VVAccess.ReadWrite)] [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> /// <summary>
/// Maximum temperature the device can reach with a 0 total laser quality. Usually the quality will be at /// 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")] [DataField("maxTemperatureDelta")]
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public float MaxTemperatureDelta = 300; 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";
} }
} }

View File

@@ -15,6 +15,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
[UsedImplicitly] [UsedImplicitly]
public sealed class GasThermoMachineSystem : EntitySystem public sealed class GasThermoMachineSystem : EntitySystem
{ {
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = 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) private void OnThermoMachineUpdated(EntityUid uid, GasThermoMachineComponent thermoMachine, AtmosDeviceUpdateEvent args)
{ {
var appearance = EntityManager.GetComponentOrNull<AppearanceComponent>(thermoMachine.Owner);
if (!thermoMachine.Enabled if (!thermoMachine.Enabled
|| !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer) || !EntityManager.TryGetComponent(uid, out NodeContainerComponent? nodeContainer)
|| !nodeContainer.TryGetNode(thermoMachine.InletName, out PipeNode? inlet)) || !nodeContainer.TryGetNode(thermoMachine.InletName, out PipeNode? inlet))
{ {
DirtyUI(uid, thermoMachine); DirtyUI(uid, thermoMachine);
appearance?.SetData(ThermoMachineVisuals.Enabled, false); _appearance.SetData(uid, ThermoMachineVisuals.Enabled, false);
return; return;
} }
@@ -49,7 +48,7 @@ namespace Content.Server.Atmos.Piping.Unary.EntitySystems
if (!MathHelper.CloseTo(combinedHeatCapacity, 0, 0.001f)) 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; var combinedEnergy = thermoMachine.HeatCapacity * thermoMachine.TargetTemperature + airHeatCapacity * inlet.Air.Temperature;
inlet.Air.Temperature = combinedEnergy / combinedHeatCapacity; 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) private void OnThermoMachineLeaveAtmosphere(EntityUid uid, GasThermoMachineComponent component, AtmosDeviceDisabledEvent args)
{ {
if (EntityManager.TryGetComponent(uid, out AppearanceComponent? appearance)) _appearance.SetData(uid, ThermoMachineVisuals.Enabled, false);
{
appearance.SetData(ThermoMachineVisuals.Enabled, false);
}
DirtyUI(uid, component); DirtyUI(uid, component);
} }
private void OnGasThermoRefreshParts(EntityUid uid, GasThermoMachineComponent component, RefreshPartsEvent args) private void OnGasThermoRefreshParts(EntityUid uid, GasThermoMachineComponent component, RefreshPartsEvent args)
{ {
// Here we evaluate the average quality of relevant machine parts. var matterBinRating = args.PartRatings[component.MachinePartHeatCapacity];
var nLasers = 0; var laserRating = args.PartRatings[component.MachinePartTemperature];
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;
component.HeatCapacity = 5000 * MathF.Pow(matterBinRating, 2); component.HeatCapacity = 5000 * MathF.Pow(matterBinRating, 2);

View File

@@ -1,5 +1,7 @@
using Content.Shared.Construction.Prototypes;
using Content.Shared.Stacks; using Content.Shared.Stacks;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Server.Construction.Components namespace Content.Server.Construction.Components
{ {
@@ -9,8 +11,8 @@ namespace Content.Server.Construction.Components
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[ViewVariables] [ViewVariables]
[DataField("requirements")] [DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>))]
public readonly Dictionary<MachinePart, int> Requirements = new(); public readonly Dictionary<string, int> Requirements = new();
[ViewVariables] [ViewVariables]
[DataField("materialRequirements")] [DataField("materialRequirements")]

View File

@@ -1,9 +1,11 @@
using System.Threading.Tasks; using System.Threading.Tasks;
using Content.Server.Stack; using Content.Server.Stack;
using Content.Shared.Construction; using Content.Shared.Construction;
using Content.Shared.Construction.Prototypes;
using Content.Shared.Interaction; using Content.Shared.Interaction;
using Content.Shared.Tag; using Content.Shared.Tag;
using Robust.Shared.Containers; using Robust.Shared.Containers;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Server.Construction.Components namespace Content.Server.Construction.Components
{ {
@@ -16,8 +18,8 @@ namespace Content.Server.Construction.Components
[ViewVariables] [ViewVariables]
public bool HasBoard => BoardContainer?.ContainedEntities.Count != 0; public bool HasBoard => BoardContainer?.ContainedEntities.Count != 0;
[ViewVariables] [DataField("progress", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>)), ViewVariables]
public readonly Dictionary<MachinePart, int> Progress = new(); public readonly Dictionary<string, int> Progress = new();
[ViewVariables] [ViewVariables]
public readonly Dictionary<string, int> MaterialProgress = new(); public readonly Dictionary<string, int> MaterialProgress = new();
@@ -28,8 +30,8 @@ namespace Content.Server.Construction.Components
[ViewVariables] [ViewVariables]
public readonly Dictionary<string, int> TagProgress = new(); public readonly Dictionary<string, int> TagProgress = new();
[ViewVariables] [DataField("requirements", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<int, MachinePartPrototype>)),ViewVariables]
public Dictionary<MachinePart, int> Requirements = new(); public Dictionary<string, int> Requirements = new();
[ViewVariables] [ViewVariables]
public Dictionary<string, int> MaterialRequirements = new(); public Dictionary<string, int> MaterialRequirements = new();

View File

@@ -1,25 +1,14 @@
using Content.Shared.Construction.Prototypes;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Construction.Components namespace Content.Server.Construction.Components
{ {
[RegisterComponent] [RegisterComponent]
public sealed class MachinePartComponent : Component public sealed class MachinePartComponent : Component
{ {
// I'm so sorry for hard-coding this. But trust me, it should make things less painful. [ViewVariables]
public static IReadOnlyDictionary<MachinePart, string> Prototypes { get; } = new Dictionary<MachinePart, string>() [DataField("part", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<MachinePartPrototype>))]
{ public string PartType { get; private set; } = default!;
{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(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
[DataField("rating")] [DataField("rating")]

View File

@@ -1,4 +1,6 @@
using System.Linq;
using Content.Server.Construction.Components; using Content.Server.Construction.Components;
using Content.Shared.Construction.Prototypes;
using Robust.Shared.Containers; using Robust.Shared.Containers;
namespace Content.Server.Construction; namespace Content.Server.Construction;
@@ -36,11 +38,32 @@ public sealed partial class ConstructionSystem
return parts; 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) 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); }, true);
} }
@@ -69,14 +92,16 @@ public sealed partial class ConstructionSystem
throw new Exception($"Entity with prototype {component.BoardPrototype} doesn't have a {nameof(MachineBoardComponent)}!"); 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) foreach (var (part, amount) in machineBoard.Requirements)
{ {
var partProto = _prototypeManager.Index<MachinePartPrototype>(part);
for (var i = 0; i < amount; i++) 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)) 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 sealed class RefreshPartsEvent : EntityEventArgs
{ {
public IReadOnlyList<MachinePartComponent> Parts = new List<MachinePartComponent>(); public IReadOnlyList<MachinePartComponent> Parts = new List<MachinePartComponent>();
public Dictionary<string, float> PartRatings = new Dictionary<string, float>();
} }

View File

@@ -183,7 +183,7 @@ public sealed class MachineFrameSystem : EntitySystem
public void ResetProgressAndRequirements(MachineFrameComponent component, MachineBoardComponent machineBoard) 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.MaterialRequirements = new Dictionary<string, int>(machineBoard.MaterialIdRequirements);
component.ComponentRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.ComponentRequirements); component.ComponentRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.ComponentRequirements);
component.TagRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.TagRequirements); component.TagRequirements = new Dictionary<string, GenericPartInfo>(machineBoard.TagRequirements);

View File

@@ -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,
}
}

View File

@@ -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; }
}

View 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