Allow chemical-fueled generators to use multiple reagents (#24258)
multi-reagent generators
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Power.Generator;
|
||||
@@ -13,11 +14,10 @@ namespace Content.Server.Power.Generator;
|
||||
public sealed partial class ChemicalFuelGeneratorAdapterComponent : Component
|
||||
{
|
||||
/// <summary>
|
||||
/// The reagent to accept as fuel.
|
||||
/// A dictionary relating a reagent to accept as fuel to a value to multiply reagent amount by to get fuel amount.
|
||||
/// </summary>
|
||||
[DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public string Reagent = "WeldingFuel";
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<ReagentPrototype>, float> Reagents = new();
|
||||
|
||||
/// <summary>
|
||||
/// The name of <see cref="Solution"/>.
|
||||
@@ -32,16 +32,10 @@ public sealed partial class ChemicalFuelGeneratorAdapterComponent : Component
|
||||
[DataField("solutionRef")]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
|
||||
/// <summary>
|
||||
/// Value to multiply reagent amount by to get fuel amount.
|
||||
/// </summary>
|
||||
[DataField("multiplier"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float Multiplier = 1f;
|
||||
|
||||
/// <summary>
|
||||
/// How much reagent (can be fractional) is left in the generator.
|
||||
/// Stored in units of <see cref="FixedPoint2.Epsilon"/>.
|
||||
/// </summary>
|
||||
[DataField("fractionalReagent"), ViewVariables(VVAccess.ReadWrite)]
|
||||
public float FractionalReagent;
|
||||
[DataField]
|
||||
public Dictionary<ProtoId<ReagentPrototype>, float> FractionalReagents = new();
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Server.Audio;
|
||||
using System.Linq;
|
||||
using Content.Server.Audio;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Materials;
|
||||
@@ -81,7 +82,7 @@ public sealed class GeneratorSystem : SharedGeneratorSystem
|
||||
|
||||
foreach (var reagentQuantity in solution)
|
||||
{
|
||||
if (reagentQuantity.Reagent.Prototype != entity.Comp.Reagent)
|
||||
if (!entity.Comp.Reagents.ContainsKey(reagentQuantity.Reagent.Prototype))
|
||||
{
|
||||
args.Clogged = true;
|
||||
return;
|
||||
@@ -94,14 +95,21 @@ public sealed class GeneratorSystem : SharedGeneratorSystem
|
||||
if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution))
|
||||
return;
|
||||
|
||||
var availableReagent = solution.GetTotalPrototypeQuantity(entity.Comp.Reagent).Value;
|
||||
var totalAvailableReagents = solution.GetTotalPrototypeQuantity(entity.Comp.Reagents.Keys.Select(p => p.Id).ToArray()).Value;
|
||||
foreach (var (reagentId, multiplier) in entity.Comp.Reagents)
|
||||
{
|
||||
var availableReagent = solution.GetTotalPrototypeQuantity(reagentId).Value;
|
||||
var removalPercentage = availableReagent / totalAvailableReagents;
|
||||
var fractionalReagent = entity.Comp.FractionalReagents.GetValueOrDefault(reagentId);
|
||||
var toRemove = RemoveFractionalFuel(
|
||||
ref entity.Comp.FractionalReagent,
|
||||
args.FuelUsed,
|
||||
entity.Comp.Multiplier * FixedPoint2.Epsilon.Float(),
|
||||
ref fractionalReagent,
|
||||
args.FuelUsed * removalPercentage,
|
||||
multiplier * FixedPoint2.Epsilon.Float(),
|
||||
availableReagent);
|
||||
|
||||
_solutionContainer.RemoveReagent(entity.Comp.Solution.Value, entity.Comp.Reagent, FixedPoint2.FromCents(toRemove));
|
||||
entity.Comp.FractionalReagents[reagentId] = fractionalReagent;
|
||||
_solutionContainer.RemoveReagent(entity.Comp.Solution.Value, reagentId, FixedPoint2.FromCents(toRemove));
|
||||
}
|
||||
}
|
||||
|
||||
private void ChemicalGetFuel(Entity<ChemicalFuelGeneratorAdapterComponent> entity, ref GeneratorGetFuelEvent args)
|
||||
@@ -109,9 +117,19 @@ public sealed class GeneratorSystem : SharedGeneratorSystem
|
||||
if (!_solutionContainer.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution))
|
||||
return;
|
||||
|
||||
var availableReagent = solution.GetTotalPrototypeQuantity(entity.Comp.Reagent).Float();
|
||||
var reagent = entity.Comp.FractionalReagent * FixedPoint2.Epsilon.Float() + availableReagent;
|
||||
args.Fuel = reagent * entity.Comp.Multiplier;
|
||||
var totalAvailableReagents = solution.GetTotalPrototypeQuantity(entity.Comp.Reagents.Keys.Select(p => p.Id).ToArray());
|
||||
var fuel = 0f;
|
||||
foreach (var (reagentId, multiplier) in entity.Comp.Reagents)
|
||||
{
|
||||
var availableReagent = solution.GetTotalPrototypeQuantity(reagentId);
|
||||
var percentage = availableReagent / totalAvailableReagents;
|
||||
var fractionalReagent = (availableReagent * percentage).Float();
|
||||
|
||||
var reagent = entity.Comp.FractionalReagents.GetValueOrDefault(reagentId) * FixedPoint2.Epsilon.Float() + fractionalReagent;
|
||||
fuel += reagent * multiplier;
|
||||
}
|
||||
|
||||
args.Fuel = fuel;
|
||||
}
|
||||
|
||||
private void SolidUseFuel(EntityUid uid, SolidFuelGeneratorAdapterComponent component, GeneratorUseFuel args)
|
||||
|
||||
@@ -292,7 +292,8 @@
|
||||
fuelEfficiencyConstant: 0.3
|
||||
- type: ChemicalFuelGeneratorAdapter
|
||||
solution: tank
|
||||
reagent: WeldingFuel
|
||||
reagents:
|
||||
WeldingFuel: 1
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
tank:
|
||||
|
||||
Reference in New Issue
Block a user