Revert "Solution Entities" (#23160)
Revert "Solution Entities (#21916)"
This reverts commit d75e743dd7.
This commit is contained in:
@@ -4,6 +4,9 @@ using Robust.Client.Console;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.IoC;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Client.Administration.UI.ManageSolutions
|
||||
|
||||
@@ -20,7 +20,7 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
||||
private NetEntity _target = NetEntity.Invalid;
|
||||
private string? _selectedSolution;
|
||||
private AddReagentWindow? _addReagentWindow;
|
||||
private Dictionary<string, EntityUid>? _solutions;
|
||||
private Dictionary<string, Solution>? _solutions;
|
||||
|
||||
public EditSolutionsWindow()
|
||||
{
|
||||
@@ -60,11 +60,9 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
||||
if (_selectedSolution == null || _solutions == null)
|
||||
return;
|
||||
|
||||
if (!_solutions.TryGetValue(_selectedSolution, out var solutionId) ||
|
||||
!_entityManager.TryGetComponent(solutionId, out SolutionComponent? solutionComp))
|
||||
if (!_solutions.TryGetValue(_selectedSolution, out var solution))
|
||||
return;
|
||||
|
||||
var solution = solutionComp.Solution;
|
||||
UpdateVolumeBox(solution);
|
||||
UpdateThermalBox(solution);
|
||||
|
||||
@@ -200,13 +198,10 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
||||
/// </summary>
|
||||
private void SetReagent(FloatSpinBox.FloatSpinBoxEventArgs args, string prototype)
|
||||
{
|
||||
if (_solutions == null || _selectedSolution == null ||
|
||||
!_solutions.TryGetValue(_selectedSolution, out var solutionId) ||
|
||||
!_entityManager.TryGetComponent(solutionId, out SolutionComponent? solutionComp))
|
||||
if (_solutions == null || _selectedSolution == null)
|
||||
return;
|
||||
|
||||
var solution = solutionComp.Solution;
|
||||
var current = solution.GetTotalPrototypeQuantity(prototype);
|
||||
var current = _solutions[_selectedSolution].GetTotalPrototypeQuantity(prototype);
|
||||
var delta = args.Value - current.Float();
|
||||
|
||||
if (MathF.Abs(delta) < 0.01)
|
||||
@@ -280,38 +275,22 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
||||
/// <summary>
|
||||
/// Update the solution options.
|
||||
/// </summary>
|
||||
public void UpdateSolutions(List<(string, NetEntity)>? solutions)
|
||||
public void UpdateSolutions(Dictionary<string, Solution>? solutions)
|
||||
{
|
||||
SolutionOption.Clear();
|
||||
|
||||
if (solutions is { Count: > 0 })
|
||||
{
|
||||
if (_solutions is { Count: > 0 })
|
||||
_solutions.Clear();
|
||||
else
|
||||
_solutions = new(solutions.Count);
|
||||
|
||||
foreach (var (name, netSolution) in solutions)
|
||||
{
|
||||
if (_entityManager.TryGetEntity(netSolution, out var solution))
|
||||
_solutions.Add(name, solution.Value);
|
||||
}
|
||||
}
|
||||
else
|
||||
_solutions = null;
|
||||
_solutions = solutions;
|
||||
|
||||
if (_solutions == null)
|
||||
return;
|
||||
|
||||
int i = 0;
|
||||
int selectedIndex = 0; // Default to the first solution if none are found.
|
||||
foreach (var (name, _) in _solutions)
|
||||
foreach (var solution in _solutions.Keys)
|
||||
{
|
||||
SolutionOption.AddItem(name, i);
|
||||
SolutionOption.SetItemMetadata(i, name);
|
||||
SolutionOption.AddItem(solution, i);
|
||||
SolutionOption.SetItemMetadata(i, solution);
|
||||
|
||||
if (name == _selectedSolution)
|
||||
selectedIndex = i;
|
||||
if (solution == _selectedSolution)
|
||||
SolutionOption.Select(i);
|
||||
|
||||
i++;
|
||||
}
|
||||
@@ -321,11 +300,14 @@ namespace Content.Client.Administration.UI.ManageSolutions
|
||||
// No applicable solutions
|
||||
Close();
|
||||
Dispose();
|
||||
return;
|
||||
}
|
||||
|
||||
SolutionOption.Select(selectedIndex);
|
||||
_selectedSolution = (string?) SolutionOption.SelectedMetadata;
|
||||
if (_selectedSolution == null || !_solutions.ContainsKey(_selectedSolution))
|
||||
{
|
||||
// the previously selected solution is no longer valid.
|
||||
SolutionOption.Select(0);
|
||||
_selectedSolution = (string?) SolutionOption.SelectedMetadata;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
|
||||
namespace Content.Client.Chemistry.Containers.EntitySystems;
|
||||
|
||||
public sealed partial class SolutionContainerSystem : SharedSolutionContainerSystem
|
||||
{
|
||||
}
|
||||
@@ -1,9 +1,11 @@
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Kitchen;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -13,7 +15,7 @@ namespace Content.Client.Kitchen.UI
|
||||
public sealed partial class GrinderMenu : FancyWindow
|
||||
{
|
||||
private readonly IEntityManager _entityManager;
|
||||
private readonly IPrototypeManager _prototypeManager;
|
||||
private readonly IPrototypeManager _prototypeManager ;
|
||||
private readonly ReagentGrinderBoundUserInterface _owner;
|
||||
|
||||
private readonly Dictionary<int, EntityUid> _chamberVisualContents = new();
|
||||
@@ -120,8 +122,8 @@ namespace Content.Client.Kitchen.UI
|
||||
{
|
||||
foreach (var (reagent, quantity) in reagents)
|
||||
{
|
||||
var reagentName = _prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto)
|
||||
? Loc.GetString($"{quantity} {proto.LocalizedName}")
|
||||
var reagentName = _prototypeManager.TryIndex(reagent.Prototype, out ReagentPrototype? proto)
|
||||
? Loc.GetString($"{quantity} {proto.LocalizedName}")
|
||||
: "???";
|
||||
BeakerContentBox.BoxContents.AddItem(reagentName);
|
||||
}
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Shared.Graphics;
|
||||
|
||||
namespace Content.Client.Kitchen.UI
|
||||
{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -51,7 +51,7 @@ public sealed class SolutionSystemTests
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var protoMan = server.ResolveDependency<IPrototypeManager>();
|
||||
var containerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var containerSystem = entityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var coordinates = testMap.GridCoords;
|
||||
|
||||
@@ -67,11 +67,11 @@ public sealed class SolutionSystemTests
|
||||
|
||||
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
|
||||
Assert.That(containerSystem
|
||||
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
|
||||
.TryGetSolution(beaker, "beaker", out var solution));
|
||||
|
||||
solution.AddSolution(originalWater, protoMan);
|
||||
Assert.That(containerSystem
|
||||
.TryAddSolution(solutionEnt.Value, oilAdded));
|
||||
.TryAddSolution(beaker, solution, oilAdded));
|
||||
|
||||
var water = solution.GetTotalPrototypeQuantity("Water");
|
||||
var oil = solution.GetTotalPrototypeQuantity("Oil");
|
||||
@@ -97,7 +97,7 @@ public sealed class SolutionSystemTests
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var protoMan = server.ResolveDependency<IPrototypeManager>();
|
||||
var containerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var containerSystem = entityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
var coordinates = testMap.GridCoords;
|
||||
|
||||
EntityUid beaker;
|
||||
@@ -112,11 +112,11 @@ public sealed class SolutionSystemTests
|
||||
|
||||
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
|
||||
Assert.That(containerSystem
|
||||
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
|
||||
.TryGetSolution(beaker, "beaker", out var solution));
|
||||
|
||||
solution.AddSolution(originalWater, protoMan);
|
||||
Assert.That(containerSystem
|
||||
.TryAddSolution(solutionEnt.Value, oilAdded), Is.False);
|
||||
.TryAddSolution(beaker, solution, oilAdded), Is.False);
|
||||
|
||||
var water = solution.GetTotalPrototypeQuantity("Water");
|
||||
var oil = solution.GetTotalPrototypeQuantity("Oil");
|
||||
@@ -141,7 +141,7 @@ public sealed class SolutionSystemTests
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var protoMan = server.ResolveDependency<IPrototypeManager>();
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var containerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var containerSystem = entityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
var coordinates = testMap.GridCoords;
|
||||
|
||||
EntityUid beaker;
|
||||
@@ -158,11 +158,11 @@ public sealed class SolutionSystemTests
|
||||
|
||||
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
|
||||
Assert.That(containerSystem
|
||||
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
|
||||
.TryGetSolution(beaker, "beaker", out var solution));
|
||||
|
||||
solution.AddSolution(originalWater, protoMan);
|
||||
Assert.That(containerSystem
|
||||
.TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out var overflowingSolution));
|
||||
.TryMixAndOverflow(beaker, solution, oilAdded, threshold, out var overflowingSolution));
|
||||
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
@@ -194,7 +194,7 @@ public sealed class SolutionSystemTests
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var protoMan = server.ResolveDependency<IPrototypeManager>();
|
||||
var containerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var containerSystem = entityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var coordinates = testMap.GridCoords;
|
||||
|
||||
@@ -212,11 +212,11 @@ public sealed class SolutionSystemTests
|
||||
|
||||
beaker = entityManager.SpawnEntity("SolutionTarget", coordinates);
|
||||
Assert.That(containerSystem
|
||||
.TryGetSolution(beaker, "beaker", out var solutionEnt, out var solution));
|
||||
.TryGetSolution(beaker, "beaker", out var solution));
|
||||
|
||||
solution.AddSolution(originalWater, protoMan);
|
||||
Assert.That(containerSystem
|
||||
.TryMixAndOverflow(solutionEnt.Value, oilAdded, threshold, out _),
|
||||
.TryMixAndOverflow(beaker, solution, oilAdded, threshold, out _),
|
||||
Is.False);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using System.Linq;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Chemistry
|
||||
{
|
||||
@@ -34,7 +34,8 @@ namespace Content.IntegrationTests.Tests.Chemistry
|
||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
var testMap = await pair.CreateTestMap();
|
||||
var coordinates = testMap.GridCoords;
|
||||
var solutionContainerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var solutionSystem = server.ResolveDependency<IEntitySystemManager>()
|
||||
.GetEntitySystem<SolutionContainerSystem>();
|
||||
|
||||
foreach (var reactionPrototype in prototypeManager.EnumeratePrototypes<ReactionPrototype>())
|
||||
{
|
||||
@@ -42,31 +43,30 @@ namespace Content.IntegrationTests.Tests.Chemistry
|
||||
Console.WriteLine($"Testing {reactionPrototype.ID}");
|
||||
|
||||
EntityUid beaker = default;
|
||||
Entity<SolutionComponent>? solutionEnt = default!;
|
||||
Solution solution = null;
|
||||
Solution component = null;
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
beaker = entityManager.SpawnEntity("TestSolutionContainer", coordinates);
|
||||
Assert.That(solutionContainerSystem
|
||||
.TryGetSolution(beaker, "beaker", out solutionEnt, out solution));
|
||||
Assert.That(solutionSystem
|
||||
.TryGetSolution(beaker, "beaker", out component));
|
||||
foreach (var (id, reactant) in reactionPrototype.Reactants)
|
||||
{
|
||||
#pragma warning disable NUnit2045
|
||||
Assert.That(solutionContainerSystem
|
||||
.TryAddReagent(solutionEnt.Value, id, reactant.Amount, out var quantity));
|
||||
Assert.That(solutionSystem
|
||||
.TryAddReagent(beaker, component, id, reactant.Amount, out var quantity));
|
||||
Assert.That(reactant.Amount, Is.EqualTo(quantity));
|
||||
#pragma warning restore NUnit2045
|
||||
}
|
||||
|
||||
solutionContainerSystem.SetTemperature(solutionEnt.Value, reactionPrototype.MinimumTemperature);
|
||||
solutionSystem.SetTemperature(beaker, component, reactionPrototype.MinimumTemperature);
|
||||
|
||||
if (reactionPrototype.MixingCategories != null)
|
||||
{
|
||||
var dummyEntity = entityManager.SpawnEntity(null, MapCoordinates.Nullspace);
|
||||
var mixerComponent = entityManager.AddComponent<ReactionMixerComponent>(dummyEntity);
|
||||
mixerComponent.ReactionTypes = reactionPrototype.MixingCategories;
|
||||
solutionContainerSystem.UpdateChemicals(solutionEnt.Value, true, mixerComponent);
|
||||
solutionSystem.UpdateChemicals(beaker, component, true, mixerComponent);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -79,7 +79,7 @@ namespace Content.IntegrationTests.Tests.Chemistry
|
||||
var foundProductsMap = reactionPrototype.Products
|
||||
.Concat(reactionPrototype.Reactants.Where(x => x.Value.Catalyst).ToDictionary(x => x.Key, x => x.Value.Amount))
|
||||
.ToDictionary(x => x, _ => false);
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
foreach (var (reagent, quantity) in component.Contents)
|
||||
{
|
||||
Assert.That(foundProductsMap.TryFirstOrNull(x => x.Key.Key == reagent.Prototype && x.Key.Value == quantity, out var foundProduct));
|
||||
foundProductsMap[foundProduct.Value.Key] = true;
|
||||
|
||||
@@ -80,7 +80,7 @@ public sealed class AbsorbentTest
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var absorbentSystem = entityManager.System<AbsorbentSystem>();
|
||||
var solutionContainerSystem = entityManager.System<SharedSolutionContainerSystem>();
|
||||
var solutionContainerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
|
||||
EntityUid user = default;
|
||||
@@ -94,19 +94,19 @@ public sealed class AbsorbentTest
|
||||
refillable = entityManager.SpawnEntity(RefillableDummyId, coordinates);
|
||||
|
||||
entityManager.TryGetComponent(absorbent, out component);
|
||||
solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution);
|
||||
solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution);
|
||||
solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSolution);
|
||||
solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSolution);
|
||||
|
||||
// Arrange
|
||||
if (testCase.InitialAbsorbentSolution.VolumeOfEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable));
|
||||
solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable));
|
||||
if (testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable));
|
||||
solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable));
|
||||
|
||||
if (testCase.InitialRefillableSolution.VolumeOfEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable));
|
||||
solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable));
|
||||
if (testCase.InitialRefillableSolution.VolumeOfNonEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable));
|
||||
solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable));
|
||||
|
||||
// Act
|
||||
absorbentSystem.Mop(user, refillable, absorbent, component);
|
||||
@@ -138,7 +138,7 @@ public sealed class AbsorbentTest
|
||||
|
||||
var entityManager = server.ResolveDependency<IEntityManager>();
|
||||
var absorbentSystem = entityManager.System<AbsorbentSystem>();
|
||||
var solutionContainerSystem = entityManager.System<SharedSolutionContainerSystem>();
|
||||
var solutionContainerSystem = entityManager.System<SolutionContainerSystem>();
|
||||
var prototypeManager = server.ResolveDependency<IPrototypeManager>();
|
||||
|
||||
EntityUid user = default;
|
||||
@@ -152,18 +152,18 @@ public sealed class AbsorbentTest
|
||||
refillable = entityManager.SpawnEntity(SmallRefillableDummyId, coordinates);
|
||||
|
||||
entityManager.TryGetComponent(absorbent, out component);
|
||||
solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSoln, out var absorbentSolution);
|
||||
solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSoln, out var refillableSolution);
|
||||
solutionContainerSystem.TryGetSolution(absorbent, AbsorbentComponent.SolutionName, out var absorbentSolution);
|
||||
solutionContainerSystem.TryGetRefillableSolution(refillable, out var refillableSolution);
|
||||
|
||||
// Arrange
|
||||
solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable));
|
||||
solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(EvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfEvaporable));
|
||||
if (testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(absorbentSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable));
|
||||
solutionContainerSystem.AddSolution(absorbent, absorbentSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialAbsorbentSolution.VolumeOfNonEvaporable));
|
||||
|
||||
if (testCase.InitialRefillableSolution.VolumeOfEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable));
|
||||
solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(EvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfEvaporable));
|
||||
if (testCase.InitialRefillableSolution.VolumeOfNonEvaporable > FixedPoint2.Zero)
|
||||
solutionContainerSystem.AddSolution(refillableSoln.Value, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable));
|
||||
solutionContainerSystem.AddSolution(refillable, refillableSolution, new Solution(NonEvaporablePrototypeId, testCase.InitialRefillableSolution.VolumeOfNonEvaporable));
|
||||
|
||||
// Act
|
||||
absorbentSystem.Mop(user, refillable, absorbent, component);
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Console;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
@@ -42,13 +41,13 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var solutionContainerSystem = _entManager.System<SolutionContainerSystem>();
|
||||
if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution))
|
||||
if (!man.Solutions.ContainsKey(args[1]))
|
||||
{
|
||||
var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name));
|
||||
var validSolutions = string.Join(", ", man.Solutions.Keys);
|
||||
shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}");
|
||||
return;
|
||||
}
|
||||
var solution = man.Solutions[args[1]];
|
||||
|
||||
if (!_protomanager.HasIndex<ReagentPrototype>(args[2]))
|
||||
{
|
||||
@@ -64,9 +63,9 @@ namespace Content.Server.Administration.Commands
|
||||
var quantity = FixedPoint2.New(MathF.Abs(quantityFloat));
|
||||
|
||||
if (quantityFloat > 0)
|
||||
solutionContainerSystem.TryAddReagent(solution.Value, args[2], quantity, out _);
|
||||
_entManager.System<SolutionContainerSystem>().TryAddReagent(uid.Value, solution, args[2], quantity, out _);
|
||||
else
|
||||
solutionContainerSystem.RemoveReagent(solution.Value, args[2], quantity);
|
||||
_entManager.System<SolutionContainerSystem>().RemoveReagent(uid.Value, solution, args[2], quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Console;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
@@ -36,13 +35,13 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var solutionContainerSystem = _entManager.System<SolutionContainerSystem>();
|
||||
if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution))
|
||||
if (!man.Solutions.ContainsKey(args[1]))
|
||||
{
|
||||
var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name));
|
||||
var validSolutions = string.Join(", ", man.Solutions.Keys);
|
||||
shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}");
|
||||
return;
|
||||
}
|
||||
var solution = man.Solutions[args[1]];
|
||||
|
||||
if (!float.TryParse(args[2], out var quantityFloat))
|
||||
{
|
||||
@@ -50,14 +49,14 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
if (quantityFloat < 0.0f)
|
||||
if(quantityFloat < 0.0f)
|
||||
{
|
||||
shell.WriteLine($"Cannot set the maximum volume of a solution to a negative number.");
|
||||
return;
|
||||
}
|
||||
|
||||
var quantity = FixedPoint2.New(quantityFloat);
|
||||
solutionContainerSystem.SetCapacity(solution.Value, quantity);
|
||||
_entManager.System<SolutionContainerSystem>().SetCapacity(uid.Value, solution, quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Robust.Shared.Console;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
@@ -35,13 +34,13 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var solutionContainerSystem = _entManager.System<SolutionContainerSystem>();
|
||||
if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solution))
|
||||
if (!man.Solutions.ContainsKey(args[1]))
|
||||
{
|
||||
var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name));
|
||||
var validSolutions = string.Join(", ", man.Solutions.Keys);
|
||||
shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}");
|
||||
return;
|
||||
}
|
||||
var solution = man.Solutions[args[1]];
|
||||
|
||||
if (!float.TryParse(args[2], out var quantity))
|
||||
{
|
||||
@@ -55,7 +54,7 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
solutionContainerSystem.SetTemperature(solution.Value, quantity);
|
||||
_entManager.System<SolutionContainerSystem>().SetTemperature(uid.Value, solution, quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Robust.Shared.Console;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Administration.Commands
|
||||
{
|
||||
@@ -35,13 +34,13 @@ namespace Content.Server.Administration.Commands
|
||||
return;
|
||||
}
|
||||
|
||||
var solutionContainerSystem = _entManager.System<SolutionContainerSystem>();
|
||||
if (!solutionContainerSystem.TryGetSolution((uid.Value, man), args[1], out var solutionEnt, out var solution))
|
||||
if (!man.Solutions.ContainsKey(args[1]))
|
||||
{
|
||||
var validSolutions = string.Join(", ", solutionContainerSystem.EnumerateSolutions((uid.Value, man)).Select(s => s.Name));
|
||||
var validSolutions = string.Join(", ", man.Solutions.Keys);
|
||||
shell.WriteLine($"Entity does not have a \"{args[1]}\" solution. Valid solutions are:\n{validSolutions}");
|
||||
return;
|
||||
}
|
||||
var solution = man.Solutions[args[1]];
|
||||
|
||||
if (!float.TryParse(args[2], out var quantity))
|
||||
{
|
||||
@@ -51,19 +50,19 @@ namespace Content.Server.Administration.Commands
|
||||
|
||||
if (solution.GetHeatCapacity(null) <= 0.0f)
|
||||
{
|
||||
if (quantity != 0.0f)
|
||||
if(quantity != 0.0f)
|
||||
{
|
||||
shell.WriteLine($"Cannot set the thermal energy of a solution with 0 heat capacity to a non-zero number.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else if (quantity <= 0.0f)
|
||||
else if(quantity <= 0.0f)
|
||||
{
|
||||
shell.WriteLine($"Cannot set the thermal energy of a solution with heat capacity to a non-positive number.");
|
||||
return;
|
||||
}
|
||||
|
||||
solutionContainerSystem.SetThermalEnergy(solutionEnt.Value, quantity);
|
||||
_entManager.System<SolutionContainerSystem>().SetThermalEnergy(uid.Value, solution, quantity);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Administration.Managers;
|
||||
using Content.Server.Administration.UI;
|
||||
@@ -33,7 +34,6 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
using static Content.Shared.Configurable.ConfigurationComponent;
|
||||
|
||||
namespace Content.Server.Administration.Systems
|
||||
@@ -71,7 +71,7 @@ namespace Content.Server.Administration.Systems
|
||||
{
|
||||
SubscribeLocalEvent<GetVerbsEvent<Verb>>(GetVerbs);
|
||||
SubscribeLocalEvent<RoundRestartCleanupEvent>(Reset);
|
||||
SubscribeLocalEvent<SolutionContainerManagerComponent, SolutionContainerChangedEvent>(OnSolutionChanged);
|
||||
SubscribeLocalEvent<SolutionContainerManagerComponent, SolutionChangedEvent>(OnSolutionChanged);
|
||||
}
|
||||
|
||||
private void GetVerbs(GetVerbsEvent<Verb> ev)
|
||||
@@ -470,11 +470,11 @@ namespace Content.Server.Administration.Systems
|
||||
}
|
||||
|
||||
#region SolutionsEui
|
||||
private void OnSolutionChanged(Entity<SolutionContainerManagerComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
private void OnSolutionChanged(EntityUid uid, SolutionContainerManagerComponent component, SolutionChangedEvent args)
|
||||
{
|
||||
foreach (var eui in _openSolutionUis.Values)
|
||||
{
|
||||
if (eui.Target == entity.Owner)
|
||||
if (eui.Target == uid)
|
||||
eui.StateDirty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using System.Linq;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Toolshed;
|
||||
using Robust.Shared.Toolshed.Syntax;
|
||||
using Robust.Shared.Toolshed.TypeParsers;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Administration.Toolshed;
|
||||
|
||||
@@ -24,8 +24,10 @@ public sealed class SolutionCommand : ToolshedCommand
|
||||
{
|
||||
_solutionContainer ??= GetSys<SolutionContainerSystem>();
|
||||
|
||||
if (_solutionContainer.TryGetSolution(input, name.Evaluate(ctx)!, out var solution))
|
||||
return new SolutionRef(solution.Value);
|
||||
_solutionContainer.TryGetSolution(input, name.Evaluate(ctx)!, out var solution);
|
||||
|
||||
if (solution is not null)
|
||||
return new SolutionRef(input, solution);
|
||||
|
||||
return null;
|
||||
}
|
||||
@@ -53,11 +55,11 @@ public sealed class SolutionCommand : ToolshedCommand
|
||||
var amount = amountRef.Evaluate(ctx);
|
||||
if (amount > 0)
|
||||
{
|
||||
_solutionContainer.TryAddReagent(input.Solution, name.Value.ID, amount, out _);
|
||||
_solutionContainer.TryAddReagent(input.Owner, input.Solution, name.Value.ID, amount, out _);
|
||||
}
|
||||
else if (amount < 0)
|
||||
{
|
||||
_solutionContainer.RemoveReagent(input.Solution, name.Value.ID, -amount);
|
||||
_solutionContainer.RemoveReagent(input.Owner, input.Solution, name.Value.ID, -amount);
|
||||
}
|
||||
|
||||
return input;
|
||||
@@ -73,10 +75,10 @@ public sealed class SolutionCommand : ToolshedCommand
|
||||
=> input.Select(x => AdjReagent(ctx, x, name, amountRef));
|
||||
}
|
||||
|
||||
public readonly record struct SolutionRef(Entity<SolutionComponent> Solution)
|
||||
public readonly record struct SolutionRef(EntityUid Owner, Solution Solution)
|
||||
{
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Solution.Owner} {Solution.Comp.Solution}";
|
||||
return $"{Owner} {Solution}";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Administration.Systems;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.EUI;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
@@ -15,13 +14,11 @@ namespace Content.Server.Administration.UI
|
||||
public sealed class EditSolutionsEui : BaseEui
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
public readonly EntityUid Target;
|
||||
|
||||
public EditSolutionsEui(EntityUid entity)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_solutionContainerSystem = _entityManager.System<SolutionContainerSystem>();
|
||||
Target = entity;
|
||||
}
|
||||
|
||||
@@ -39,23 +36,8 @@ namespace Content.Server.Administration.UI
|
||||
|
||||
public override EuiStateBase GetNewState()
|
||||
{
|
||||
List<(string Name, NetEntity Solution)>? netSolutions;
|
||||
|
||||
if (_entityManager.TryGetComponent(Target, out SolutionContainerManagerComponent? container) && container.Containers.Count > 0)
|
||||
{
|
||||
netSolutions = new();
|
||||
foreach (var (name, solution) in _solutionContainerSystem.EnumerateSolutions((Target, container)))
|
||||
{
|
||||
if (name is null || !_entityManager.TryGetNetEntity(solution, out var netSolution))
|
||||
continue;
|
||||
|
||||
netSolutions.Add((name, netSolution.Value));
|
||||
}
|
||||
}
|
||||
else
|
||||
netSolutions = null;
|
||||
|
||||
return new EditSolutionsEuiState(_entityManager.GetNetEntity(Target), netSolutions);
|
||||
var solutions = _entityManager.GetComponentOrNull<SolutionContainerManagerComponent>(Target)?.Solutions;
|
||||
return new EditSolutionsEuiState(_entityManager.GetNetEntity(Target), solutions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Content.Server.Animals.Systems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
|
||||
namespace Content.Server.Animals.Components
|
||||
|
||||
/// <summary>
|
||||
@@ -20,17 +20,11 @@ namespace Content.Server.Animals.Components
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public ProtoId<ReagentPrototype> ReagentId = "Milk";
|
||||
|
||||
/// <summary>
|
||||
/// The name of <see cref="Solution"/>.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public string SolutionName = "udder";
|
||||
|
||||
/// <summary>
|
||||
/// The solution to add reagent to.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public string Solution = "udder";
|
||||
|
||||
/// <summary>
|
||||
/// The amount of reagent to be generated on update.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Animals.Systems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -20,17 +19,11 @@ public sealed partial class WoolyComponent : Component
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public ProtoId<ReagentPrototype> ReagentId = "Fiber";
|
||||
|
||||
/// <summary>
|
||||
/// The name of <see cref="Solution"/>.
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public string SolutionName = "wool";
|
||||
|
||||
/// <summary>
|
||||
/// The solution to add reagent to.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? Solution;
|
||||
[DataField, ViewVariables(VVAccess.ReadOnly)]
|
||||
public string Solution = "wool";
|
||||
|
||||
/// <summary>
|
||||
/// The amount of reagent to be generated on update.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Animals.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
@@ -61,11 +61,11 @@ internal sealed class UdderSystem : EntitySystem
|
||||
_hunger.ModifyHunger(uid, -udder.HungerUsage, hunger);
|
||||
}
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, udder.SolutionName, ref udder.Solution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, udder.Solution, out var solution))
|
||||
continue;
|
||||
|
||||
//TODO: toxins from bloodstream !?
|
||||
_solutionContainerSystem.TryAddReagent(udder.Solution.Value, udder.ReagentId, udder.QuantityPerUpdate, out _);
|
||||
_solutionContainerSystem.TryAddReagent(uid, solution, udder.ReagentId, udder.QuantityPerUpdate, out _);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,50 +85,47 @@ internal sealed class UdderSystem : EntitySystem
|
||||
_doAfterSystem.TryStartDoAfter(doargs);
|
||||
}
|
||||
|
||||
private void OnDoAfter(Entity<UdderComponent> entity, ref MilkingDoAfterEvent args)
|
||||
private void OnDoAfter(EntityUid uid, UdderComponent component, MilkingDoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled || args.Args.Used == null)
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.SolutionName, ref entity.Comp.Solution, out var solution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution))
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSoln, out var targetSolution))
|
||||
if (!_solutionContainerSystem.TryGetRefillableSolution(args.Args.Used.Value, out var targetSolution))
|
||||
return;
|
||||
|
||||
args.Handled = true;
|
||||
var quantity = solution.Volume;
|
||||
if (quantity == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), entity.Owner, args.Args.User);
|
||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-dry"), uid, args.Args.User);
|
||||
return;
|
||||
}
|
||||
|
||||
if (quantity > targetSolution.AvailableVolume)
|
||||
quantity = targetSolution.AvailableVolume;
|
||||
|
||||
var split = _solutionContainerSystem.SplitSolution(entity.Comp.Solution.Value, quantity);
|
||||
_solutionContainerSystem.TryAddSolution(targetSoln.Value, split);
|
||||
var split = _solutionContainerSystem.SplitSolution(uid, solution, quantity);
|
||||
_solutionContainerSystem.TryAddSolution(args.Args.Used.Value, targetSolution, split);
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), entity.Owner,
|
||||
_popupSystem.PopupEntity(Loc.GetString("udder-system-success", ("amount", quantity), ("target", Identity.Entity(args.Args.Used.Value, EntityManager))), uid,
|
||||
args.Args.User, PopupType.Medium);
|
||||
}
|
||||
|
||||
private void AddMilkVerb(Entity<UdderComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
private void AddMilkVerb(EntityUid uid, UdderComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (args.Using == null ||
|
||||
!args.CanInteract ||
|
||||
!EntityManager.HasComponent<RefillableSolutionComponent>(args.Using.Value))
|
||||
return;
|
||||
|
||||
var uid = entity.Owner;
|
||||
var user = args.User;
|
||||
var used = args.Using.Value;
|
||||
AlternativeVerb verb = new()
|
||||
{
|
||||
Act = () =>
|
||||
{
|
||||
AttemptMilk(uid, user, used);
|
||||
AttemptMilk(uid, args.User, args.Using.Value);
|
||||
},
|
||||
Text = Loc.GetString("udder-system-verb-milk"),
|
||||
Priority = 2
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Content.Server.Animals.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Nutrition;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Nutrition.Components;
|
||||
using Content.Shared.Nutrition.EntitySystems;
|
||||
@@ -52,10 +52,10 @@ public sealed class WoolySystem : EntitySystem
|
||||
_hunger.ModifyHunger(uid, -wooly.HungerUsage, hunger);
|
||||
}
|
||||
|
||||
if (!_solutionContainer.ResolveSolution(uid, wooly.SolutionName, ref wooly.Solution))
|
||||
if (!_solutionContainer.TryGetSolution(uid, wooly.Solution, out var solution))
|
||||
continue;
|
||||
|
||||
_solutionContainer.TryAddReagent(wooly.Solution.Value, wooly.ReagentId, wooly.Quantity, out _);
|
||||
_solutionContainer.TryAddReagent(uid, solution, wooly.ReagentId, wooly.Quantity, out _);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Anomaly.Effects;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -86,17 +85,10 @@ public sealed partial class ReagentProducerAnomalyComponent : Component
|
||||
/// </summary>
|
||||
[DataField, ViewVariables(VVAccess.ReadWrite)]
|
||||
public ProtoId<ReagentPrototype> ProducingReagent = "Water";
|
||||
|
||||
/// <summary>
|
||||
/// Solution name where the substance is generated
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[DataField("solution")]
|
||||
public string SolutionName = "default";
|
||||
|
||||
/// <summary>
|
||||
/// Solution where the substance is generated
|
||||
/// </summary>
|
||||
[DataField("solutionRef")]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
public string Solution = "default";
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Anomaly.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using System.Linq;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
|
||||
namespace Content.Server.Anomaly.Effects;
|
||||
/// <summary>
|
||||
@@ -27,40 +27,41 @@ public sealed class InjectionAnomalySystem : EntitySystem
|
||||
_injectableQuery = GetEntityQuery<InjectableSolutionComponent>();
|
||||
}
|
||||
|
||||
private void OnPulse(Entity<InjectionAnomalyComponent> entity, ref AnomalyPulseEvent args)
|
||||
private void OnPulse(EntityUid uid, InjectionAnomalyComponent component, ref AnomalyPulseEvent args)
|
||||
{
|
||||
PulseScalableEffect(entity, entity.Comp.InjectRadius, entity.Comp.MaxSolutionInjection * args.Severity);
|
||||
PulseScalableEffect(uid, component, component.InjectRadius, component.MaxSolutionInjection * args.Severity);
|
||||
}
|
||||
|
||||
private void OnSupercritical(Entity<InjectionAnomalyComponent> entity, ref AnomalySupercriticalEvent args)
|
||||
private void OnSupercritical(EntityUid uid, InjectionAnomalyComponent component, ref AnomalySupercriticalEvent args)
|
||||
{
|
||||
PulseScalableEffect(entity, entity.Comp.SuperCriticalInjectRadius, entity.Comp.SuperCriticalSolutionInjection);
|
||||
PulseScalableEffect(uid, component, component.SuperCriticalInjectRadius, component.SuperCriticalSolutionInjection);
|
||||
}
|
||||
|
||||
private void PulseScalableEffect(Entity<InjectionAnomalyComponent> entity, float injectRadius, float maxInject)
|
||||
private void PulseScalableEffect(EntityUid uid, InjectionAnomalyComponent component, float injectRadius, float maxInject)
|
||||
{
|
||||
if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol))
|
||||
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol))
|
||||
return;
|
||||
|
||||
//We get all the entity in the radius into which the reagent will be injected.
|
||||
var xformQuery = GetEntityQuery<TransformComponent>();
|
||||
var xform = xformQuery.GetComponent(entity);
|
||||
var xform = xformQuery.GetComponent(uid);
|
||||
var allEnts = _lookup.GetEntitiesInRange<InjectableSolutionComponent>(xform.MapPosition, injectRadius)
|
||||
.Select(x => x.Owner).ToList();
|
||||
|
||||
//for each matching entity found
|
||||
foreach (var ent in allEnts)
|
||||
{
|
||||
if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable, out _))
|
||||
if (!_solutionContainer.TryGetInjectableSolution(ent, out var injectable))
|
||||
continue;
|
||||
|
||||
if (_injectableQuery.TryGetComponent(ent, out var injEnt))
|
||||
{
|
||||
_solutionContainer.TryTransferSolution(injectable.Value, sol, maxInject);
|
||||
var buffer = sol;
|
||||
_solutionContainer.TryTransferSolution(ent, injectable, buffer, maxInject);
|
||||
//Spawn Effect
|
||||
var uidXform = Transform(ent);
|
||||
Spawn(entity.Comp.VisualEffectPrototype, uidXform.Coordinates);
|
||||
Spawn(component.VisualEffectPrototype, uidXform.Coordinates);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Anomaly.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
|
||||
namespace Content.Server.Anomaly.Effects;
|
||||
|
||||
@@ -19,21 +19,21 @@ public sealed class PuddleCreateAnomalySystem : EntitySystem
|
||||
SubscribeLocalEvent<PuddleCreateAnomalyComponent, AnomalySupercriticalEvent>(OnSupercritical, before: new[] { typeof(InjectionAnomalySystem) });
|
||||
}
|
||||
|
||||
private void OnPulse(Entity<PuddleCreateAnomalyComponent> entity, ref AnomalyPulseEvent args)
|
||||
private void OnPulse(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalyPulseEvent args)
|
||||
{
|
||||
if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out var sol, out _))
|
||||
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol))
|
||||
return;
|
||||
|
||||
var xform = Transform(entity.Owner);
|
||||
var puddleSol = _solutionContainer.SplitSolution(sol.Value, entity.Comp.MaxPuddleSize * args.Severity);
|
||||
_puddle.TrySplashSpillAt(entity.Owner, xform.Coordinates, puddleSol, out _);
|
||||
var xform = Transform(uid);
|
||||
var puddleSol = _solutionContainer.SplitSolution(uid, sol, component.MaxPuddleSize * args.Severity);
|
||||
_puddle.TrySplashSpillAt(uid, xform.Coordinates, puddleSol, out _);
|
||||
}
|
||||
private void OnSupercritical(Entity<PuddleCreateAnomalyComponent> entity, ref AnomalySupercriticalEvent args)
|
||||
private void OnSupercritical(EntityUid uid, PuddleCreateAnomalyComponent component, ref AnomalySupercriticalEvent args)
|
||||
{
|
||||
if (!_solutionContainer.TryGetSolution(entity.Owner, entity.Comp.Solution, out _, out var sol))
|
||||
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var sol))
|
||||
return;
|
||||
|
||||
var xform = Transform(entity.Owner);
|
||||
_puddle.TrySpillAt(xform.Coordinates, sol, out _);
|
||||
var buffer = sol;
|
||||
var xform = Transform(uid);
|
||||
_puddle.TrySpillAt(xform.Coordinates, buffer, out _);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Content.Server.Anomaly.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Anomaly.Components;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Content.Shared.Sprite;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server.Anomaly.Effects;
|
||||
|
||||
@@ -42,17 +42,17 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
SubscribeLocalEvent<ReagentProducerAnomalyComponent, MapInitEvent>(OnMapInit);
|
||||
}
|
||||
|
||||
private void OnPulse(Entity<ReagentProducerAnomalyComponent> entity, ref AnomalyPulseEvent args)
|
||||
private void OnPulse(EntityUid uid, ReagentProducerAnomalyComponent component, ref AnomalyPulseEvent args)
|
||||
{
|
||||
if (_random.NextFloat(0.0f, 1.0f) > args.Stability)
|
||||
ChangeReagent(entity, args.Severity);
|
||||
ChangeReagent(uid, component, args.Severity);
|
||||
}
|
||||
|
||||
private void ChangeReagent(Entity<ReagentProducerAnomalyComponent> entity, float severity)
|
||||
private void ChangeReagent(EntityUid uid, ReagentProducerAnomalyComponent component, float severity)
|
||||
{
|
||||
var reagent = GetRandomReagentType(entity, severity);
|
||||
entity.Comp.ProducingReagent = reagent;
|
||||
_audio.PlayPvs(entity.Comp.ChangeSound, entity);
|
||||
var reagent = GetRandomReagentType(uid, component, severity);
|
||||
component.ProducingReagent = reagent;
|
||||
_audio.PlayPvs(component.ChangeSound, uid);
|
||||
}
|
||||
|
||||
//reagent realtime generation
|
||||
@@ -68,7 +68,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
if (component.AccumulatedFrametime < component.UpdateInterval)
|
||||
continue;
|
||||
|
||||
if (!_solutionContainer.ResolveSolution(uid, component.SolutionName, ref component.Solution, out var producerSolution))
|
||||
if (!_solutionContainer.TryGetSolution(uid, component.Solution, out var producerSol))
|
||||
continue;
|
||||
|
||||
Solution newSol = new();
|
||||
@@ -76,7 +76,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
if (anomaly.Severity >= 0.97) reagentProducingAmount *= component.SupercriticalReagentProducingModifier;
|
||||
|
||||
newSol.AddReagent(component.ProducingReagent, reagentProducingAmount);
|
||||
_solutionContainer.TryAddSolution(component.Solution.Value, newSol); //TO DO - the container is not fully filled.
|
||||
_solutionContainer.TryAddSolution(uid, producerSol, newSol); //TO DO - the container is not fully filled.
|
||||
|
||||
component.AccumulatedFrametime = 0;
|
||||
|
||||
@@ -87,7 +87,7 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
// and nothing worked out for me. So for now it will be like this.
|
||||
if (component.NeedRecolor)
|
||||
{
|
||||
var color = producerSolution.GetColor(_prototypeManager);
|
||||
var color = producerSol.GetColor(_prototypeManager);
|
||||
_light.SetColor(uid, color);
|
||||
if (TryComp<RandomSpriteComponent>(uid, out var randomSprite))
|
||||
{
|
||||
@@ -103,9 +103,9 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<ReagentProducerAnomalyComponent> entity, ref MapInitEvent args)
|
||||
private void OnMapInit(EntityUid uid, ReagentProducerAnomalyComponent component, MapInitEvent args)
|
||||
{
|
||||
ChangeReagent(entity, 0.1f); //MapInit Reagent 100% change
|
||||
ChangeReagent(uid, component, 0.1f); //MapInit Reagent 100% change
|
||||
}
|
||||
|
||||
// returns a random reagent based on a system of random weights.
|
||||
@@ -117,33 +117,33 @@ public sealed class ReagentProducerAnomalySystem : EntitySystem
|
||||
// After that, a random reagent in the selected category is selected.
|
||||
//
|
||||
// Such a system is made to control the danger and interest of the anomaly more.
|
||||
private string GetRandomReagentType(Entity<ReagentProducerAnomalyComponent> entity, float severity)
|
||||
private string GetRandomReagentType(EntityUid uid, ReagentProducerAnomalyComponent component, float severity)
|
||||
{
|
||||
//Category Weight Randomization
|
||||
var currentWeightDangerous = MathHelper.Lerp(entity.Comp.WeightSpreadDangerous.X, entity.Comp.WeightSpreadDangerous.Y, severity);
|
||||
var currentWeightFun = MathHelper.Lerp(entity.Comp.WeightSpreadFun.X, entity.Comp.WeightSpreadFun.Y, severity);
|
||||
var currentWeightUseful = MathHelper.Lerp(entity.Comp.WeightSpreadUseful.X, entity.Comp.WeightSpreadUseful.Y, severity);
|
||||
var currentWeightDangerous = MathHelper.Lerp(component.WeightSpreadDangerous.X, component.WeightSpreadDangerous.Y, severity);
|
||||
var currentWeightFun = MathHelper.Lerp(component.WeightSpreadFun.X, component.WeightSpreadFun.Y, severity);
|
||||
var currentWeightUseful = MathHelper.Lerp(component.WeightSpreadUseful.X, component.WeightSpreadUseful.Y, severity);
|
||||
|
||||
var sumWeight = currentWeightDangerous + currentWeightFun + currentWeightUseful;
|
||||
var rnd = _random.NextFloat(0f, sumWeight);
|
||||
//Dangerous
|
||||
if (rnd <= currentWeightDangerous && entity.Comp.DangerousChemicals.Count > 0)
|
||||
if (rnd <= currentWeightDangerous && component.DangerousChemicals.Count > 0)
|
||||
{
|
||||
var reagent = _random.Pick(entity.Comp.DangerousChemicals);
|
||||
var reagent = _random.Pick(component.DangerousChemicals);
|
||||
return reagent;
|
||||
}
|
||||
else rnd -= currentWeightDangerous;
|
||||
//Fun
|
||||
if (rnd <= currentWeightFun && entity.Comp.FunChemicals.Count > 0)
|
||||
if (rnd <= currentWeightFun && component.FunChemicals.Count > 0)
|
||||
{
|
||||
var reagent = _random.Pick(entity.Comp.FunChemicals);
|
||||
var reagent = _random.Pick(component.FunChemicals);
|
||||
return reagent;
|
||||
}
|
||||
else rnd -= currentWeightFun;
|
||||
//Useful
|
||||
if (rnd <= currentWeightUseful && entity.Comp.UsefulChemicals.Count > 0)
|
||||
if (rnd <= currentWeightUseful && component.UsefulChemicals.Count > 0)
|
||||
{
|
||||
var reagent = _random.Pick(entity.Comp.UsefulChemicals);
|
||||
var reagent = _random.Pick(component.UsefulChemicals);
|
||||
return reagent;
|
||||
}
|
||||
//We should never end up here.
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Atmos.Piping.Unary.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.Components;
|
||||
|
||||
@@ -22,12 +21,6 @@ public sealed partial class GasCondenserComponent : Component
|
||||
[DataField]
|
||||
public string SolutionId = "tank";
|
||||
|
||||
/// <summary>
|
||||
/// The solution that gases are condensed into.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
|
||||
/// <summary>
|
||||
/// For a condenser, how many U of reagents are given per each mole of gas.
|
||||
/// </summary>
|
||||
|
||||
@@ -5,11 +5,10 @@ using Content.Server.NodeContainer;
|
||||
using Content.Server.NodeContainer.EntitySystems;
|
||||
using Content.Server.NodeContainer.Nodes;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
|
||||
namespace Content.Server.Atmos.Piping.Unary.EntitySystems;
|
||||
|
||||
@@ -19,7 +18,7 @@ public sealed class GasCondenserSystem : EntitySystem
|
||||
[Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!;
|
||||
[Dependency] private readonly PowerReceiverSystem _power = default!;
|
||||
[Dependency] private readonly NodeContainerSystem _nodeContainer = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solution = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solution = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -28,12 +27,12 @@ public sealed class GasCondenserSystem : EntitySystem
|
||||
SubscribeLocalEvent<GasCondenserComponent, AtmosDeviceUpdateEvent>(OnCondenserUpdated);
|
||||
}
|
||||
|
||||
private void OnCondenserUpdated(Entity<GasCondenserComponent> entity, ref AtmosDeviceUpdateEvent args)
|
||||
private void OnCondenserUpdated(EntityUid uid, GasCondenserComponent component, ref AtmosDeviceUpdateEvent args)
|
||||
{
|
||||
if (!(_power.IsPowered(entity) && TryComp<ApcPowerReceiverComponent>(entity, out var receiver))
|
||||
|| !TryComp<NodeContainerComponent>(entity, out var nodeContainer)
|
||||
|| !_nodeContainer.TryGetNode(nodeContainer, entity.Comp.Inlet, out PipeNode? inlet)
|
||||
|| !_solution.ResolveSolution(entity.Owner, entity.Comp.SolutionId, ref entity.Comp.Solution, out var solution))
|
||||
if (!(_power.IsPowered(uid) && TryComp<ApcPowerReceiverComponent>(uid, out var receiver))
|
||||
|| !TryComp<NodeContainerComponent>(uid, out var nodeContainer)
|
||||
|| !_nodeContainer.TryGetNode(nodeContainer, component.Inlet, out PipeNode? inlet)
|
||||
|| !_solution.TryGetSolution(uid, component.SolutionId, out var solution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -49,21 +48,18 @@ public sealed class GasCondenserSystem : EntitySystem
|
||||
if (moles <= 0)
|
||||
continue;
|
||||
|
||||
if (_atmosphereSystem.GetGas(i).Reagent is not { } gasReagent)
|
||||
if (_atmosphereSystem.GetGas(i).Reagent is not {} gasReagent)
|
||||
continue;
|
||||
|
||||
var moleToReagentMultiplier = entity.Comp.MolesToReagentMultiplier;
|
||||
var amount = FixedPoint2.Min(FixedPoint2.New(moles * moleToReagentMultiplier), solution.AvailableVolume);
|
||||
if (amount <= 0)
|
||||
continue;
|
||||
var moleToReagentMultiplier = component.MolesToReagentMultiplier;
|
||||
var amount = moles * moleToReagentMultiplier;
|
||||
|
||||
solution.AddReagent(gasReagent, amount);
|
||||
if (_solution.TryAddReagent(uid, solution, gasReagent, amount, out var remaining))
|
||||
continue;
|
||||
|
||||
// if we have leftover reagent, then convert it back to moles and put it back in the mixture.
|
||||
inlet.Air.AdjustMoles(i, moles - (amount.Float() / moleToReagentMultiplier));
|
||||
inlet.Air.AdjustMoles(i, remaining.Float() / moleToReagentMultiplier);
|
||||
}
|
||||
|
||||
_solution.UpdateChemicals(entity.Comp.Solution.Value);
|
||||
}
|
||||
|
||||
public float NumberOfMolesToConvert(ApcPowerReceiverComponent comp, GasMixture mix, float dt)
|
||||
|
||||
@@ -34,52 +34,52 @@ namespace Content.Server.Body.Components
|
||||
/// <summary>
|
||||
/// How much should bleeding should be reduced every update interval?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bleedReductionAmount")]
|
||||
public float BleedReductionAmount = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// How high can <see cref="BleedAmount"/> go?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("maxBleedAmount")]
|
||||
public float MaxBleedAmount = 10.0f;
|
||||
|
||||
/// <summary>
|
||||
/// What percentage of current blood is necessary to avoid dealing blood loss damage?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bloodlossThreshold")]
|
||||
public float BloodlossThreshold = 0.9f;
|
||||
|
||||
/// <summary>
|
||||
/// The base bloodloss damage to be incurred if below <see cref="BloodlossThreshold"/>
|
||||
/// The default values are defined per mob/species in YML.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
[DataField("bloodlossDamage", required: true)]
|
||||
public DamageSpecifier BloodlossDamage = new();
|
||||
|
||||
/// <summary>
|
||||
/// The base bloodloss damage to be healed if above <see cref="BloodlossThreshold"/>
|
||||
/// The default values are defined per mob/species in YML.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
[DataField("bloodlossHealDamage", required: true)]
|
||||
public DamageSpecifier BloodlossHealDamage = new();
|
||||
|
||||
/// <summary>
|
||||
/// How frequently should this bloodstream update, in seconds?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("updateInterval")]
|
||||
public float UpdateInterval = 3.0f;
|
||||
|
||||
// TODO shouldn't be hardcoded, should just use some organ simulation like bone marrow or smth.
|
||||
/// <summary>
|
||||
/// How much reagent of blood should be restored each update interval?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bloodRefreshAmount")]
|
||||
public float BloodRefreshAmount = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// How much blood needs to be in the temporary solution in order to create a puddle?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bleedPuddleThreshold")]
|
||||
public FixedPoint2 BleedPuddleThreshold = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
@@ -89,19 +89,19 @@ namespace Content.Server.Body.Components
|
||||
/// <remarks>
|
||||
/// For example, piercing damage is increased while poison damage is nullified entirely.
|
||||
/// </remarks>
|
||||
[DataField(customTypeSerializer:typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
|
||||
[DataField("damageBleedModifiers", customTypeSerializer:typeof(PrototypeIdSerializer<DamageModifierSetPrototype>))]
|
||||
public string DamageBleedModifiers = "BloodlossHuman";
|
||||
|
||||
/// <summary>
|
||||
/// The sound to be played when a weapon instantly deals blood loss damage.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("instantBloodSound")]
|
||||
public SoundSpecifier InstantBloodSound = new SoundCollectionSpecifier("blood");
|
||||
|
||||
/// <summary>
|
||||
/// The sound to be played when some damage actually heals bleeding rather than starting it.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bloodHealedSound")]
|
||||
public SoundSpecifier BloodHealedSound = new SoundPathSpecifier("/Audio/Effects/lightburn.ogg");
|
||||
|
||||
// TODO probably damage bleed thresholds.
|
||||
@@ -109,14 +109,14 @@ namespace Content.Server.Body.Components
|
||||
/// <summary>
|
||||
/// Max volume of internal chemical solution storage
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("chemicalMaxVolume")]
|
||||
public FixedPoint2 ChemicalMaxVolume = FixedPoint2.New(250);
|
||||
|
||||
/// <summary>
|
||||
/// Max volume of internal blood storage,
|
||||
/// and starting level of blood.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bloodMaxVolume")]
|
||||
public FixedPoint2 BloodMaxVolume = FixedPoint2.New(300);
|
||||
|
||||
/// <summary>
|
||||
@@ -125,40 +125,29 @@ namespace Content.Server.Body.Components
|
||||
/// <remarks>
|
||||
/// Slime-people might use slime as their blood or something like that.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[DataField("bloodReagent")]
|
||||
public string BloodReagent = "Blood";
|
||||
|
||||
/// <summary>Name/Key that <see cref="BloodSolution"/> is indexed by.</summary>
|
||||
[DataField]
|
||||
public string BloodSolutionName = DefaultBloodSolutionName;
|
||||
|
||||
/// <summary>Name/Key that <see cref="ChemicalSolution"/> is indexed by.</summary>
|
||||
[DataField]
|
||||
public string ChemicalSolutionName = DefaultChemicalsSolutionName;
|
||||
|
||||
/// <summary>Name/Key that <see cref="TemporarySolution"/> is indexed by.</summary>
|
||||
[DataField]
|
||||
public string BloodTemporarySolutionName = DefaultBloodTemporarySolutionName;
|
||||
|
||||
/// <summary>
|
||||
/// Internal solution for blood storage
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? BloodSolution = null;
|
||||
|
||||
/// <summary>
|
||||
/// Internal solution for reagent storage
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? ChemicalSolution = null;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
[Access(typeof(BloodstreamSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
public Solution ChemicalSolution = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Internal solution for blood storage
|
||||
/// </summary>
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Solution BloodSolution = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Temporary blood solution.
|
||||
/// When blood is lost, it goes to this solution, and when this
|
||||
/// solution hits a certain cap, the blood is actually spilled as a puddle.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? TemporarySolution = null;
|
||||
[ViewVariables(VVAccess.ReadWrite)]
|
||||
public Solution BloodTemporarySolution = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Variable that stores the amount of status time added by having a low blood level.
|
||||
|
||||
@@ -8,7 +8,7 @@ namespace Content.Server.Body.Components;
|
||||
[RegisterComponent, Access(typeof(LungSystem))]
|
||||
public sealed partial class LungComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
[DataField("air")]
|
||||
[Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
public GasMixture Air { get; set; } = new()
|
||||
{
|
||||
@@ -16,15 +16,7 @@ public sealed partial class LungComponent : Component
|
||||
Temperature = Atmospherics.NormalBodyTemperature
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// The name/key of the solution on this entity which these lungs act on.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public string SolutionName = LungSystem.LungSolutionName;
|
||||
|
||||
/// <summary>
|
||||
/// The solution on this entity that these lungs act on.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
[ViewVariables]
|
||||
[Access(typeof(LungSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
public Solution LungSolution = default!;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace Content.Server.Body.Components
|
||||
/// How often to metabolize reagents, in seconds.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
[DataField]
|
||||
[DataField("updateFrequency")]
|
||||
public float UpdateFrequency = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
@@ -33,13 +33,13 @@ namespace Content.Server.Body.Components
|
||||
/// <remarks>
|
||||
/// Most things will use the parent entity (bloodstream).
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[DataField("solutionOnBody")]
|
||||
public bool SolutionOnBody = true;
|
||||
|
||||
/// <summary>
|
||||
/// List of metabolizer types that this organ is. ex. Human, Slime, Felinid, w/e.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer:typeof(PrototypeIdHashSetSerializer<MetabolizerTypePrototype>))]
|
||||
[DataField("metabolizerTypes", customTypeSerializer:typeof(PrototypeIdHashSetSerializer<MetabolizerTypePrototype>))]
|
||||
[Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends
|
||||
public HashSet<string>? MetabolizerTypes = null;
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace Content.Server.Body.Components
|
||||
/// Should this metabolizer remove chemicals that have no metabolisms defined?
|
||||
/// As a stop-gap, basically.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("removeEmpty")]
|
||||
public bool RemoveEmpty = false;
|
||||
|
||||
/// <summary>
|
||||
@@ -72,7 +72,7 @@ namespace Content.Server.Body.Components
|
||||
[DataDefinition]
|
||||
public sealed partial class MetabolismGroupEntry
|
||||
{
|
||||
[DataField(required: true, customTypeSerializer:typeof(PrototypeIdSerializer<MetabolismGroupPrototype>))]
|
||||
[DataField("id", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<MetabolismGroupPrototype>))]
|
||||
public string Id = default!;
|
||||
|
||||
[DataField("rateModifier")]
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
using Content.Server.Nutrition.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Whitelist;
|
||||
|
||||
namespace Content.Server.Body.Components
|
||||
@@ -14,32 +15,26 @@ namespace Content.Server.Body.Components
|
||||
/// <summary>
|
||||
/// How fast should this component update, in seconds?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("updateInterval")]
|
||||
public float UpdateInterval = 1.0f;
|
||||
|
||||
/// <summary>
|
||||
/// The solution inside of this stomach this transfers reagents to the body.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
|
||||
/// <summary>
|
||||
/// What solution should this stomach push reagents into, on the body?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("bodySolutionName")]
|
||||
public string BodySolutionName = BloodstreamComponent.DefaultChemicalsSolutionName;
|
||||
|
||||
/// <summary>
|
||||
/// Time in seconds between reagents being ingested and them being
|
||||
/// transferred to <see cref="BloodstreamComponent"/>
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("digestionDelay")]
|
||||
public float DigestionDelay = 20;
|
||||
|
||||
/// <summary>
|
||||
/// A whitelist for what special-digestible-required foods this stomach is capable of eating.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("specialDigestible")]
|
||||
public EntityWhitelist? SpecialDigestible = null;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Chemistry.ReactionEffects;
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Server.Forensics;
|
||||
using Content.Server.HealthExaminable;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Alert;
|
||||
@@ -18,9 +16,13 @@ using Content.Shared.Mobs.Systems;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Rejuvenate;
|
||||
using Content.Shared.Speech.EntitySystems;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Content.Shared.Speech.EntitySystems;
|
||||
using Robust.Server.Audio;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Content.Server.Forensics;
|
||||
|
||||
namespace Content.Server.Body.Systems;
|
||||
|
||||
@@ -49,13 +51,14 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
SubscribeLocalEvent<BloodstreamComponent, BeingGibbedEvent>(OnBeingGibbed);
|
||||
SubscribeLocalEvent<BloodstreamComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||
SubscribeLocalEvent<BloodstreamComponent, ReactionAttemptEvent>(OnReactionAttempt);
|
||||
SubscribeLocalEvent<BloodstreamComponent, SolutionRelayEvent<ReactionAttemptEvent>>(OnReactionAttempt);
|
||||
SubscribeLocalEvent<BloodstreamComponent, RejuvenateEvent>(OnRejuvenate);
|
||||
}
|
||||
|
||||
private void OnReactionAttempt(Entity<BloodstreamComponent> entity, ref ReactionAttemptEvent args)
|
||||
private void OnReactionAttempt(EntityUid uid, BloodstreamComponent component, ReactionAttemptEvent args)
|
||||
{
|
||||
if (args.Cancelled)
|
||||
if (args.Solution.Name != BloodstreamComponent.DefaultBloodSolutionName
|
||||
&& args.Solution.Name != BloodstreamComponent.DefaultChemicalsSolutionName
|
||||
&& args.Solution.Name != BloodstreamComponent.DefaultBloodTemporarySolutionName)
|
||||
return;
|
||||
|
||||
foreach (var effect in args.Reaction.Effects)
|
||||
@@ -64,7 +67,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
{
|
||||
case CreateEntityReactionEffect: // Prevent entities from spawning in the bloodstream
|
||||
case AreaReactionEffect: // No spontaneous smoke or foam leaking out of blood vessels.
|
||||
args.Cancelled = true;
|
||||
args.Cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -78,16 +81,6 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
// Having cheese-clots form in your veins can't be good for you.
|
||||
}
|
||||
|
||||
private void OnReactionAttempt(Entity<BloodstreamComponent> entity, ref SolutionRelayEvent<ReactionAttemptEvent> args)
|
||||
{
|
||||
if (args.Name != entity.Comp.BloodSolutionName
|
||||
&& args.Name != entity.Comp.ChemicalSolutionName
|
||||
&& args.Name != entity.Comp.BloodTemporarySolutionName)
|
||||
return;
|
||||
|
||||
OnReactionAttempt(entity, ref args.Event);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
@@ -102,11 +95,8 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
|
||||
bloodstream.AccumulatedFrametime -= bloodstream.UpdateInterval;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, bloodstream.BloodSolutionName, ref bloodstream.BloodSolution, out var bloodSolution))
|
||||
continue;
|
||||
|
||||
// Adds blood to their blood level if it is below the maximum; Blood regeneration. Must be alive.
|
||||
if (bloodSolution.Volume < bloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
|
||||
if (bloodstream.BloodSolution.Volume < bloodstream.BloodSolution.MaxVolume && !_mobStateSystem.IsDead(uid))
|
||||
{
|
||||
TryModifyBloodLevel(uid, bloodstream.BloodRefreshAmount, bloodstream);
|
||||
}
|
||||
@@ -153,18 +143,19 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComponentInit(Entity<BloodstreamComponent> entity, ref ComponentInit args)
|
||||
private void OnComponentInit(EntityUid uid, BloodstreamComponent component, ComponentInit args)
|
||||
{
|
||||
var chemicalSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.ChemicalSolutionName);
|
||||
var bloodSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.BloodSolutionName);
|
||||
var tempSolution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.BloodTemporarySolutionName);
|
||||
component.ChemicalSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultChemicalsSolutionName);
|
||||
component.BloodSolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodSolutionName);
|
||||
component.BloodTemporarySolution = _solutionContainerSystem.EnsureSolution(uid, BloodstreamComponent.DefaultBloodTemporarySolutionName);
|
||||
|
||||
chemicalSolution.MaxVolume = entity.Comp.ChemicalMaxVolume;
|
||||
bloodSolution.MaxVolume = entity.Comp.BloodMaxVolume;
|
||||
tempSolution.MaxVolume = entity.Comp.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
|
||||
component.ChemicalSolution.MaxVolume = component.ChemicalMaxVolume;
|
||||
component.BloodSolution.MaxVolume = component.BloodMaxVolume;
|
||||
component.BloodTemporarySolution.MaxVolume = component.BleedPuddleThreshold * 4; // give some leeway, for chemstream as well
|
||||
|
||||
// Fill blood solution with BLOOD
|
||||
bloodSolution.AddReagent(entity.Comp.BloodReagent, entity.Comp.BloodMaxVolume - bloodSolution.Volume);
|
||||
_solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent,
|
||||
component.BloodMaxVolume, out _);
|
||||
}
|
||||
|
||||
private void OnDamageChanged(EntityUid uid, BloodstreamComponent component, DamageChangedEvent args)
|
||||
@@ -259,45 +250,34 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
component.AccumulatedFrametime = component.UpdateInterval;
|
||||
}
|
||||
|
||||
private void OnRejuvenate(Entity<BloodstreamComponent> entity, ref RejuvenateEvent args)
|
||||
private void OnRejuvenate(EntityUid uid, BloodstreamComponent component, RejuvenateEvent args)
|
||||
{
|
||||
TryModifyBleedAmount(entity.Owner, -entity.Comp.BleedAmount, entity.Comp);
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.BloodSolutionName, ref entity.Comp.BloodSolution, out var bloodSolution))
|
||||
TryModifyBloodLevel(entity.Owner, bloodSolution.AvailableVolume, entity.Comp);
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(entity.Owner, entity.Comp.ChemicalSolutionName, ref entity.Comp.ChemicalSolution))
|
||||
_solutionContainerSystem.RemoveAllSolution(entity.Comp.ChemicalSolution.Value);
|
||||
TryModifyBleedAmount(uid, -component.BleedAmount, component);
|
||||
TryModifyBloodLevel(uid, component.BloodSolution.AvailableVolume, component);
|
||||
_solutionContainerSystem.RemoveAllSolution(uid, component.ChemicalSolution);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Attempt to transfer provided solution to internal solution.
|
||||
/// </summary>
|
||||
public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component = null)
|
||||
public bool TryAddToChemicals(EntityUid uid, Solution solution, BloodstreamComponent? component=null)
|
||||
{
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution))
|
||||
return false;
|
||||
|
||||
return _solutionContainerSystem.TryAddSolution(component.ChemicalSolution.Value, solution);
|
||||
return _solutionContainerSystem.TryAddSolution(uid, component.ChemicalSolution, solution);
|
||||
}
|
||||
|
||||
public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null)
|
||||
{
|
||||
public bool FlushChemicals(EntityUid uid, string excludedReagentID, FixedPoint2 quantity, BloodstreamComponent? component = null) {
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
|
||||
return false;
|
||||
|
||||
for (var i = chemSolution.Contents.Count - 1; i >= 0; i--)
|
||||
for (var i = component.ChemicalSolution.Contents.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var (reagentId, _) = chemSolution.Contents[i];
|
||||
var (reagentId, _) = component.ChemicalSolution.Contents[i];
|
||||
if (reagentId.Prototype != excludedReagentID)
|
||||
{
|
||||
_solutionContainerSystem.RemoveReagent(component.ChemicalSolution.Value, reagentId, quantity);
|
||||
_solutionContainerSystem.RemoveReagent(uid, component.ChemicalSolution, reagentId, quantity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,10 +289,7 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component))
|
||||
return 0.0f;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
|
||||
return 0.0f;
|
||||
|
||||
return bloodSolution.FillFraction;
|
||||
return component.BloodSolution.FillFraction;
|
||||
}
|
||||
|
||||
public void SetBloodLossThreshold(EntityUid uid, float threshold, BloodstreamComponent? comp = null)
|
||||
@@ -331,41 +308,28 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution))
|
||||
return false;
|
||||
|
||||
if (amount >= 0)
|
||||
return _solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, amount, out _);
|
||||
return _solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, amount, out _);
|
||||
|
||||
// Removal is more involved,
|
||||
// since we also wanna handle moving it to the temporary solution
|
||||
// and then spilling it if necessary.
|
||||
var newSol = _solutionContainerSystem.SplitSolution(component.BloodSolution.Value, -amount);
|
||||
var newSol = component.BloodSolution.SplitSolution(-amount);
|
||||
component.BloodTemporarySolution.AddSolution(newSol, _prototypeManager);
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution))
|
||||
return true;
|
||||
|
||||
tempSolution.AddSolution(newSol, _prototypeManager);
|
||||
|
||||
if (tempSolution.Volume > component.BleedPuddleThreshold)
|
||||
if (component.BloodTemporarySolution.Volume > component.BleedPuddleThreshold)
|
||||
{
|
||||
// Pass some of the chemstream into the spilled blood.
|
||||
if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution))
|
||||
{
|
||||
var temp = _solutionContainerSystem.SplitSolution(component.ChemicalSolution.Value, tempSolution.Volume / 10);
|
||||
tempSolution.AddSolution(temp, _prototypeManager);
|
||||
}
|
||||
|
||||
if (_puddleSystem.TrySpillAt(uid, tempSolution, out var puddleUid, false))
|
||||
var temp = component.ChemicalSolution.SplitSolution(component.BloodTemporarySolution.Volume / 10);
|
||||
component.BloodTemporarySolution.AddSolution(temp, _prototypeManager);
|
||||
if (_puddleSystem.TrySpillAt(uid, component.BloodTemporarySolution, out var puddleUid, false))
|
||||
{
|
||||
_forensicsSystem.TransferDna(puddleUid, uid, false);
|
||||
}
|
||||
|
||||
tempSolution.RemoveAllSolution();
|
||||
component.BloodTemporarySolution.RemoveAllSolution();
|
||||
}
|
||||
|
||||
_solutionContainerSystem.UpdateChemicals(component.TemporarySolution.Value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -399,28 +363,16 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
var tempSol = new Solution();
|
||||
var max = component.BloodSolution.MaxVolume + component.BloodTemporarySolution.MaxVolume +
|
||||
component.ChemicalSolution.MaxVolume;
|
||||
var tempSol = new Solution() { MaxVolume = max };
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
|
||||
{
|
||||
tempSol.MaxVolume += bloodSolution.MaxVolume;
|
||||
tempSol.AddSolution(bloodSolution, _prototypeManager);
|
||||
_solutionContainerSystem.RemoveAllSolution(component.BloodSolution.Value);
|
||||
}
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(uid, component.ChemicalSolutionName, ref component.ChemicalSolution, out var chemSolution))
|
||||
{
|
||||
tempSol.MaxVolume += chemSolution.MaxVolume;
|
||||
tempSol.AddSolution(chemSolution, _prototypeManager);
|
||||
_solutionContainerSystem.RemoveAllSolution(component.ChemicalSolution.Value);
|
||||
}
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(uid, component.BloodTemporarySolutionName, ref component.TemporarySolution, out var tempSolution))
|
||||
{
|
||||
tempSol.MaxVolume += tempSolution.MaxVolume;
|
||||
tempSol.AddSolution(tempSolution, _prototypeManager);
|
||||
_solutionContainerSystem.RemoveAllSolution(component.TemporarySolution.Value);
|
||||
}
|
||||
tempSol.AddSolution(component.BloodSolution, _prototypeManager);
|
||||
component.BloodSolution.RemoveAllSolution();
|
||||
tempSol.AddSolution(component.BloodTemporarySolution, _prototypeManager);
|
||||
component.BloodTemporarySolution.RemoveAllSolution();
|
||||
tempSol.AddSolution(component.ChemicalSolution, _prototypeManager);
|
||||
component.ChemicalSolution.RemoveAllSolution();
|
||||
|
||||
if (_puddleSystem.TrySpillAt(uid, tempSol, out var puddleUid))
|
||||
{
|
||||
@@ -436,20 +388,13 @@ public sealed class BloodstreamSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component, false))
|
||||
return;
|
||||
|
||||
if (reagent == component.BloodReagent)
|
||||
if(reagent == component.BloodReagent)
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.BloodSolutionName, ref component.BloodSolution, out var bloodSolution))
|
||||
{
|
||||
component.BloodReagent = reagent;
|
||||
return;
|
||||
}
|
||||
|
||||
var currentVolume = bloodSolution.RemoveReagent(component.BloodReagent, bloodSolution.Volume);
|
||||
var currentVolume = component.BloodSolution.Volume;
|
||||
|
||||
component.BloodReagent = reagent;
|
||||
|
||||
if (currentVolume > 0)
|
||||
_solutionContainerSystem.TryAddReagent(component.BloodSolution.Value, component.BloodReagent, currentVolume, out _);
|
||||
component.BloodSolution.RemoveAllSolution();
|
||||
_solutionContainerSystem.TryAddReagent(uid, component.BloodSolution, component.BloodReagent, currentVolume, out _);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Content.Server.Atmos.Components;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Inventory.Events;
|
||||
|
||||
@@ -44,11 +44,11 @@ public sealed class LungSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnComponentInit(Entity<LungComponent> entity, ref ComponentInit args)
|
||||
private void OnComponentInit(EntityUid uid, LungComponent component, ComponentInit args)
|
||||
{
|
||||
var solution = _solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName);
|
||||
solution.MaxVolume = 100.0f;
|
||||
solution.CanReact = false; // No dexalin lungs
|
||||
component.LungSolution = _solutionContainerSystem.EnsureSolution(uid, LungSolutionName);
|
||||
component.LungSolution.MaxVolume = 100.0f;
|
||||
component.LungSolution.CanReact = false; // No dexalin lungs
|
||||
}
|
||||
|
||||
private void OnMaskToggled(Entity<BreathToolComponent> ent, ref ItemMaskToggledEvent args)
|
||||
@@ -71,9 +71,6 @@ public sealed class LungSystem : EntitySystem
|
||||
|
||||
public void GasToReagent(EntityUid uid, LungComponent lung)
|
||||
{
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, lung.SolutionName, ref lung.Solution, out var solution))
|
||||
return;
|
||||
|
||||
foreach (var gas in Enum.GetValues<Gas>())
|
||||
{
|
||||
var i = (int) gas;
|
||||
@@ -84,13 +81,11 @@ public sealed class LungSystem : EntitySystem
|
||||
if (reagent == null) continue;
|
||||
|
||||
var amount = moles * Atmospherics.BreathMolesToReagentMultiplier;
|
||||
solution.AddReagent(reagent, amount);
|
||||
_solutionContainerSystem.TryAddReagent(uid, lung.LungSolution, reagent, amount, out _);
|
||||
|
||||
// We don't remove the gas from the lung mix,
|
||||
// that's the responsibility of whatever gas is being metabolized.
|
||||
// Most things will just want to exhale again.
|
||||
}
|
||||
|
||||
_solutionContainerSystem.UpdateChemicals(lung.Solution.Value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
@@ -37,15 +37,15 @@ namespace Content.Server.Body.Systems
|
||||
SubscribeLocalEvent<MetabolizerComponent, ApplyMetabolicMultiplierEvent>(OnApplyMetabolicMultiplier);
|
||||
}
|
||||
|
||||
private void OnMetabolizerInit(Entity<MetabolizerComponent> entity, ref ComponentInit args)
|
||||
private void OnMetabolizerInit(EntityUid uid, MetabolizerComponent component, ComponentInit args)
|
||||
{
|
||||
if (!entity.Comp.SolutionOnBody)
|
||||
if (!component.SolutionOnBody)
|
||||
{
|
||||
_solutionContainerSystem.EnsureSolution(entity.Owner, entity.Comp.SolutionName);
|
||||
_solutionContainerSystem.EnsureSolution(uid, component.SolutionName);
|
||||
}
|
||||
else if (_organQuery.CompOrNull(entity)?.Body is { } body)
|
||||
else if (_organQuery.CompOrNull(uid)?.Body is { } body)
|
||||
{
|
||||
_solutionContainerSystem.EnsureSolution(body, entity.Comp.SolutionName);
|
||||
_solutionContainerSystem.EnsureSolution(body, component.SolutionName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,7 +95,6 @@ namespace Content.Server.Body.Systems
|
||||
|
||||
// First step is get the solution we actually care about
|
||||
Solution? solution = null;
|
||||
Entity<SolutionComponent>? soln = default!;
|
||||
EntityUid? solutionEntityUid = null;
|
||||
|
||||
SolutionContainerManagerComponent? manager = null;
|
||||
@@ -107,7 +106,7 @@ namespace Content.Server.Body.Systems
|
||||
if (!_solutionQuery.Resolve(body, ref manager, false))
|
||||
return;
|
||||
|
||||
_solutionContainerSystem.TryGetSolution((body, manager), meta.SolutionName, out soln, out solution);
|
||||
_solutionContainerSystem.TryGetSolution(body, meta.SolutionName, out solution, manager);
|
||||
solutionEntityUid = body;
|
||||
}
|
||||
}
|
||||
@@ -116,11 +115,11 @@ namespace Content.Server.Body.Systems
|
||||
if (!_solutionQuery.Resolve(uid, ref manager, false))
|
||||
return;
|
||||
|
||||
_solutionContainerSystem.TryGetSolution((uid, manager), meta.SolutionName, out soln, out solution);
|
||||
_solutionContainerSystem.TryGetSolution(uid, meta.SolutionName, out solution, manager);
|
||||
solutionEntityUid = uid;
|
||||
}
|
||||
|
||||
if (solutionEntityUid == null || soln is null || solution is null || solution.Contents.Count == 0)
|
||||
if (solutionEntityUid == null || solution == null || solution.Contents.Count == 0)
|
||||
return;
|
||||
|
||||
// randomize the reagent list so we don't have any weird quirks
|
||||
@@ -139,7 +138,8 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
if (meta.RemoveEmpty)
|
||||
{
|
||||
solution.RemoveReagent(reagent, FixedPoint2.New(1));
|
||||
_solutionContainerSystem.RemoveReagent(solutionEntityUid.Value, solution, reagent,
|
||||
FixedPoint2.New(1));
|
||||
}
|
||||
|
||||
continue;
|
||||
@@ -198,14 +198,12 @@ namespace Content.Server.Body.Systems
|
||||
// remove a certain amount of reagent
|
||||
if (mostToRemove > FixedPoint2.Zero)
|
||||
{
|
||||
solution.RemoveReagent(reagent, mostToRemove);
|
||||
_solutionContainerSystem.RemoveReagent(solutionEntityUid.Value, solution, reagent, mostToRemove);
|
||||
|
||||
// We have processed a reagant, so count it towards the cap
|
||||
reagents += 1;
|
||||
}
|
||||
}
|
||||
|
||||
_solutionContainerSystem.UpdateChemicals(soln.Value);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ using Content.Server.Administration.Logs;
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Alert;
|
||||
using Content.Shared.Atmos;
|
||||
@@ -27,7 +26,6 @@ namespace Content.Server.Body.Systems
|
||||
[Dependency] private readonly LungSystem _lungSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -146,9 +144,7 @@ namespace Content.Server.Body.Systems
|
||||
{
|
||||
_atmosSys.Merge(outGas, lung.Air);
|
||||
lung.Air.Clear();
|
||||
|
||||
if (_solutionContainerSystem.ResolveSolution(lung.Owner, lung.SolutionName, ref lung.Solution))
|
||||
_solutionContainerSystem.RemoveAllSolution(lung.Solution.Value);
|
||||
lung.LungSolution.RemoveAllSolution();
|
||||
}
|
||||
|
||||
_atmosSys.Merge(ev.Gas, outGas);
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Body.Organ;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Server.Body.Systems
|
||||
@@ -31,7 +31,8 @@ namespace Content.Server.Body.Systems
|
||||
stomach.AccumulatedFrameTime -= stomach.UpdateInterval;
|
||||
|
||||
// Get our solutions
|
||||
if (!_solutionContainerSystem.ResolveSolution((uid, sol), DefaultSolutionName, ref stomach.Solution, out var stomachSolution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName,
|
||||
out var stomachSolution, sol))
|
||||
continue;
|
||||
|
||||
if (organ.Body is not { } body || !_solutionContainerSystem.TryGetSolution(body, stomach.BodySolutionName, out var bodySolution))
|
||||
@@ -50,7 +51,7 @@ namespace Content.Server.Body.Systems
|
||||
if (reagent.Quantity > delta.ReagentQuantity.Quantity)
|
||||
reagent = new(reagent.Reagent, delta.ReagentQuantity.Quantity);
|
||||
|
||||
stomachSolution.RemoveReagent(reagent);
|
||||
_solutionContainerSystem.RemoveReagent(uid, stomachSolution, reagent);
|
||||
transferSolution.AddReagent(reagent);
|
||||
}
|
||||
|
||||
@@ -63,10 +64,8 @@ namespace Content.Server.Body.Systems
|
||||
stomach.ReagentDeltas.Remove(item);
|
||||
}
|
||||
|
||||
_solutionContainerSystem.UpdateChemicals(stomach.Solution.Value);
|
||||
|
||||
// Transfer everything to the body solution!
|
||||
_solutionContainerSystem.TryAddSolution(bodySolution.Value, transferSolution);
|
||||
_solutionContainerSystem.TryAddSolution(body, bodySolution, transferSolution);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,13 +86,12 @@ namespace Content.Server.Body.Systems
|
||||
}
|
||||
|
||||
public bool CanTransferSolution(EntityUid uid, Solution solution,
|
||||
StomachComponent? stomach = null,
|
||||
SolutionContainerManagerComponent? solutions = null)
|
||||
{
|
||||
if (!Resolve(uid, ref stomach, ref solutions, false))
|
||||
if (!Resolve(uid, ref solutions, false))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution, out var stomachSolution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions))
|
||||
return false;
|
||||
|
||||
// TODO: For now no partial transfers. Potentially change by design
|
||||
@@ -110,11 +108,11 @@ namespace Content.Server.Body.Systems
|
||||
if (!Resolve(uid, ref stomach, ref solutions, false))
|
||||
return false;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution((uid, solutions), DefaultSolutionName, ref stomach.Solution)
|
||||
|| !CanTransferSolution(uid, solution, stomach, solutions))
|
||||
if (!_solutionContainerSystem.TryGetSolution(uid, DefaultSolutionName, out var stomachSolution, solutions)
|
||||
|| !CanTransferSolution(uid, solution, solutions))
|
||||
return false;
|
||||
|
||||
_solutionContainerSystem.TryAddSolution(stomach.Solution.Value, solution);
|
||||
_solutionContainerSystem.TryAddSolution(uid, stomachSolution, solution);
|
||||
// Add each reagent to ReagentDeltas. Used to track how long each reagent has been in the stomach
|
||||
foreach (var reagent in solution.Contents)
|
||||
{
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Server.Botany.Components;
|
||||
@@ -91,7 +90,4 @@ public sealed partial class PlantHolderComponent : Component
|
||||
|
||||
[ViewVariables(VVAccess.ReadWrite), DataField("solution")]
|
||||
public string SoilSolutionName = "soil";
|
||||
|
||||
[DataField]
|
||||
public Entity<SolutionComponent>? SoilSolution = null;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Server.GameObjects;
|
||||
|
||||
namespace Content.Server.Botany.Systems;
|
||||
|
||||
@@ -10,7 +11,7 @@ public sealed partial class BotanySystem
|
||||
if (!TryGetSeed(produce, out var seed))
|
||||
return;
|
||||
|
||||
var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName, FixedPoint2.Zero, out _);
|
||||
var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName);
|
||||
|
||||
solutionContainer.RemoveAllSolution();
|
||||
foreach (var (chem, quantity) in seed.Chemicals)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Botany;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Examine;
|
||||
using Content.Shared.Hands.EntitySystems;
|
||||
using Content.Shared.Physics;
|
||||
@@ -18,8 +20,6 @@ using Robust.Shared.Physics.Components;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Botany.Systems;
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Content.Server.Atmos;
|
||||
using Content.Server.Atmos.EntitySystems;
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Fluids.Components;
|
||||
using Content.Server.Ghost.Roles.Components;
|
||||
using Content.Server.Kitchen.Components;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Botany;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Examine;
|
||||
@@ -38,7 +38,7 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
[Dependency] private readonly PopupSystem _popup = default!;
|
||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
||||
[Dependency] private readonly SharedPointLightSystem _pointLight = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly TagSystem _tagSystem = default!;
|
||||
[Dependency] private readonly RandomHelperSystem _randomHelper = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
@@ -70,13 +70,11 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExamine(Entity<PlantHolderComponent> entity, ref ExaminedEvent args)
|
||||
private void OnExamine(EntityUid uid, PlantHolderComponent component, ExaminedEvent args)
|
||||
{
|
||||
if (!args.IsInDetailsRange)
|
||||
return;
|
||||
|
||||
var (_, component) = entity;
|
||||
|
||||
if (component.Seed == null)
|
||||
{
|
||||
args.PushMarkup(Loc.GetString("plant-holder-component-nothing-planted-message"));
|
||||
@@ -133,10 +131,8 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInteractUsing(Entity<PlantHolderComponent> entity, ref InteractUsingEvent args)
|
||||
private void OnInteractUsing(EntityUid uid, PlantHolderComponent component, InteractUsingEvent args)
|
||||
{
|
||||
var (uid, component) = entity;
|
||||
|
||||
if (TryComp(args.Used, out SeedComponent? seeds))
|
||||
{
|
||||
if (component.Seed == null)
|
||||
@@ -207,8 +203,8 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (_solutionContainerSystem.TryGetDrainableSolution(args.Used, out var solution, out _)
|
||||
&& _solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution)
|
||||
if (_solutionSystem.TryGetDrainableSolution(args.Used, out var solution)
|
||||
&& _solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var targetSolution)
|
||||
&& TryComp(args.Used, out SprayComponent? spray))
|
||||
{
|
||||
var amount = FixedPoint2.New(1);
|
||||
@@ -218,7 +214,7 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
|
||||
_audio.PlayPvs(spray.SpraySound, args.Used, AudioParams.Default.WithVariation(0.125f));
|
||||
|
||||
var split = _solutionContainerSystem.Drain(solutionEntity, solution.Value, amount);
|
||||
var split = _solutionSystem.Drain(solutionEntity, solution, amount);
|
||||
|
||||
if (split.Volume == 0)
|
||||
{
|
||||
@@ -231,7 +227,7 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
("owner", uid),
|
||||
("amount", split.Volume)), args.User, PopupType.Medium);
|
||||
|
||||
_solutionContainerSystem.TryAddSolution(component.SoilSolution.Value, split);
|
||||
_solutionSystem.TryAddSolution(targetEntity, targetSolution, split);
|
||||
|
||||
ForceUpdateByExternalCause(uid, component);
|
||||
|
||||
@@ -294,15 +290,16 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
("usingItem", args.Used),
|
||||
("owner", uid)), uid, Filter.PvsExcept(args.User), true);
|
||||
|
||||
if (_solutionContainerSystem.TryGetSolution(args.Used, produce.SolutionName, out var soln2, out var solution2))
|
||||
if (_solutionSystem.TryGetSolution(args.Used, produce.SolutionName, out var solution2))
|
||||
{
|
||||
if (_solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution, out var solution1))
|
||||
if (_solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var solution1))
|
||||
{
|
||||
// We try to fit as much of the composted plant's contained solution into the hydroponics tray as we can,
|
||||
// since the plant will be consumed anyway.
|
||||
|
||||
var fillAmount = FixedPoint2.Min(solution2.Volume, solution1.AvailableVolume);
|
||||
_solutionContainerSystem.TryAddSolution(component.SoilSolution.Value, _solutionContainerSystem.SplitSolution(soln2.Value, fillAmount));
|
||||
_solutionSystem.TryAddSolution(uid, solution1,
|
||||
_solutionSystem.SplitSolution(args.Used, solution2, fillAmount));
|
||||
|
||||
ForceUpdateByExternalCause(uid, component);
|
||||
}
|
||||
@@ -317,9 +314,9 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnInteractHand(Entity<PlantHolderComponent> entity, ref InteractHandEvent args)
|
||||
private void OnInteractHand(EntityUid uid, PlantHolderComponent component, InteractHandEvent args)
|
||||
{
|
||||
DoHarvest(entity, args.User, entity.Comp);
|
||||
DoHarvest(uid, args.User, component);
|
||||
}
|
||||
|
||||
public void WeedInvasion()
|
||||
@@ -822,13 +819,13 @@ public sealed class PlantHolderSystem : EntitySystem
|
||||
if (!Resolve(uid, ref component))
|
||||
return;
|
||||
|
||||
if (!_solutionContainerSystem.ResolveSolution(uid, component.SoilSolutionName, ref component.SoilSolution, out var solution))
|
||||
if (!_solutionSystem.TryGetSolution(uid, component.SoilSolutionName, out var solution))
|
||||
return;
|
||||
|
||||
if (solution.Volume > 0 && component.MutationLevel < 25)
|
||||
{
|
||||
var amt = FixedPoint2.New(1);
|
||||
foreach (var entry in _solutionContainerSystem.RemoveEachReagent(component.SoilSolution.Value, amt))
|
||||
foreach (var entry in _solutionSystem.RemoveEachReagent(uid, solution, amt))
|
||||
{
|
||||
var reagentProto = _prototype.Index<ReagentPrototype>(entry.Reagent.Prototype);
|
||||
reagentProto.ReactionPlant(uid, entry, solution);
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Administration;
|
||||
using System.Linq;
|
||||
using Content.Server.Administration;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Cargo.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Body.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
@@ -16,7 +16,6 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Cargo.Systems;
|
||||
|
||||
@@ -31,7 +30,6 @@ public sealed class PricingSystem : EntitySystem
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly BodySystem _bodySystem = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobStateSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
@@ -108,36 +106,13 @@ public sealed class PricingSystem : EntitySystem
|
||||
args.Price += (component.Price - partPenalty) * (_mobStateSystem.IsAlive(uid, state) ? 1.0 : component.DeathPenalty);
|
||||
}
|
||||
|
||||
private double GetSolutionPrice(Entity<SolutionContainerManagerComponent> entity)
|
||||
{
|
||||
if (Comp<MetaDataComponent>(entity).EntityLifeStage < EntityLifeStage.MapInitialized)
|
||||
return GetSolutionPrice(entity.Comp);
|
||||
|
||||
var price = 0.0;
|
||||
|
||||
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, entity.Comp)))
|
||||
{
|
||||
var solution = soln.Comp.Solution;
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<ReagentPrototype>(reagent.Prototype, out var reagentProto))
|
||||
continue;
|
||||
|
||||
// TODO check ReagentData for price information?
|
||||
price += (float) quantity * reagentProto.PricePerUnit;
|
||||
}
|
||||
}
|
||||
|
||||
return price;
|
||||
}
|
||||
|
||||
private double GetSolutionPrice(SolutionContainerManagerComponent component)
|
||||
{
|
||||
var price = 0.0;
|
||||
|
||||
foreach (var (_, prototype) in _solutionContainerSystem.EnumerateSolutions(component))
|
||||
foreach (var solution in component.Solutions.Values)
|
||||
{
|
||||
foreach (var (reagent, quantity) in prototype.Contents)
|
||||
foreach (var (reagent, quantity) in solution.Contents)
|
||||
{
|
||||
if (!_prototypeManager.TryIndex<ReagentPrototype>(reagent.Prototype, out var reagentProto))
|
||||
continue;
|
||||
@@ -282,7 +257,7 @@ public sealed class PricingSystem : EntitySystem
|
||||
|
||||
if (TryComp<SolutionContainerManagerComponent>(uid, out var solComp))
|
||||
{
|
||||
price += GetSolutionPrice((uid, solComp));
|
||||
price += GetSolutionPrice(solComp);
|
||||
}
|
||||
|
||||
return price;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
using Content.Server.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.Components;
|
||||
|
||||
@@ -15,13 +17,7 @@ public sealed partial class SolutionRegenerationComponent : Component
|
||||
/// The name of the solution to add to.
|
||||
/// </summary>
|
||||
[DataField("solution", required: true), ViewVariables(VVAccess.ReadWrite)]
|
||||
public string SolutionName = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The solution to add reagents to.
|
||||
/// </summary>
|
||||
[DataField("solutionRef")]
|
||||
public Entity<SolutionComponent>? Solution = null;
|
||||
public string Solution = string.Empty;
|
||||
|
||||
/// <summary>
|
||||
/// The reagent(s) to be regenerated in the solution.
|
||||
|
||||
@@ -1,185 +0,0 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Network;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Chemistry.Containers.EntitySystems;
|
||||
|
||||
public sealed partial class SolutionContainerSystem : SharedSolutionContainerSystem
|
||||
{
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<SolutionContainerManagerComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<SolutionContainerManagerComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
SubscribeLocalEvent<ContainedSolutionComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
}
|
||||
|
||||
|
||||
public Solution EnsureSolution(Entity<MetaDataComponent?> entity, string name)
|
||||
=> EnsureSolution(entity, name, out _);
|
||||
|
||||
public Solution EnsureSolution(Entity<MetaDataComponent?> entity, string name, out bool existed)
|
||||
=> EnsureSolution(entity, name, FixedPoint2.Zero, out existed);
|
||||
|
||||
public Solution EnsureSolution(Entity<MetaDataComponent?> entity, string name, FixedPoint2 minVol, out bool existed)
|
||||
=> EnsureSolution(entity, name, minVol, null, out existed);
|
||||
|
||||
public Solution EnsureSolution(Entity<MetaDataComponent?> entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed)
|
||||
{
|
||||
var (uid, meta) = entity;
|
||||
DebugTools.Assert(Resolve(uid, ref meta), $"Attempted to ensure solution on invalid entity {ToPrettyString(entity.Owner)}");
|
||||
|
||||
var manager = EnsureComp<SolutionContainerManagerComponent>(uid);
|
||||
if (meta.EntityLifeStage >= EntityLifeStage.MapInitialized)
|
||||
return EnsureSolutionEntity((uid, manager), name, minVol, prototype, out existed).Comp.Solution;
|
||||
else
|
||||
return EnsureSolutionPrototype((uid, manager), name, minVol, prototype, out existed);
|
||||
}
|
||||
|
||||
public Entity<SolutionComponent> EnsureSolutionEntity(Entity<SolutionContainerManagerComponent?> entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed)
|
||||
{
|
||||
existed = true;
|
||||
|
||||
var (uid, container) = entity;
|
||||
|
||||
var solutionSlot = ContainerSystem.EnsureContainer<ContainerSlot>(uid, $"solution@{name}", out existed);
|
||||
if (!Resolve(uid, ref container, logMissing: false))
|
||||
{
|
||||
existed = false;
|
||||
container = AddComp<SolutionContainerManagerComponent>(uid);
|
||||
container.Containers.Add(name);
|
||||
}
|
||||
else if (!existed)
|
||||
{
|
||||
container.Containers.Add(name);
|
||||
Dirty(uid, container);
|
||||
}
|
||||
|
||||
var needsInit = false;
|
||||
SolutionComponent solutionComp;
|
||||
if (solutionSlot.ContainedEntity is not { } solutionId)
|
||||
{
|
||||
prototype ??= new() { MaxVolume = minVol };
|
||||
prototype.Name = name;
|
||||
(solutionId, solutionComp, _) = SpawnSolutionUninitialized(solutionSlot, name, minVol, prototype);
|
||||
existed = false;
|
||||
needsInit = true;
|
||||
Dirty(uid, container);
|
||||
}
|
||||
else
|
||||
{
|
||||
solutionComp = Comp<SolutionComponent>(solutionId);
|
||||
DebugTools.Assert(TryComp(solutionId, out ContainedSolutionComponent? relation) && relation.Container == uid && relation.ContainerName == name);
|
||||
DebugTools.Assert(solutionComp.Solution.Name == name);
|
||||
|
||||
var solution = solutionComp.Solution;
|
||||
solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, minVol);
|
||||
|
||||
// Depending on MapInitEvent order some systems can ensure solution empty solutions and conflict with the prototype solutions.
|
||||
// We want the reagents from the prototype to exist even if something else already created the solution.
|
||||
if (prototype is { Volume.Value: > 0 })
|
||||
solution.AddSolution(prototype, PrototypeManager);
|
||||
|
||||
Dirty(solutionId, solutionComp);
|
||||
}
|
||||
|
||||
if (needsInit)
|
||||
EntityManager.InitializeAndStartEntity(solutionId, Transform(solutionId).MapID);
|
||||
|
||||
return (solutionId, solutionComp);
|
||||
}
|
||||
|
||||
private Solution EnsureSolutionPrototype(Entity<SolutionContainerManagerComponent?> entity, string name, FixedPoint2 minVol, Solution? prototype, out bool existed)
|
||||
{
|
||||
existed = true;
|
||||
|
||||
var (uid, container) = entity;
|
||||
if (!Resolve(uid, ref container, logMissing: false))
|
||||
{
|
||||
container = AddComp<SolutionContainerManagerComponent>(uid);
|
||||
existed = false;
|
||||
}
|
||||
|
||||
if (container.Solutions is null)
|
||||
container.Solutions = new(SolutionContainerManagerComponent.DefaultCapacity);
|
||||
|
||||
if (!container.Solutions.TryGetValue(name, out var solution))
|
||||
{
|
||||
solution = prototype ?? new() { Name = name, MaxVolume = minVol };
|
||||
container.Solutions.Add(name, solution);
|
||||
existed = false;
|
||||
}
|
||||
else
|
||||
solution.MaxVolume = FixedPoint2.Max(solution.MaxVolume, minVol);
|
||||
|
||||
Dirty(uid, container);
|
||||
return solution;
|
||||
}
|
||||
|
||||
|
||||
private Entity<SolutionComponent, ContainedSolutionComponent> SpawnSolutionUninitialized(ContainerSlot container, string name, FixedPoint2 minVol, Solution prototype)
|
||||
{
|
||||
var coords = new EntityCoordinates(container.Owner, Vector2.Zero);
|
||||
var uid = EntityManager.CreateEntityUninitialized(null, coords, null);
|
||||
|
||||
var solution = new SolutionComponent() { Solution = prototype };
|
||||
AddComp(uid, solution);
|
||||
|
||||
var relation = new ContainedSolutionComponent() { Container = container.Owner, ContainerName = name };
|
||||
AddComp(uid, relation);
|
||||
|
||||
ContainerSystem.Insert(uid, container, force: true);
|
||||
|
||||
return (uid, solution, relation);
|
||||
}
|
||||
|
||||
|
||||
#region Event Handlers
|
||||
|
||||
private void OnMapInit(Entity<SolutionContainerManagerComponent> entity, ref MapInitEvent args)
|
||||
{
|
||||
if (entity.Comp.Solutions is not { } prototypes)
|
||||
return;
|
||||
|
||||
foreach (var (name, prototype) in prototypes)
|
||||
{
|
||||
EnsureSolutionEntity((entity.Owner, entity.Comp), name, prototype.MaxVolume, prototype, out _);
|
||||
}
|
||||
|
||||
entity.Comp.Solutions = null;
|
||||
Dirty(entity);
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(Entity<SolutionContainerManagerComponent> entity, ref ComponentShutdown args)
|
||||
{
|
||||
foreach (var name in entity.Comp.Containers)
|
||||
{
|
||||
if (ContainerSystem.TryGetContainer(entity, $"solution@{name}", out var solutionContainer))
|
||||
ContainerSystem.ShutdownContainer(solutionContainer);
|
||||
}
|
||||
entity.Comp.Containers.Clear();
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(Entity<ContainedSolutionComponent> entity, ref ComponentShutdown args)
|
||||
{
|
||||
if (TryComp(entity.Comp.Container, out SolutionContainerManagerComponent? container))
|
||||
{
|
||||
container.Containers.Remove(entity.Comp.ContainerName);
|
||||
Dirty(entity.Comp.Container, container);
|
||||
}
|
||||
|
||||
if (ContainerSystem.TryGetContainer(entity, $"solution@{entity.Comp.ContainerName}", out var solutionContainer))
|
||||
ContainerSystem.ShutdownContainer(solutionContainer);
|
||||
}
|
||||
|
||||
#endregion Event Handlers
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Labels;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Storage.EntitySystems;
|
||||
@@ -18,8 +19,6 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -48,7 +47,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ChemMasterComponent, ComponentStartup>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ChemMasterComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ChemMasterComponent, SolutionChangedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ChemMasterComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ChemMasterComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ChemMasterComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
@@ -68,7 +67,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
private void UpdateUiState(Entity<ChemMasterComponent> ent, bool updateLabel = false)
|
||||
{
|
||||
var (owner, chemMaster) = ent;
|
||||
if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(owner, SharedChemMaster.BufferSolutionName, out var bufferSolution))
|
||||
return;
|
||||
var inputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.InputSlotName);
|
||||
var outputContainer = _itemSlotsSystem.GetItemOrNull(owner, SharedChemMaster.OutputSlotName);
|
||||
@@ -131,8 +130,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
|
||||
if (container is null ||
|
||||
!_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSoln, out var containerSolution) ||
|
||||
!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
|
||||
!_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution) ||
|
||||
!_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -141,12 +140,12 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
amount = FixedPoint2.Min(amount, containerSolution.AvailableVolume);
|
||||
amount = bufferSolution.RemoveReagent(id, amount);
|
||||
_solutionContainerSystem.TryAddReagent(containerSoln.Value, id, amount, out var _);
|
||||
_solutionContainerSystem.TryAddReagent(container.Value, containerSolution, id, amount, out var _);
|
||||
}
|
||||
else // Container to buffer
|
||||
{
|
||||
amount = FixedPoint2.Min(amount, containerSolution.GetReagentQuantity(id));
|
||||
_solutionContainerSystem.RemoveReagent(containerSoln.Value, id, amount);
|
||||
_solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount);
|
||||
bufferSolution.AddReagent(id, amount);
|
||||
}
|
||||
|
||||
@@ -157,7 +156,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
if (fromBuffer)
|
||||
{
|
||||
if (_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var bufferSolution))
|
||||
if (_solutionContainerSystem.TryGetSolution(chemMaster, SharedChemMaster.BufferSolutionName, out var bufferSolution))
|
||||
bufferSolution.RemoveReagent(id, amount);
|
||||
else
|
||||
return;
|
||||
@@ -166,9 +165,9 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
var container = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.InputSlotName);
|
||||
if (container is not null &&
|
||||
_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution, out _))
|
||||
_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var containerSolution))
|
||||
{
|
||||
_solutionContainerSystem.RemoveReagent(containerSolution.Value, id, amount);
|
||||
_solutionContainerSystem.RemoveReagent(container.Value, containerSolution, id, amount);
|
||||
}
|
||||
else
|
||||
return;
|
||||
@@ -211,8 +210,10 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
_storageSystem.Insert(container, item, out _, user: user, storage);
|
||||
_labelSystem.Label(item, message.Label);
|
||||
|
||||
var itemSolution = _solutionContainerSystem.EnsureSolutionEntity(item, SharedChemMaster.PillSolutionName, message.Dosage, null, out _);
|
||||
_solutionContainerSystem.TryAddSolution(itemSolution, withdrawal.SplitSolution(message.Dosage));
|
||||
var itemSolution = _solutionContainerSystem.EnsureSolution(item, SharedChemMaster.PillSolutionName);
|
||||
|
||||
_solutionContainerSystem.TryAddSolution(
|
||||
item, itemSolution, withdrawal.SplitSolution(message.Dosage));
|
||||
|
||||
var pill = EnsureComp<PillComponent>(item);
|
||||
pill.PillType = chemMaster.Comp.PillType;
|
||||
@@ -222,13 +223,13 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
// Log pill creation by a user
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||
$"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}");
|
||||
$"{ToPrettyString(user.Value):user} printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}");
|
||||
}
|
||||
else
|
||||
{
|
||||
// Log pill creation by magic? This should never happen... right?
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Low,
|
||||
$"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution.Comp.Solution)}");
|
||||
$"Unknown printed {ToPrettyString(item):pill} {SolutionContainerSystem.ToPrettyString(itemSolution)}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -241,7 +242,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
var user = message.Session.AttachedEntity;
|
||||
var maybeContainer = _itemSlotsSystem.GetItemOrNull(chemMaster, SharedChemMaster.OutputSlotName);
|
||||
if (maybeContainer is not { Valid: true } container
|
||||
|| !_solutionContainerSystem.TryGetSolution(container, SharedChemMaster.BottleSolutionName, out var soln, out var solution))
|
||||
|| !_solutionContainerSystem.TryGetSolution(
|
||||
container, SharedChemMaster.BottleSolutionName, out var solution))
|
||||
{
|
||||
return; // output can't fit reagents
|
||||
}
|
||||
@@ -258,7 +260,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return;
|
||||
|
||||
_labelSystem.Label(container, message.Label);
|
||||
_solutionContainerSystem.TryAddSolution(soln.Value, withdrawal);
|
||||
_solutionContainerSystem.TryAddSolution(
|
||||
container, solution, withdrawal);
|
||||
|
||||
if (user.HasValue)
|
||||
{
|
||||
@@ -284,7 +287,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
outputSolution = null;
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(chemMaster.Owner, SharedChemMaster.BufferSolutionName, out _, out var solution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(
|
||||
chemMaster, SharedChemMaster.BufferSolutionName, out var solution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -319,7 +323,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return null;
|
||||
|
||||
if (!TryComp(container, out FitsInDispenserComponent? fits)
|
||||
|| !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out _, out var solution))
|
||||
|| !_solutionContainerSystem.TryGetSolution(container.Value, fits.Solution, out var solution))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
@@ -335,7 +339,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
var name = Name(container.Value);
|
||||
{
|
||||
if (_solutionContainerSystem.TryGetSolution(
|
||||
container.Value, SharedChemMaster.BottleSolutionName, out _, out var solution))
|
||||
container.Value, SharedChemMaster.BottleSolutionName, out var solution))
|
||||
{
|
||||
return BuildContainerInfo(name, solution);
|
||||
}
|
||||
@@ -346,7 +350,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
var pills = storage.Container.ContainedEntities.Select((Func<EntityUid, (string, FixedPoint2 quantity)>) (pill =>
|
||||
{
|
||||
_solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out _, out var solution);
|
||||
_solutionContainerSystem.TryGetSolution(pill, SharedChemMaster.PillSolutionName, out var solution);
|
||||
var quantity = solution?.Volume ?? FixedPoint2.Zero;
|
||||
return (Name(pill), quantity);
|
||||
})).ToList();
|
||||
|
||||
@@ -1,22 +1,21 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Forensics;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Verbs;
|
||||
using Robust.Shared.GameStates;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Verbs;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Player;
|
||||
using Content.Shared.Forensics;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
@@ -26,11 +25,11 @@ public sealed partial class ChemistrySystem
|
||||
/// <summary>
|
||||
/// Default transfer amounts for the set-transfer verb.
|
||||
/// </summary>
|
||||
public static readonly List<int> TransferAmounts = new() { 1, 5, 10, 15 };
|
||||
public static readonly List<int> TransferAmounts = new() {1, 5, 10, 15};
|
||||
private void InitializeInjector()
|
||||
{
|
||||
SubscribeLocalEvent<InjectorComponent, GetVerbsEvent<AlternativeVerb>>(AddSetTransferVerbs);
|
||||
SubscribeLocalEvent<InjectorComponent, SolutionContainerChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<InjectorComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<InjectorComponent, InjectorDoAfterEvent>(OnInjectDoAfter);
|
||||
SubscribeLocalEvent<InjectorComponent, ComponentStartup>(OnInjectorStartup);
|
||||
SubscribeLocalEvent<InjectorComponent, UseInHandEvent>(OnInjectorUse);
|
||||
@@ -38,7 +37,7 @@ public sealed partial class ChemistrySystem
|
||||
SubscribeLocalEvent<InjectorComponent, ComponentGetState>(OnInjectorGetState);
|
||||
}
|
||||
|
||||
private void AddSetTransferVerbs(Entity<InjectorComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
private void AddSetTransferVerbs(EntityUid uid, InjectorComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
if (!args.CanAccess || !args.CanInteract || args.Hands == null)
|
||||
return;
|
||||
@@ -46,14 +45,11 @@ public sealed partial class ChemistrySystem
|
||||
if (!EntityManager.TryGetComponent(args.User, out ActorComponent? actor))
|
||||
return;
|
||||
|
||||
var (uid, component) = entity;
|
||||
|
||||
// Add specific transfer verbs according to the container's size
|
||||
var priority = 0;
|
||||
var user = args.User;
|
||||
foreach (var amount in TransferAmounts)
|
||||
{
|
||||
if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
|
||||
if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
|
||||
continue;
|
||||
|
||||
AlternativeVerb verb = new();
|
||||
@@ -62,7 +58,7 @@ public sealed partial class ChemistrySystem
|
||||
verb.Act = () =>
|
||||
{
|
||||
component.TransferAmount = FixedPoint2.New(amount);
|
||||
_popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), user, user);
|
||||
_popup.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), args.User, args.User);
|
||||
};
|
||||
|
||||
// we want to sort by size, not alphabetically by the verb text.
|
||||
@@ -73,22 +69,22 @@ public sealed partial class ChemistrySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void UseInjector(Entity<InjectorComponent> injector, EntityUid target, EntityUid user)
|
||||
private void UseInjector(EntityUid target, EntityUid user, EntityUid injector, InjectorComponent component)
|
||||
{
|
||||
// Handle injecting/drawing for solutions
|
||||
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
{
|
||||
if (_solutionContainers.TryGetInjectableSolution(target, out var injectableSolution, out _))
|
||||
if (_solutions.TryGetInjectableSolution(target, out var injectableSolution))
|
||||
{
|
||||
TryInject(injector, target, injectableSolution.Value, user, false);
|
||||
TryInject(component, injector, target, injectableSolution, user, false);
|
||||
}
|
||||
else if (_solutionContainers.TryGetRefillableSolution(target, out var refillableSolution, out _))
|
||||
else if (_solutions.TryGetRefillableSolution(target, out var refillableSolution))
|
||||
{
|
||||
TryInject(injector, target, refillableSolution.Value, user, true);
|
||||
TryInject(component, injector, target, refillableSolution, user, true);
|
||||
}
|
||||
else if (TryComp<BloodstreamComponent>(target, out var bloodstream))
|
||||
{
|
||||
TryInjectIntoBloodstream(injector, (target, bloodstream), user);
|
||||
TryInjectIntoBloodstream(component, injector, target, bloodstream, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -96,112 +92,111 @@ public sealed partial class ChemistrySystem
|
||||
("target", Identity.Entity(target, EntityManager))), injector, user);
|
||||
}
|
||||
}
|
||||
else if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw)
|
||||
else if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Draw)
|
||||
{
|
||||
// Draw from a bloodstream, if the target has that
|
||||
if (TryComp<BloodstreamComponent>(target, out var stream) &&
|
||||
_solutionContainers.ResolveSolution(target, stream.BloodSolutionName, ref stream.BloodSolution))
|
||||
if (TryComp<BloodstreamComponent>(target, out var stream))
|
||||
{
|
||||
TryDraw(injector, (target, stream), stream.BloodSolution.Value, user);
|
||||
TryDraw(component, injector, target, stream.BloodSolution, user, stream);
|
||||
return;
|
||||
}
|
||||
|
||||
// Draw from an object (food, beaker, etc)
|
||||
if (_solutionContainers.TryGetDrawableSolution(target, out var drawableSolution, out _))
|
||||
if (_solutions.TryGetDrawableSolution(target, out var drawableSolution))
|
||||
{
|
||||
TryDraw(injector, target, drawableSolution.Value, user);
|
||||
TryDraw(component, injector, target, drawableSolution, user);
|
||||
}
|
||||
else
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-cannot-draw-message",
|
||||
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
("target", Identity.Entity(target, EntityManager))), injector, user);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSolutionChange(Entity<InjectorComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
private void OnSolutionChange(EntityUid uid, InjectorComponent component, SolutionChangedEvent args)
|
||||
{
|
||||
Dirty(entity);
|
||||
Dirty(component);
|
||||
}
|
||||
|
||||
private void OnInjectorGetState(Entity<InjectorComponent> entity, ref ComponentGetState args)
|
||||
private void OnInjectorGetState(EntityUid uid, InjectorComponent component, ref ComponentGetState args)
|
||||
{
|
||||
_solutionContainers.TryGetSolution(entity.Owner, InjectorComponent.SolutionName, out _, out var solution);
|
||||
_solutions.TryGetSolution(uid, InjectorComponent.SolutionName, out var solution);
|
||||
|
||||
var currentVolume = solution?.Volume ?? FixedPoint2.Zero;
|
||||
var maxVolume = solution?.MaxVolume ?? FixedPoint2.Zero;
|
||||
|
||||
args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, entity.Comp.ToggleState);
|
||||
args.State = new SharedInjectorComponent.InjectorComponentState(currentVolume, maxVolume, component.ToggleState);
|
||||
}
|
||||
|
||||
private void OnInjectDoAfter(Entity<InjectorComponent> entity, ref InjectorDoAfterEvent args)
|
||||
private void OnInjectDoAfter(EntityUid uid, InjectorComponent component, DoAfterEvent args)
|
||||
{
|
||||
if (args.Cancelled || args.Handled || args.Args.Target == null)
|
||||
return;
|
||||
|
||||
UseInjector(entity, args.Args.Target.Value, args.Args.User);
|
||||
UseInjector(args.Args.Target.Value, args.Args.User, uid, component);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnInjectorAfterInteract(Entity<InjectorComponent> entity, ref AfterInteractEvent args)
|
||||
private void OnInjectorAfterInteract(EntityUid uid, InjectorComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (args.Handled || !args.CanReach)
|
||||
return;
|
||||
|
||||
//Make sure we have the attacking entity
|
||||
if (args.Target is not { Valid: true } target || !HasComp<SolutionContainerManagerComponent>(entity))
|
||||
if (args.Target is not { Valid: true } target || !HasComp<SolutionContainerManagerComponent>(uid))
|
||||
return;
|
||||
|
||||
// Is the target a mob? If yes, use a do-after to give them time to respond.
|
||||
if (HasComp<MobStateComponent>(target) || HasComp<BloodstreamComponent>(target))
|
||||
{
|
||||
// Are use using an injector capible of targeting a mob?
|
||||
if (entity.Comp.IgnoreMobs)
|
||||
if (component.IgnoreMobs)
|
||||
return;
|
||||
|
||||
InjectDoAfter(entity, target, args.User);
|
||||
InjectDoAfter(component, args.User, target, uid);
|
||||
args.Handled = true;
|
||||
return;
|
||||
}
|
||||
|
||||
UseInjector(entity, target, args.User);
|
||||
UseInjector(target, args.User, uid, component);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnInjectorStartup(Entity<InjectorComponent> entity, ref ComponentStartup args)
|
||||
private void OnInjectorStartup(EntityUid uid, InjectorComponent component, ComponentStartup args)
|
||||
{
|
||||
// ???? why ?????
|
||||
Dirty(entity);
|
||||
Dirty(component);
|
||||
}
|
||||
|
||||
private void OnInjectorUse(Entity<InjectorComponent> entity, ref UseInHandEvent args)
|
||||
private void OnInjectorUse(EntityUid uid, InjectorComponent component, UseInHandEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
Toggle(entity, args.User);
|
||||
Toggle(component, args.User, uid);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Toggle between draw/inject state if applicable
|
||||
/// </summary>
|
||||
private void Toggle(Entity<InjectorComponent> injector, EntityUid user)
|
||||
private void Toggle(InjectorComponent component, EntityUid user, EntityUid injector)
|
||||
{
|
||||
if (injector.Comp.InjectOnly)
|
||||
if (component.InjectOnly)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
string msg;
|
||||
switch (injector.Comp.ToggleState)
|
||||
switch (component.ToggleState)
|
||||
{
|
||||
case SharedInjectorComponent.InjectorToggleMode.Inject:
|
||||
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
|
||||
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
|
||||
msg = "injector-component-drawing-text";
|
||||
break;
|
||||
case SharedInjectorComponent.InjectorToggleMode.Draw:
|
||||
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
|
||||
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
|
||||
msg = "injector-component-injecting-text";
|
||||
break;
|
||||
default:
|
||||
@@ -214,18 +209,18 @@ public sealed partial class ChemistrySystem
|
||||
/// <summary>
|
||||
/// Send informative pop-up messages and wait for a do-after to complete.
|
||||
/// </summary>
|
||||
private void InjectDoAfter(Entity<InjectorComponent> injector, EntityUid target, EntityUid user)
|
||||
private void InjectDoAfter(InjectorComponent component, EntityUid user, EntityUid target, EntityUid injector)
|
||||
{
|
||||
// Create a pop-up for the user
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-injecting-user"), target, user);
|
||||
|
||||
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution))
|
||||
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution))
|
||||
return;
|
||||
|
||||
var actualDelay = MathF.Max(injector.Comp.Delay, 1f);
|
||||
var actualDelay = MathF.Max(component.Delay, 1f);
|
||||
|
||||
// Injections take 0.5 seconds longer per additional 5u
|
||||
actualDelay += (float) injector.Comp.TransferAmount / injector.Comp.Delay - 0.5f;
|
||||
actualDelay += (float) component.TransferAmount / component.Delay - 0.5f;
|
||||
|
||||
var isTarget = user != target;
|
||||
|
||||
@@ -249,7 +244,7 @@ public sealed partial class ChemistrySystem
|
||||
}
|
||||
|
||||
// Add an admin log, using the "force feed" log type. It's not quite feeding, but the effect is the same.
|
||||
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
{
|
||||
_adminLogger.Add(LogType.ForceFeed,
|
||||
$"{EntityManager.ToPrettyString(user):user} is attempting to inject {EntityManager.ToPrettyString(target):target} with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}");
|
||||
@@ -260,11 +255,11 @@ public sealed partial class ChemistrySystem
|
||||
// Self-injections take half as long.
|
||||
actualDelay /= 2;
|
||||
|
||||
if (injector.Comp.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
if (component.ToggleState == SharedInjectorComponent.InjectorToggleMode.Inject)
|
||||
_adminLogger.Add(LogType.Ingestion, $"{EntityManager.ToPrettyString(user):user} is attempting to inject themselves with a solution {SolutionContainerSystem.ToPrettyString(solution):solution}.");
|
||||
}
|
||||
|
||||
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector.Owner, target: target, used: injector.Owner)
|
||||
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager, user, actualDelay, new InjectorDoAfterEvent(), injector, target: target, used: injector)
|
||||
{
|
||||
BreakOnUserMove = true,
|
||||
BreakOnDamage = true,
|
||||
@@ -273,80 +268,77 @@ public sealed partial class ChemistrySystem
|
||||
});
|
||||
}
|
||||
|
||||
private void TryInjectIntoBloodstream(Entity<InjectorComponent> injector, Entity<BloodstreamComponent> target, EntityUid user)
|
||||
private void TryInjectIntoBloodstream(InjectorComponent component, EntityUid injector, EntityUid target, BloodstreamComponent targetBloodstream, EntityUid user)
|
||||
{
|
||||
// Get transfer amount. May be smaller than _transferAmount if not enough room
|
||||
if (!_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution, out var chemSolution))
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
return;
|
||||
}
|
||||
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetBloodstream.ChemicalSolution.AvailableVolume);
|
||||
|
||||
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, chemSolution.AvailableVolume);
|
||||
if (realTransferAmount <= 0)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-cannot-inject-message", ("target", Identity.Entity(target, EntityManager))), injector, user);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move units from attackSolution to targetSolution
|
||||
var removedSolution = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, realTransferAmount);
|
||||
var removedSolution = _solutions.SplitSolution(user, targetBloodstream.ChemicalSolution, realTransferAmount);
|
||||
|
||||
_blood.TryAddToChemicals(target, removedSolution, target.Comp);
|
||||
_blood.TryAddToChemicals(target, removedSolution, targetBloodstream);
|
||||
|
||||
_reactiveSystem.DoEntityReaction(target, removedSolution, ReactionMethod.Injection);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-inject-success-message",
|
||||
("amount", removedSolution.Volume),
|
||||
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
("target", Identity.Entity(target, EntityManager))), injector, user);
|
||||
|
||||
Dirty(injector);
|
||||
AfterInject(injector, target);
|
||||
Dirty(component);
|
||||
AfterInject(component, injector, target);
|
||||
}
|
||||
|
||||
private void TryInject(Entity<InjectorComponent> injector, EntityUid targetEntity, Entity<SolutionComponent> targetSolution, EntityUid user, bool asRefill)
|
||||
private void TryInject(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, bool asRefill)
|
||||
{
|
||||
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.Volume == 0)
|
||||
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|
||||
|| solution.Volume == 0)
|
||||
return;
|
||||
|
||||
// Get transfer amount. May be smaller than _transferAmount if not enough room
|
||||
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.AvailableVolume);
|
||||
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.AvailableVolume);
|
||||
|
||||
if (realTransferAmount <= 0)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-target-already-full-message", ("target", Identity.Entity(targetEntity, EntityManager))),
|
||||
injector.Owner, user);
|
||||
injector, user);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move units from attackSolution to targetSolution
|
||||
Solution removedSolution;
|
||||
if (TryComp<StackComponent>(targetEntity, out var stack))
|
||||
removedSolution = _solutionContainers.SplitStackSolution(soln.Value, realTransferAmount, stack.Count);
|
||||
removedSolution = _solutions.SplitStackSolution(injector, solution, realTransferAmount, stack.Count);
|
||||
else
|
||||
removedSolution = _solutionContainers.SplitSolution(soln.Value, realTransferAmount);
|
||||
removedSolution = _solutions.SplitSolution(injector, solution, realTransferAmount);
|
||||
|
||||
_reactiveSystem.DoEntityReaction(targetEntity, removedSolution, ReactionMethod.Injection);
|
||||
|
||||
if (!asRefill)
|
||||
_solutionContainers.Inject(targetEntity, targetSolution, removedSolution);
|
||||
_solutions.Inject(targetEntity, targetSolution, removedSolution);
|
||||
else
|
||||
_solutionContainers.Refill(targetEntity, targetSolution, removedSolution);
|
||||
_solutions.Refill(targetEntity, targetSolution, removedSolution);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-transfer-success-message",
|
||||
("amount", removedSolution.Volume),
|
||||
("target", Identity.Entity(targetEntity, EntityManager))), injector.Owner, user);
|
||||
("target", Identity.Entity(targetEntity, EntityManager))), injector, user);
|
||||
|
||||
Dirty(injector);
|
||||
AfterInject(injector, targetEntity);
|
||||
Dirty(component);
|
||||
AfterInject(component, injector, targetEntity);
|
||||
}
|
||||
|
||||
private void AfterInject(Entity<InjectorComponent> injector, EntityUid target)
|
||||
private void AfterInject(InjectorComponent component, EntityUid injector, EntityUid target)
|
||||
{
|
||||
// Automatically set syringe to draw after completely draining it.
|
||||
if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.Volume == 0)
|
||||
if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|
||||
&& solution.Volume == 0)
|
||||
{
|
||||
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
|
||||
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Draw;
|
||||
}
|
||||
|
||||
// Leave some DNA from the injectee on it
|
||||
@@ -354,12 +346,13 @@ public sealed partial class ChemistrySystem
|
||||
RaiseLocalEvent(target, ref ev);
|
||||
}
|
||||
|
||||
private void AfterDraw(Entity<InjectorComponent> injector, EntityUid target)
|
||||
private void AfterDraw(InjectorComponent component, EntityUid injector, EntityUid target)
|
||||
{
|
||||
// Automatically set syringe to inject after completely filling it.
|
||||
if (_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out _, out var solution) && solution.AvailableVolume == 0)
|
||||
if (_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|
||||
&& solution.AvailableVolume == 0)
|
||||
{
|
||||
injector.Comp.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
|
||||
component.ToggleState = SharedInjectorComponent.InjectorToggleMode.Inject;
|
||||
}
|
||||
|
||||
// Leave some DNA from the drawee on it
|
||||
@@ -367,68 +360,70 @@ public sealed partial class ChemistrySystem
|
||||
RaiseLocalEvent(target, ref ev);
|
||||
}
|
||||
|
||||
private void TryDraw(Entity<InjectorComponent> injector, Entity<BloodstreamComponent?> target, Entity<SolutionComponent> targetSolution, EntityUid user)
|
||||
private void TryDraw(InjectorComponent component, EntityUid injector, EntityUid targetEntity, Solution targetSolution, EntityUid user, BloodstreamComponent? stream = null)
|
||||
{
|
||||
if (!_solutionContainers.TryGetSolution(injector.Owner, InjectorComponent.SolutionName, out var soln, out var solution) || solution.AvailableVolume == 0)
|
||||
if (!_solutions.TryGetSolution(injector, InjectorComponent.SolutionName, out var solution)
|
||||
|| solution.AvailableVolume == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Get transfer amount. May be smaller than _transferAmount if not enough room, also make sure there's room in the injector
|
||||
var realTransferAmount = FixedPoint2.Min(injector.Comp.TransferAmount, targetSolution.Comp.Solution.Volume, solution.AvailableVolume);
|
||||
var realTransferAmount = FixedPoint2.Min(component.TransferAmount, targetSolution.Volume, solution.AvailableVolume);
|
||||
|
||||
if (realTransferAmount <= 0)
|
||||
{
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(target, EntityManager))),
|
||||
injector.Owner, user);
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-target-is-empty-message", ("target", Identity.Entity(targetEntity, EntityManager))),
|
||||
injector, user);
|
||||
return;
|
||||
}
|
||||
|
||||
// We have some snowflaked behavior for streams.
|
||||
if (target.Comp != null)
|
||||
if (stream != null)
|
||||
{
|
||||
DrawFromBlood(injector, (target.Owner, target.Comp), soln.Value, realTransferAmount, user);
|
||||
DrawFromBlood(user, injector, targetEntity, component, solution, stream, realTransferAmount);
|
||||
return;
|
||||
}
|
||||
|
||||
// Move units from attackSolution to targetSolution
|
||||
var removedSolution = _solutionContainers.Draw(target.Owner, targetSolution, realTransferAmount);
|
||||
var removedSolution = _solutions.Draw(targetEntity, targetSolution, realTransferAmount);
|
||||
|
||||
if (!_solutionContainers.TryAddSolution(soln.Value, removedSolution))
|
||||
if (!_solutions.TryAddSolution(injector, solution, removedSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-draw-success-message",
|
||||
("amount", removedSolution.Volume),
|
||||
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
("target", Identity.Entity(targetEntity, EntityManager))), injector, user);
|
||||
|
||||
Dirty(injector);
|
||||
AfterDraw(injector, target);
|
||||
Dirty(component);
|
||||
AfterDraw(component, injector, targetEntity);
|
||||
}
|
||||
|
||||
private void DrawFromBlood(Entity<InjectorComponent> injector, Entity<BloodstreamComponent> target, Entity<SolutionComponent> injectorSolution, FixedPoint2 transferAmount, EntityUid user)
|
||||
private void DrawFromBlood(EntityUid user, EntityUid injector, EntityUid target, InjectorComponent component, Solution injectorSolution, BloodstreamComponent stream, FixedPoint2 transferAmount)
|
||||
{
|
||||
var drawAmount = (float) transferAmount;
|
||||
|
||||
if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.ChemicalSolutionName, ref target.Comp.ChemicalSolution))
|
||||
var bloodAmount = drawAmount;
|
||||
var chemAmount = 0f;
|
||||
if (stream.ChemicalSolution.Volume > 0f) // If they have stuff in their chem stream, we'll draw some of that
|
||||
{
|
||||
var chemTemp = _solutionContainers.SplitSolution(target.Comp.ChemicalSolution.Value, drawAmount * 0.15f);
|
||||
_solutionContainers.TryAddSolution(injectorSolution, chemTemp);
|
||||
drawAmount -= (float) chemTemp.Volume;
|
||||
bloodAmount = drawAmount * 0.85f;
|
||||
chemAmount = drawAmount * 0.15f;
|
||||
}
|
||||
|
||||
if (_solutionContainers.ResolveSolution(target.Owner, target.Comp.BloodSolutionName, ref target.Comp.BloodSolution))
|
||||
{
|
||||
var bloodTemp = _solutionContainers.SplitSolution(target.Comp.BloodSolution.Value, drawAmount);
|
||||
_solutionContainers.TryAddSolution(injectorSolution, bloodTemp);
|
||||
}
|
||||
var bloodTemp = stream.BloodSolution.SplitSolution(bloodAmount);
|
||||
var chemTemp = stream.ChemicalSolution.SplitSolution(chemAmount);
|
||||
|
||||
_solutions.TryAddSolution(injector, injectorSolution, bloodTemp);
|
||||
_solutions.TryAddSolution(injector, injectorSolution, chemTemp);
|
||||
|
||||
_popup.PopupEntity(Loc.GetString("injector-component-draw-success-message",
|
||||
("amount", transferAmount),
|
||||
("target", Identity.Entity(target, EntityManager))), injector.Owner, user);
|
||||
("target", Identity.Entity(target, EntityManager))), injector, user);
|
||||
|
||||
Dirty(injector);
|
||||
AfterDraw(injector, target);
|
||||
Dirty(component);
|
||||
AfterDraw(component, injector, target);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Interaction;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.CombatMode;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Mobs.Systems;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
@@ -23,7 +24,7 @@ public sealed partial class ChemistrySystem : EntitySystem
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly MobStateSystem _mobState = default!;
|
||||
[Dependency] private readonly SharedCombatModeSystem _combat = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainers = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutions = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
||||
@@ -1,21 +1,20 @@
|
||||
using System.Linq;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Forensics;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Content.Shared.Mobs.Components;
|
||||
using Content.Shared.Timing;
|
||||
using Content.Shared.Weapons.Melee.Events;
|
||||
using Content.Shared.Timing;
|
||||
using Robust.Shared.GameStates;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using Content.Shared.Forensics;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -27,33 +26,33 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
SubscribeLocalEvent<HyposprayComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
SubscribeLocalEvent<HyposprayComponent, MeleeHitEvent>(OnAttack);
|
||||
SubscribeLocalEvent<HyposprayComponent, SolutionContainerChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<HyposprayComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<HyposprayComponent, UseInHandEvent>(OnUseInHand);
|
||||
SubscribeLocalEvent<HyposprayComponent, ComponentGetState>(OnHypoGetState);
|
||||
}
|
||||
|
||||
private void OnHypoGetState(Entity<HyposprayComponent> entity, ref ComponentGetState args)
|
||||
private void OnHypoGetState(EntityUid uid, HyposprayComponent component, ref ComponentGetState args)
|
||||
{
|
||||
args.State = _solutionContainers.TryGetSolution(entity.Owner, entity.Comp.SolutionName, out _, out var solution)
|
||||
args.State = _solutions.TryGetSolution(uid, component.SolutionName, out var solution)
|
||||
? new HyposprayComponentState(solution.Volume, solution.MaxVolume)
|
||||
: new HyposprayComponentState(FixedPoint2.Zero, FixedPoint2.Zero);
|
||||
}
|
||||
|
||||
private void OnUseInHand(Entity<HyposprayComponent> entity, ref UseInHandEvent args)
|
||||
private void OnUseInHand(EntityUid uid, HyposprayComponent component, UseInHandEvent args)
|
||||
{
|
||||
if (args.Handled)
|
||||
return;
|
||||
|
||||
TryDoInject(entity, args.User, args.User);
|
||||
TryDoInject(uid, args.User, args.User);
|
||||
args.Handled = true;
|
||||
}
|
||||
|
||||
private void OnSolutionChange(Entity<HyposprayComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
private void OnSolutionChange(EntityUid uid, HyposprayComponent component, SolutionChangedEvent args)
|
||||
{
|
||||
Dirty(entity);
|
||||
Dirty(component);
|
||||
}
|
||||
|
||||
public void OnAfterInteract(Entity<HyposprayComponent> entity, ref AfterInteractEvent args)
|
||||
public void OnAfterInteract(EntityUid uid, HyposprayComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (!args.CanReach)
|
||||
return;
|
||||
@@ -61,20 +60,21 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
var target = args.Target;
|
||||
var user = args.User;
|
||||
|
||||
TryDoInject(entity, target, user);
|
||||
TryDoInject(uid, target, user);
|
||||
}
|
||||
|
||||
public void OnAttack(Entity<HyposprayComponent> entity, ref MeleeHitEvent args)
|
||||
public void OnAttack(EntityUid uid, HyposprayComponent component, MeleeHitEvent args)
|
||||
{
|
||||
if (!args.HitEntities.Any())
|
||||
return;
|
||||
|
||||
TryDoInject(entity, args.HitEntities.First(), args.User);
|
||||
TryDoInject(uid, args.HitEntities.First(), args.User);
|
||||
}
|
||||
|
||||
public bool TryDoInject(Entity<HyposprayComponent> hypo, EntityUid? target, EntityUid user)
|
||||
public bool TryDoInject(EntityUid uid, EntityUid? target, EntityUid user, HyposprayComponent? component=null)
|
||||
{
|
||||
var (uid, component) = hypo;
|
||||
if (!Resolve(uid, ref component))
|
||||
return false;
|
||||
|
||||
if (!EligibleEntity(target, _entMan, component))
|
||||
return false;
|
||||
@@ -92,13 +92,15 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
target = user;
|
||||
}
|
||||
|
||||
if (!_solutionContainers.TryGetSolution(uid, component.SolutionName, out var hypoSpraySoln, out var hypoSpraySolution) || hypoSpraySolution.Volume == 0)
|
||||
_solutions.TryGetSolution(uid, component.SolutionName, out var hypoSpraySolution);
|
||||
|
||||
if (hypoSpraySolution == null || hypoSpraySolution.Volume == 0)
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("hypospray-component-empty-message"), user);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!_solutionContainers.TryGetInjectableSolution(target.Value, out var targetSoln, out var targetSolution))
|
||||
if (!_solutions.TryGetInjectableSolution(target.Value, out var targetSolution))
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("hypospray-cant-inject", ("target", Identity.Entity(target.Value, _entMan))), user);
|
||||
return false;
|
||||
@@ -125,17 +127,17 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
if (realTransferAmount <= 0)
|
||||
{
|
||||
_popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message", ("owner", target)), user);
|
||||
_popup.PopupCursor(Loc.GetString("hypospray-component-transfer-already-full-message",("owner", target)), user);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Move units from attackSolution to targetSolution
|
||||
var removedSolution = _solutionContainers.SplitSolution(hypoSpraySoln.Value, realTransferAmount);
|
||||
var removedSolution = _solutions.SplitSolution(uid, hypoSpraySolution, realTransferAmount);
|
||||
|
||||
if (!targetSolution.CanAddSolution(removedSolution))
|
||||
return true;
|
||||
_reactiveSystem.DoEntityReaction(target.Value, removedSolution, ReactionMethod.Injection);
|
||||
_solutionContainers.TryAddSolution(targetSoln.Value, removedSolution);
|
||||
_solutions.TryAddSolution(target.Value, targetSolution, removedSolution);
|
||||
|
||||
var ev = new TransferDnaEvent { Donor = target.Value, Recipient = uid };
|
||||
RaiseLocalEvent(target.Value, ref ev);
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
using Content.Server.Xenoarchaeology.XenoArtifacts.Triggers.Components;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Interaction.Events;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
@@ -11,26 +15,27 @@ public sealed partial class ChemistrySystem
|
||||
SubscribeLocalEvent<ReactionMixerComponent, AfterInteractEvent>(OnAfterInteract);
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<ReactionMixerComponent> entity, ref AfterInteractEvent args)
|
||||
private void OnAfterInteract(EntityUid uid, ReactionMixerComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (!args.Target.HasValue || !args.CanReach)
|
||||
return;
|
||||
|
||||
var mixAttemptEvent = new MixingAttemptEvent(entity);
|
||||
RaiseLocalEvent(entity, ref mixAttemptEvent);
|
||||
if (mixAttemptEvent.Cancelled)
|
||||
var mixAttemptEvent = new MixingAttemptEvent(uid);
|
||||
RaiseLocalEvent(uid, ref mixAttemptEvent);
|
||||
if(mixAttemptEvent.Cancelled)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_solutionContainers.TryGetMixableSolution(args.Target.Value, out var solution))
|
||||
return;
|
||||
Solution? solution = null;
|
||||
if (!_solutions.TryGetMixableSolution(args.Target.Value, out solution))
|
||||
return;
|
||||
|
||||
_popup.PopupEntity(Loc.GetString(entity.Comp.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(entity.Owner, EntityManager))), args.User, args.User);
|
||||
_popup.PopupEntity(Loc.GetString(component.MixMessage, ("mixed", Identity.Entity(args.Target.Value, EntityManager)), ("mixer", Identity.Entity(uid, EntityManager))), args.User, args.User);
|
||||
|
||||
_solutionContainers.UpdateChemicals(solution.Value, true, entity.Comp);
|
||||
_solutions.UpdateChemicals(args.Target.Value, solution, true, component);
|
||||
|
||||
var afterMixingEvent = new AfterMixingEvent(entity, args.Target.Value);
|
||||
RaiseLocalEvent(entity, afterMixingEvent);
|
||||
var afterMixingEvent = new AfterMixingEvent(uid, args.Target.Value);
|
||||
RaiseLocalEvent(uid, afterMixingEvent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
|
||||
@@ -13,27 +12,27 @@ namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem
|
||||
{
|
||||
base.Initialize();
|
||||
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, ComponentStartup>(OnStartup);
|
||||
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, SolutionContainerChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
}
|
||||
|
||||
public void OnStartup(Entity<DeleteOnSolutionEmptyComponent> entity, ref ComponentStartup args)
|
||||
public void OnStartup(EntityUid uid, DeleteOnSolutionEmptyComponent component, ComponentStartup args)
|
||||
{
|
||||
CheckSolutions(entity);
|
||||
CheckSolutions(uid, component);
|
||||
}
|
||||
|
||||
public void OnSolutionChange(Entity<DeleteOnSolutionEmptyComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
public void OnSolutionChange(EntityUid uid, DeleteOnSolutionEmptyComponent component, SolutionChangedEvent args)
|
||||
{
|
||||
CheckSolutions(entity);
|
||||
CheckSolutions(uid, component);
|
||||
}
|
||||
|
||||
public void CheckSolutions(Entity<DeleteOnSolutionEmptyComponent> entity)
|
||||
public void CheckSolutions(EntityUid uid, DeleteOnSolutionEmptyComponent component)
|
||||
{
|
||||
if (!TryComp(entity, out SolutionContainerManagerComponent? solutions))
|
||||
if (!EntityManager.HasComponent<SolutionContainerManagerComponent>(uid))
|
||||
return;
|
||||
|
||||
if (_solutionContainerSystem.TryGetSolution((entity.Owner, solutions), entity.Comp.Solution, out _, out var solution))
|
||||
if (_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution))
|
||||
if (solution.Volume <= 0)
|
||||
EntityManager.QueueDeleteEntity(entity);
|
||||
EntityManager.QueueDeleteEntity(uid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Linq;
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Dispenser;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
@@ -15,7 +15,6 @@ using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -37,7 +36,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, ComponentStartup>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, SolutionContainerChangedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, SolutionChangedEvent>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntInsertedIntoContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, EntRemovedFromContainerMessage>(SubscribeUpdateUiState);
|
||||
SubscribeLocalEvent<ReagentDispenserComponent, BoundUIOpenedEvent>(SubscribeUpdateUiState);
|
||||
@@ -69,7 +68,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
if (container is not { Valid: true })
|
||||
return null;
|
||||
|
||||
if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out _, out var solution))
|
||||
if (_solutionContainerSystem.TryGetFitsInDispenser(container.Value, out var solution))
|
||||
{
|
||||
return new ContainerInfo(Name(container.Value), solution.Volume, solution.MaxVolume)
|
||||
{
|
||||
@@ -123,10 +122,10 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return;
|
||||
|
||||
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
|
||||
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
|
||||
if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution))
|
||||
return;
|
||||
|
||||
if (_solutionContainerSystem.TryAddReagent(solution.Value, message.ReagentId, (int) reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
|
||||
if (_solutionContainerSystem.TryAddReagent(outputContainer.Value, solution, message.ReagentId, (int)reagentDispenser.Comp.DispenseAmount, out var dispensedAmount)
|
||||
&& message.Session.AttachedEntity is not null)
|
||||
{
|
||||
_adminLogger.Add(LogType.ChemicalReaction, LogImpact.Medium,
|
||||
@@ -140,10 +139,10 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
private void OnClearContainerSolutionMessage(Entity<ReagentDispenserComponent> reagentDispenser, ref ReagentDispenserClearContainerSolutionMessage message)
|
||||
{
|
||||
var outputContainer = _itemSlotsSystem.GetItemOrNull(reagentDispenser, SharedReagentDispenser.OutputSlotName);
|
||||
if (outputContainer is not { Valid: true } || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution, out _))
|
||||
if (outputContainer is not {Valid: true} || !_solutionContainerSystem.TryGetFitsInDispenser(outputContainer.Value, out var solution))
|
||||
return;
|
||||
|
||||
_solutionContainerSystem.RemoveAllSolution(solution.Value);
|
||||
_solutionContainerSystem.RemoveAllSolution(outputContainer.Value, solution);
|
||||
UpdateUiState(reagentDispenser);
|
||||
ClickSound(reagentDispenser);
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Popups;
|
||||
@@ -17,23 +16,21 @@ public sealed class RehydratableSystem : EntitySystem
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<RehydratableComponent, SolutionContainerChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<RehydratableComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
}
|
||||
|
||||
private void OnSolutionChange(Entity<RehydratableComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
private void OnSolutionChange(EntityUid uid, RehydratableComponent comp, SolutionChangedEvent args)
|
||||
{
|
||||
var quantity = _solutions.GetTotalPrototypeQuantity(entity, entity.Comp.CatalystPrototype);
|
||||
if (quantity != FixedPoint2.Zero && quantity >= entity.Comp.CatalystMinimum)
|
||||
var quantity = _solutions.GetTotalPrototypeQuantity(uid, comp.CatalystPrototype);
|
||||
if (quantity != FixedPoint2.Zero && quantity >= comp.CatalystMinimum)
|
||||
{
|
||||
Expand(entity);
|
||||
Expand(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
// Try not to make this public if you can help it.
|
||||
private void Expand(Entity<RehydratableComponent> entity)
|
||||
private void Expand(EntityUid uid, RehydratableComponent comp)
|
||||
{
|
||||
var (uid, comp) = entity;
|
||||
|
||||
_popups.PopupEntity(Loc.GetString("rehydratable-component-expands-message", ("owner", uid)), uid);
|
||||
|
||||
var randomMob = _random.Pick(comp.PossibleSpawns);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Construction;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Placeable;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
@@ -13,7 +13,7 @@ public sealed class SolutionHeaterSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly PowerReceiverSystem _powerReceiver = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solution = default!;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override void Initialize()
|
||||
@@ -51,41 +51,41 @@ public sealed class SolutionHeaterSystem : EntitySystem
|
||||
RemComp<ActiveSolutionHeaterComponent>(uid);
|
||||
}
|
||||
|
||||
private void OnPowerChanged(Entity<SolutionHeaterComponent> entity, ref PowerChangedEvent args)
|
||||
private void OnPowerChanged(EntityUid uid, SolutionHeaterComponent component, ref PowerChangedEvent args)
|
||||
{
|
||||
var placer = Comp<ItemPlacerComponent>(entity);
|
||||
var placer = Comp<ItemPlacerComponent>(uid);
|
||||
if (args.Powered && placer.PlacedEntities.Count > 0)
|
||||
{
|
||||
TurnOn(entity);
|
||||
TurnOn(uid);
|
||||
}
|
||||
else
|
||||
{
|
||||
TurnOff(entity);
|
||||
TurnOff(uid);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRefreshParts(Entity<SolutionHeaterComponent> entity, ref RefreshPartsEvent args)
|
||||
private void OnRefreshParts(EntityUid uid, SolutionHeaterComponent component, RefreshPartsEvent args)
|
||||
{
|
||||
var heatRating = args.PartRatings[entity.Comp.MachinePartHeatMultiplier] - 1;
|
||||
var heatRating = args.PartRatings[component.MachinePartHeatMultiplier] - 1;
|
||||
|
||||
entity.Comp.HeatPerSecond = entity.Comp.BaseHeatPerSecond * MathF.Pow(entity.Comp.PartRatingHeatMultiplier, heatRating);
|
||||
component.HeatPerSecond = component.BaseHeatPerSecond * MathF.Pow(component.PartRatingHeatMultiplier, heatRating);
|
||||
}
|
||||
|
||||
private void OnUpgradeExamine(Entity<SolutionHeaterComponent> entity, ref UpgradeExamineEvent args)
|
||||
private void OnUpgradeExamine(EntityUid uid, SolutionHeaterComponent component, UpgradeExamineEvent args)
|
||||
{
|
||||
args.AddPercentageUpgrade("solution-heater-upgrade-heat", entity.Comp.HeatPerSecond / entity.Comp.BaseHeatPerSecond);
|
||||
args.AddPercentageUpgrade("solution-heater-upgrade-heat", component.HeatPerSecond / component.BaseHeatPerSecond);
|
||||
}
|
||||
|
||||
private void OnItemPlaced(Entity<SolutionHeaterComponent> entity, ref ItemPlacedEvent args)
|
||||
private void OnItemPlaced(EntityUid uid, SolutionHeaterComponent comp, ref ItemPlacedEvent args)
|
||||
{
|
||||
TryTurnOn(entity);
|
||||
TryTurnOn(uid);
|
||||
}
|
||||
|
||||
private void OnItemRemoved(Entity<SolutionHeaterComponent> entity, ref ItemRemovedEvent args)
|
||||
private void OnItemRemoved(EntityUid uid, SolutionHeaterComponent component, ref ItemRemovedEvent args)
|
||||
{
|
||||
var placer = Comp<ItemPlacerComponent>(entity);
|
||||
var placer = Comp<ItemPlacerComponent>(uid);
|
||||
if (placer.PlacedEntities.Count == 0) // Last entity was removed
|
||||
TurnOff(entity);
|
||||
TurnOff(uid);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
@@ -97,13 +97,13 @@ public sealed class SolutionHeaterSystem : EntitySystem
|
||||
{
|
||||
foreach (var heatingEntity in placer.PlacedEntities)
|
||||
{
|
||||
if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var container))
|
||||
if (!TryComp<SolutionContainerManagerComponent>(heatingEntity, out var solution))
|
||||
continue;
|
||||
|
||||
var energy = heater.HeatPerSecond * frameTime;
|
||||
foreach (var (_, soln) in _solutionContainer.EnumerateSolutions((heatingEntity, container)))
|
||||
foreach (var s in solution.Solutions.Values)
|
||||
{
|
||||
_solutionContainer.AddThermalEnergy(soln, energy);
|
||||
_solution.AddThermalEnergy(heatingEntity, s, energy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,19 @@
|
||||
using Content.Server.Body.Components;
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Inventory;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
[UsedImplicitly]
|
||||
internal sealed class SolutionInjectOnCollideSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainersSystem = default!;
|
||||
[Dependency] private readonly IPrototypeManager _protoManager = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionsSystem = default!;
|
||||
[Dependency] private readonly BloodstreamSystem _bloodstreamSystem = default!;
|
||||
[Dependency] private readonly InventorySystem _inventorySystem = default!;
|
||||
|
||||
@@ -28,7 +30,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
if (!args.OtherBody.Hard ||
|
||||
!EntityManager.TryGetComponent<BloodstreamComponent>(target, out var bloodstream) ||
|
||||
!_solutionContainersSystem.TryGetInjectableSolution(ent.Owner, out var solution, out _))
|
||||
!_solutionsSystem.TryGetInjectableSolution(ent, out var solution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -42,7 +44,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return;
|
||||
}
|
||||
|
||||
var solRemoved = _solutionContainersSystem.SplitSolution(solution.Value, component.TransferAmount);
|
||||
var solRemoved = solution.SplitSolution(component.TransferAmount);
|
||||
var solRemovedVol = solRemoved.Volume;
|
||||
|
||||
var solToInject = solRemoved.SplitSolution(solRemovedVol * component.TransferEfficiency);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
@@ -29,13 +30,13 @@ public sealed class SolutionPurgeSystem : EntitySystem
|
||||
|
||||
// timer ignores if it's empty, it's just a fixed cycle
|
||||
purge.NextPurgeTime += purge.Duration;
|
||||
if (_solutionContainer.TryGetSolution((uid, manager), purge.Solution, out var solution))
|
||||
_solutionContainer.SplitSolutionWithout(solution.Value, purge.Quantity, purge.Preserve.ToArray());
|
||||
if (_solutionContainer.TryGetSolution(uid, purge.Solution, out var solution, manager))
|
||||
_solutionContainer.SplitSolutionWithout(uid, solution, purge.Quantity, purge.Preserve.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUnpaused(Entity<SolutionPurgeComponent> entity, ref EntityUnpausedEvent args)
|
||||
private void OnUnpaused(EntityUid uid, SolutionPurgeComponent comp, ref EntityUnpausedEvent args)
|
||||
{
|
||||
entity.Comp.NextPurgeTime += args.PausedTime;
|
||||
comp.NextPurgeTime += args.PausedTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Random;
|
||||
using Content.Shared.Random.Helpers;
|
||||
@@ -21,12 +21,13 @@ public sealed class SolutionRandomFillSystem : EntitySystem
|
||||
SubscribeLocalEvent<RandomFillSolutionComponent, MapInitEvent>(OnRandomSolutionFillMapInit);
|
||||
}
|
||||
|
||||
private void OnRandomSolutionFillMapInit(Entity<RandomFillSolutionComponent> entity, ref MapInitEvent args)
|
||||
private void OnRandomSolutionFillMapInit(EntityUid uid, RandomFillSolutionComponent component, MapInitEvent args)
|
||||
{
|
||||
if (entity.Comp.WeightedRandomId == null)
|
||||
if (component.WeightedRandomId == null)
|
||||
return;
|
||||
|
||||
var pick = _proto.Index<WeightedRandomFillSolutionPrototype>(entity.Comp.WeightedRandomId).Pick(_random);
|
||||
var target = _solutionsSystem.EnsureSolution(uid, component.Solution);
|
||||
var pick = _proto.Index<WeightedRandomFillSolutionPrototype>(component.WeightedRandomId).Pick(_random);
|
||||
|
||||
var reagent = pick.reagent;
|
||||
var quantity = pick.quantity;
|
||||
@@ -37,7 +38,6 @@ public sealed class SolutionRandomFillSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
var target = _solutionsSystem.EnsureSolutionEntity(entity.Owner, entity.Comp.Solution, pick.quantity, null, out _);
|
||||
_solutionsSystem.TryAddReagent(target, reagent, quantity, out _);
|
||||
target.AddReagent(reagent, quantity);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
@@ -31,7 +31,7 @@ public sealed class SolutionRegenerationSystem : EntitySystem
|
||||
|
||||
// timer ignores if its full, it's just a fixed cycle
|
||||
regen.NextRegenTime = _timing.CurTime + regen.Duration;
|
||||
if (_solutionContainer.ResolveSolution((uid, manager), regen.SolutionName, ref regen.Solution, out var solution))
|
||||
if (_solutionContainer.TryGetSolution(uid, regen.Solution, out var solution, manager))
|
||||
{
|
||||
var amount = FixedPoint2.Min(solution.AvailableVolume, regen.Generated.Volume);
|
||||
if (amount <= FixedPoint2.Zero)
|
||||
@@ -48,13 +48,13 @@ public sealed class SolutionRegenerationSystem : EntitySystem
|
||||
generated = regen.Generated.Clone().SplitSolution(amount);
|
||||
}
|
||||
|
||||
_solutionContainer.TryAddSolution(regen.Solution.Value, generated);
|
||||
_solutionContainer.TryAddSolution(uid, solution, generated);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnUnpaused(Entity<SolutionRegenerationComponent> entity, ref EntityUnpausedEvent args)
|
||||
private void OnUnpaused(EntityUid uid, SolutionRegenerationComponent comp, ref EntityUnpausedEvent args)
|
||||
{
|
||||
entity.Comp.NextRegenTime += args.PausedTime;
|
||||
comp.NextRegenTime += args.PausedTime;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Server.Popups;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems;
|
||||
|
||||
@@ -19,7 +21,7 @@ namespace Content.Server.Chemistry.EntitySystems;
|
||||
/// </summary>
|
||||
public sealed class SolutionSpikableSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
|
||||
[Dependency] private readonly SolutionContainerSystem _solutionSystem = default!;
|
||||
[Dependency] private readonly TriggerSystem _triggerSystem = default!;
|
||||
[Dependency] private readonly PopupSystem _popupSystem = default!;
|
||||
|
||||
@@ -28,9 +30,9 @@ public sealed class SolutionSpikableSystem : EntitySystem
|
||||
SubscribeLocalEvent<RefillableSolutionComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
}
|
||||
|
||||
private void OnInteractUsing(Entity<RefillableSolutionComponent> entity, ref InteractUsingEvent args)
|
||||
private void OnInteractUsing(EntityUid uid, RefillableSolutionComponent target, InteractUsingEvent args)
|
||||
{
|
||||
TrySpike(args.Used, args.Target, args.User, entity.Comp);
|
||||
TrySpike(args.Used, args.Target, args.User, target);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -47,8 +49,8 @@ public sealed class SolutionSpikableSystem : EntitySystem
|
||||
{
|
||||
if (!Resolve(source, ref spikableSource, ref managerSource, false)
|
||||
|| !Resolve(target, ref spikableTarget, ref managerTarget, false)
|
||||
|| !_solutionContainerSystem.TryGetRefillableSolution((target, spikableTarget, managerTarget), out var targetSoln, out var targetSolution)
|
||||
|| !_solutionContainerSystem.TryGetSolution((source, managerSource), spikableSource.SourceSolution, out _, out var sourceSolution))
|
||||
|| !_solutionSystem.TryGetRefillableSolution(target, out var targetSolution, managerTarget, spikableTarget)
|
||||
|| !managerSource.Solutions.TryGetValue(spikableSource.SourceSolution, out var sourceSolution))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -59,7 +61,7 @@ public sealed class SolutionSpikableSystem : EntitySystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_solutionContainerSystem.ForceAddSolution(targetSoln.Value, sourceSolution))
|
||||
if (!_solutionSystem.ForceAddSolution(target, targetSolution, sourceSolution))
|
||||
return;
|
||||
|
||||
_popupSystem.PopupEntity(Loc.GetString(spikableSource.Popup, ("spiked-entity", target), ("spike-entity", source)), user, user);
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
using Content.Server.Administration.Logs;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Popups;
|
||||
using Content.Shared.Verbs;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Player;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
@@ -24,7 +24,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
/// <summary>
|
||||
/// Default transfer amounts for the set-transfer verb.
|
||||
/// </summary>
|
||||
public static readonly List<int> DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000 };
|
||||
public static readonly List<int> DefaultTransferAmounts = new() { 1, 5, 10, 25, 50, 100, 250, 500, 1000};
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -35,19 +35,17 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<SolutionTransferComponent, TransferAmountSetValueMessage>(OnTransferAmountSetValueMessage);
|
||||
}
|
||||
|
||||
private void OnTransferAmountSetValueMessage(Entity<SolutionTransferComponent> entity, ref TransferAmountSetValueMessage message)
|
||||
private void OnTransferAmountSetValueMessage(EntityUid uid, SolutionTransferComponent solutionTransfer, TransferAmountSetValueMessage message)
|
||||
{
|
||||
var newTransferAmount = FixedPoint2.Clamp(message.Value, entity.Comp.MinimumTransferAmount, entity.Comp.MaximumTransferAmount);
|
||||
entity.Comp.TransferAmount = newTransferAmount;
|
||||
var newTransferAmount = FixedPoint2.Clamp(message.Value, solutionTransfer.MinimumTransferAmount, solutionTransfer.MaximumTransferAmount);
|
||||
solutionTransfer.TransferAmount = newTransferAmount;
|
||||
|
||||
if (message.Session.AttachedEntity is { Valid: true } user)
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), entity.Owner, user);
|
||||
if (message.Session.AttachedEntity is {Valid: true} user)
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", newTransferAmount)), uid, user);
|
||||
}
|
||||
|
||||
private void AddSetTransferVerbs(Entity<SolutionTransferComponent> entity, ref GetVerbsEvent<AlternativeVerb> args)
|
||||
private void AddSetTransferVerbs(EntityUid uid, SolutionTransferComponent component, GetVerbsEvent<AlternativeVerb> args)
|
||||
{
|
||||
var (uid, component) = entity;
|
||||
|
||||
if (!args.CanAccess || !args.CanInteract || !component.CanChangeTransferAmount || args.Hands == null)
|
||||
return;
|
||||
|
||||
@@ -58,16 +56,15 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
AlternativeVerb custom = new();
|
||||
custom.Text = Loc.GetString("comp-solution-transfer-verb-custom-amount");
|
||||
custom.Category = VerbCategory.SetTransferAmount;
|
||||
custom.Act = () => _userInterfaceSystem.TryOpen(uid, TransferAmountUiKey.Key, actor.PlayerSession);
|
||||
custom.Act = () => _userInterfaceSystem.TryOpen(args.Target, TransferAmountUiKey.Key, actor.PlayerSession);
|
||||
custom.Priority = 1;
|
||||
args.Verbs.Add(custom);
|
||||
|
||||
// Add specific transfer verbs according to the container's size
|
||||
var priority = 0;
|
||||
var user = args.User;
|
||||
foreach (var amount in DefaultTransferAmounts)
|
||||
{
|
||||
if (amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
|
||||
if ( amount < component.MinimumTransferAmount.Int() || amount > component.MaximumTransferAmount.Int())
|
||||
continue;
|
||||
|
||||
AlternativeVerb verb = new();
|
||||
@@ -76,7 +73,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
verb.Act = () =>
|
||||
{
|
||||
component.TransferAmount = FixedPoint2.New(amount);
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, user);
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-set-amount", ("amount", amount)), uid, args.User);
|
||||
};
|
||||
|
||||
// we want to sort by size, not alphabetically by the verb text.
|
||||
@@ -87,19 +84,18 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
}
|
||||
}
|
||||
|
||||
private void OnAfterInteract(Entity<SolutionTransferComponent> entity, ref AfterInteractEvent args)
|
||||
private void OnAfterInteract(EntityUid uid, SolutionTransferComponent component, AfterInteractEvent args)
|
||||
{
|
||||
if (!args.CanReach || args.Target == null)
|
||||
return;
|
||||
|
||||
var target = args.Target!.Value;
|
||||
var (uid, component) = entity;
|
||||
|
||||
//Special case for reagent tanks, because normally clicking another container will give solution, not take it.
|
||||
if (component.CanReceive && !EntityManager.HasComponent<RefillableSolutionComponent>(target) // target must not be refillable (e.g. Reagent Tanks)
|
||||
&& _solutionContainerSystem.TryGetDrainableSolution(target, out var targetSoln, out _) // target must be drainable
|
||||
&& EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp)
|
||||
&& _solutionContainerSystem.TryGetRefillableSolution((uid, refillComp, null), out var ownerSoln, out var ownerRefill))
|
||||
if (component.CanReceive && !EntityManager.HasComponent<RefillableSolutionComponent>(target) // target must not be refillable (e.g. Reagent Tanks)
|
||||
&& _solutionContainerSystem.TryGetDrainableSolution(target, out var targetDrain) // target must be drainable
|
||||
&& EntityManager.TryGetComponent(uid, out RefillableSolutionComponent? refillComp)
|
||||
&& _solutionContainerSystem.TryGetRefillableSolution(uid, out var ownerRefill, refillable: refillComp))
|
||||
|
||||
{
|
||||
|
||||
@@ -110,7 +106,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill); // if the receiver has a smaller transfer limit, use that instead
|
||||
}
|
||||
|
||||
var transferred = Transfer(args.User, target, targetSoln.Value, uid, ownerSoln.Value, transferAmount);
|
||||
var transferred = Transfer(args.User, target, targetDrain, uid, ownerRefill, transferAmount);
|
||||
if (transferred > 0)
|
||||
{
|
||||
var toTheBrim = ownerRefill.AvailableVolume == 0;
|
||||
@@ -126,8 +122,8 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
}
|
||||
|
||||
// if target is refillable, and owner is drainable
|
||||
if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out targetSoln, out var targetRefill)
|
||||
&& _solutionContainerSystem.TryGetDrainableSolution(uid, out ownerSoln, out var ownerDrain))
|
||||
if (component.CanSend && _solutionContainerSystem.TryGetRefillableSolution(target, out var targetRefill)
|
||||
&& _solutionContainerSystem.TryGetDrainableSolution(uid, out var ownerDrain))
|
||||
{
|
||||
var transferAmount = component.TransferAmount;
|
||||
|
||||
@@ -136,7 +132,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
transferAmount = FixedPoint2.Min(transferAmount, (FixedPoint2) refill.MaxRefill);
|
||||
}
|
||||
|
||||
var transferred = Transfer(args.User, uid, ownerSoln.Value, target, targetSoln.Value, transferAmount);
|
||||
var transferred = Transfer(args.User, uid, ownerDrain, target, targetRefill, transferAmount);
|
||||
|
||||
if (transferred > 0)
|
||||
{
|
||||
@@ -154,9 +150,9 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
/// <returns>The actual amount transferred.</returns>
|
||||
public FixedPoint2 Transfer(EntityUid user,
|
||||
EntityUid sourceEntity,
|
||||
Entity<SolutionComponent> source,
|
||||
Solution source,
|
||||
EntityUid targetEntity,
|
||||
Entity<SolutionComponent> target,
|
||||
Solution target,
|
||||
FixedPoint2 amount)
|
||||
{
|
||||
var transferAttempt = new SolutionTransferAttemptEvent(sourceEntity, targetEntity);
|
||||
@@ -169,8 +165,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return FixedPoint2.Zero;
|
||||
}
|
||||
|
||||
var sourceSolution = source.Comp.Solution;
|
||||
if (sourceSolution.Volume == 0)
|
||||
if (source.Volume == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-empty", ("target", sourceEntity)), sourceEntity, user);
|
||||
return FixedPoint2.Zero;
|
||||
@@ -184,20 +179,19 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return FixedPoint2.Zero;
|
||||
}
|
||||
|
||||
var targetSolution = target.Comp.Solution;
|
||||
if (targetSolution.AvailableVolume == 0)
|
||||
if (target.AvailableVolume == 0)
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("comp-solution-transfer-is-full", ("target", targetEntity)), targetEntity, user);
|
||||
return FixedPoint2.Zero;
|
||||
}
|
||||
|
||||
var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(sourceSolution.Volume, targetSolution.AvailableVolume));
|
||||
var actualAmount = FixedPoint2.Min(amount, FixedPoint2.Min(source.Volume, target.AvailableVolume));
|
||||
|
||||
var solution = _solutionContainerSystem.Drain(sourceEntity, source, actualAmount);
|
||||
_solutionContainerSystem.Refill(targetEntity, target, solution);
|
||||
|
||||
_adminLogger.Add(LogType.Action, LogImpact.Medium,
|
||||
$"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {SolutionContainerSystem.ToPrettyString(targetSolution)}");
|
||||
$"{EntityManager.ToPrettyString(user):player} transferred {string.Join(", ", solution.Contents)} to {EntityManager.ToPrettyString(targetEntity):entity}, which now contains {string.Join(", ", target.Contents)}");
|
||||
|
||||
return actualAmount;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -17,38 +16,38 @@ public sealed class TransformableContainerSystem : EntitySystem
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<TransformableContainerComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<TransformableContainerComponent, SolutionContainerChangedEvent>(OnSolutionChange);
|
||||
SubscribeLocalEvent<TransformableContainerComponent, SolutionChangedEvent>(OnSolutionChange);
|
||||
}
|
||||
|
||||
private void OnMapInit(Entity<TransformableContainerComponent> entity, ref MapInitEvent args)
|
||||
private void OnMapInit(EntityUid uid, TransformableContainerComponent component, MapInitEvent args)
|
||||
{
|
||||
var meta = MetaData(entity.Owner);
|
||||
if (string.IsNullOrEmpty(entity.Comp.InitialName))
|
||||
var meta = MetaData(uid);
|
||||
if (string.IsNullOrEmpty(component.InitialName))
|
||||
{
|
||||
entity.Comp.InitialName = meta.EntityName;
|
||||
component.InitialName = meta.EntityName;
|
||||
}
|
||||
if (string.IsNullOrEmpty(entity.Comp.InitialDescription))
|
||||
if (string.IsNullOrEmpty(component.InitialDescription))
|
||||
{
|
||||
entity.Comp.InitialDescription = meta.EntityDescription;
|
||||
component.InitialDescription = meta.EntityDescription;
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSolutionChange(Entity<TransformableContainerComponent> entity, ref SolutionContainerChangedEvent args)
|
||||
private void OnSolutionChange(EntityUid owner, TransformableContainerComponent component,
|
||||
SolutionChangedEvent args)
|
||||
{
|
||||
if (!_solutionsSystem.TryGetFitsInDispenser(entity.Owner, out _, out var solution))
|
||||
if (!_solutionsSystem.TryGetFitsInDispenser(owner, out var solution))
|
||||
return;
|
||||
|
||||
//Transform container into initial state when emptied
|
||||
if (entity.Comp.CurrentReagent != null && solution.Contents.Count == 0)
|
||||
if (component.CurrentReagent != null && solution.Contents.Count == 0)
|
||||
{
|
||||
CancelTransformation(entity);
|
||||
CancelTransformation(owner, component);
|
||||
}
|
||||
|
||||
//the biggest reagent in the solution decides the appearance
|
||||
var reagentId = solution.GetPrimaryReagentId();
|
||||
|
||||
//If biggest reagent didn't changed - don't change anything at all
|
||||
if (entity.Comp.CurrentReagent != null && entity.Comp.CurrentReagent.ID == reagentId?.Prototype)
|
||||
if (component.CurrentReagent != null && component.CurrentReagent.ID == reagentId?.Prototype)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -57,29 +56,29 @@ public sealed class TransformableContainerSystem : EntitySystem
|
||||
if (!string.IsNullOrWhiteSpace(reagentId?.Prototype)
|
||||
&& _prototypeManager.TryIndex(reagentId.Value.Prototype, out ReagentPrototype? proto))
|
||||
{
|
||||
var metadata = MetaData(entity.Owner);
|
||||
var metadata = MetaData(owner);
|
||||
var val = Loc.GetString("transformable-container-component-glass", ("name", proto.LocalizedName));
|
||||
_metadataSystem.SetEntityName(entity.Owner, val, metadata);
|
||||
_metadataSystem.SetEntityDescription(entity.Owner, proto.LocalizedDescription, metadata);
|
||||
entity.Comp.CurrentReagent = proto;
|
||||
entity.Comp.Transformed = true;
|
||||
_metadataSystem.SetEntityName(owner, val, metadata);
|
||||
_metadataSystem.SetEntityDescription(owner, proto.LocalizedDescription, metadata);
|
||||
component.CurrentReagent = proto;
|
||||
component.Transformed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private void CancelTransformation(Entity<TransformableContainerComponent> entity)
|
||||
private void CancelTransformation(EntityUid owner, TransformableContainerComponent component)
|
||||
{
|
||||
entity.Comp.CurrentReagent = null;
|
||||
entity.Comp.Transformed = false;
|
||||
component.CurrentReagent = null;
|
||||
component.Transformed = false;
|
||||
|
||||
var metadata = MetaData(entity);
|
||||
var metadata = MetaData(owner);
|
||||
|
||||
if (!string.IsNullOrEmpty(entity.Comp.InitialName))
|
||||
if (!string.IsNullOrEmpty(component.InitialName))
|
||||
{
|
||||
_metadataSystem.SetEntityName(entity.Owner, entity.Comp.InitialName, metadata);
|
||||
_metadataSystem.SetEntityName(owner, component.InitialName, metadata);
|
||||
}
|
||||
if (!string.IsNullOrEmpty(entity.Comp.InitialDescription))
|
||||
if (!string.IsNullOrEmpty(component.InitialDescription))
|
||||
{
|
||||
_metadataSystem.SetEntityDescription(entity.Owner, entity.Comp.InitialDescription, metadata);
|
||||
_metadataSystem.SetEntityDescription(owner, component.InitialDescription, metadata);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
using System.Numerics;
|
||||
using Content.Server.Chemistry.Components;
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Physics;
|
||||
@@ -15,7 +16,6 @@ using Robust.Shared.Physics.Events;
|
||||
using Robust.Shared.Physics.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Spawners;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Chemistry.EntitySystems
|
||||
{
|
||||
@@ -40,20 +40,19 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
SubscribeLocalEvent<VaporComponent, StartCollideEvent>(HandleCollide);
|
||||
}
|
||||
|
||||
private void HandleCollide(Entity<VaporComponent> entity, ref StartCollideEvent args)
|
||||
private void HandleCollide(EntityUid uid, VaporComponent component, ref StartCollideEvent args)
|
||||
{
|
||||
if (!EntityManager.TryGetComponent(entity.Owner, out SolutionContainerManagerComponent? contents)) return;
|
||||
if (!EntityManager.TryGetComponent(uid, out SolutionContainerManagerComponent? contents)) return;
|
||||
|
||||
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((entity.Owner, contents)))
|
||||
foreach (var value in contents.Solutions.Values)
|
||||
{
|
||||
var solution = soln.Comp.Solution;
|
||||
_reactive.DoEntityReaction(args.OtherEntity, solution, ReactionMethod.Touch);
|
||||
_reactive.DoEntityReaction(args.OtherEntity, value, ReactionMethod.Touch);
|
||||
}
|
||||
|
||||
// Check for collision with a impassable object (e.g. wall) and stop
|
||||
if ((args.OtherFixture.CollisionLayer & (int) CollisionGroup.Impassable) != 0 && args.OtherFixture.Hard)
|
||||
{
|
||||
EntityManager.QueueDeleteEntity(entity);
|
||||
EntityManager.QueueDeleteEntity(uid);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -84,27 +83,28 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!_solutionContainerSystem.TryGetSolution(vapor.Owner, VaporComponent.SolutionName, out var vaporSolution))
|
||||
if (!_solutionContainerSystem.TryGetSolution(vapor, VaporComponent.SolutionName,
|
||||
out var vaporSolution))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return _solutionContainerSystem.TryAddSolution(vaporSolution.Value, solution);
|
||||
return _solutionContainerSystem.TryAddSolution(vapor, vaporSolution, solution);
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<VaporComponent, SolutionContainerManagerComponent, TransformComponent>();
|
||||
while (query.MoveNext(out var uid, out var vaporComp, out var container, out var xform))
|
||||
while (query.MoveNext(out var uid, out var vaporComp, out var solution, out var xform))
|
||||
{
|
||||
foreach (var (_, soln) in _solutionContainerSystem.EnumerateSolutions((uid, container)))
|
||||
foreach (var (_, value) in solution.Solutions)
|
||||
{
|
||||
Update(frameTime, (uid, vaporComp), soln, xform);
|
||||
Update(frameTime, (uid, vaporComp), value, xform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Update(float frameTime, Entity<VaporComponent> ent, Entity<SolutionComponent> soln, TransformComponent xform)
|
||||
private void Update(float frameTime, Entity<VaporComponent> ent, Solution contents, TransformComponent xform)
|
||||
{
|
||||
var (entity, vapor) = ent;
|
||||
if (!vapor.Active)
|
||||
@@ -112,7 +112,6 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
|
||||
vapor.ReactTimer += frameTime;
|
||||
|
||||
var contents = soln.Comp.Solution;
|
||||
if (vapor.ReactTimer >= ReactTime && TryComp(xform.GridUid, out MapGridComponent? gridComp))
|
||||
{
|
||||
vapor.ReactTimer = 0;
|
||||
@@ -132,7 +131,7 @@ namespace Content.Server.Chemistry.EntitySystems
|
||||
reaction = reagentQuantity.Quantity;
|
||||
}
|
||||
|
||||
_solutionContainerSystem.RemoveReagent(soln, reagentQuantity.Reagent, reaction);
|
||||
_solutionContainerSystem.RemoveReagent(entity, contents, reagentQuantity.Reagent, reaction);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using Content.Server.Fluids.EntitySystems;
|
||||
using Content.Shared.Audio;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Coordinates.Helpers;
|
||||
using Content.Shared.Database;
|
||||
@@ -29,7 +30,7 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// <summary>
|
||||
/// How many units of reaction for 1 smoke entity.
|
||||
/// </summary>
|
||||
[DataField] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5);
|
||||
[DataField("overflowThreshold")] public FixedPoint2 OverflowThreshold = FixedPoint2.New(2.5);
|
||||
|
||||
/// <summary>
|
||||
/// The entity prototype that will be spawned as the effect.
|
||||
@@ -55,7 +56,7 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
return;
|
||||
|
||||
var spreadAmount = (int) Math.Max(0, Math.Ceiling((args.Quantity / OverflowThreshold).Float()));
|
||||
var splitSolution = args.Source.SplitSolution(args.Source.Volume);
|
||||
var splitSolution = args.EntityManager.System<SolutionContainerSystem>().SplitSolution(args.SolutionEntity, args.Source, args.Source.Volume);
|
||||
var transform = args.EntityManager.GetComponent<TransformComponent>(args.SolutionEntity);
|
||||
var mapManager = IoCManager.Resolve<IMapManager>();
|
||||
|
||||
|
||||
@@ -11,13 +11,13 @@ public sealed partial class CreateEntityReactionEffect : ReagentEffect
|
||||
/// <summary>
|
||||
/// What entity to create.
|
||||
/// </summary>
|
||||
[DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
[DataField("entity", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Entity = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How many entities to create per unit reaction.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("number")]
|
||||
public uint Number = 1;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -23,7 +23,7 @@ public sealed partial class EmpReactionEffect : ReagentEffect
|
||||
/// <summary>
|
||||
/// How much energy will be drain from sources
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("energyConsumption")]
|
||||
public float EnergyConsumption = 12500;
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Server.Explosion.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Explosion;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects
|
||||
{
|
||||
@@ -14,7 +14,7 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// <summary>
|
||||
/// The type of explosion. Determines damage types and tile break chance scaling.
|
||||
/// </summary>
|
||||
[DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<ExplosionPrototype>))]
|
||||
[DataField("explosionType", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<ExplosionPrototype>))]
|
||||
[JsonIgnore]
|
||||
public string ExplosionType = default!;
|
||||
|
||||
@@ -22,14 +22,14 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// The max intensity the explosion can have at a given tile. Places an upper limit of damage and tile break
|
||||
/// chance.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("maxIntensity")]
|
||||
[JsonIgnore]
|
||||
public float MaxIntensity = 5;
|
||||
|
||||
/// <summary>
|
||||
/// How quickly intensity drops off as you move away from the epicenter
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("intensitySlope")]
|
||||
[JsonIgnore]
|
||||
public float IntensitySlope = 1;
|
||||
|
||||
@@ -40,14 +40,14 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
/// <remarks>
|
||||
/// A slope of 1 and MaxTotalIntensity of 100 corresponds to a radius of around 4.5 tiles.
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[DataField("maxTotalIntensity")]
|
||||
[JsonIgnore]
|
||||
public float MaxTotalIntensity = 100;
|
||||
|
||||
/// <summary>
|
||||
/// The intensity of the explosion per unit reaction.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("intensityPerUnit")]
|
||||
[JsonIgnore]
|
||||
public float IntensityPerUnit = 1;
|
||||
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using static Robust.Shared.Physics.DynamicTree;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects
|
||||
{
|
||||
@@ -119,3 +121,5 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -10,10 +10,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
/// </summary>
|
||||
public sealed partial class Temperature : ReagentEffectCondition
|
||||
{
|
||||
[DataField]
|
||||
[DataField("min")]
|
||||
public float Min = 0;
|
||||
|
||||
[DataField]
|
||||
[DataField("max")]
|
||||
public float Max = float.PositiveInfinity;
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
{
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions;
|
||||
[UsedImplicitly]
|
||||
public sealed partial class HasTag : ReagentEffectCondition
|
||||
{
|
||||
[DataField(customTypeSerializer: typeof(PrototypeIdSerializer<TagPrototype>))]
|
||||
[DataField("tag", customTypeSerializer: typeof(PrototypeIdSerializer<TagPrototype>))]
|
||||
public string Tag = default!;
|
||||
|
||||
[DataField]
|
||||
[DataField("invert")]
|
||||
public bool Invert = false;
|
||||
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
|
||||
@@ -7,14 +7,16 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
public sealed partial class MobStateCondition : ReagentEffectCondition
|
||||
{
|
||||
[DataField]
|
||||
public MobState Mobstate = MobState.Alive;
|
||||
|
||||
|
||||
[DataField("mobstate")]
|
||||
public MobState mobstate = MobState.Alive;
|
||||
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.EntityManager.TryGetComponent(args.SolutionEntity, out MobStateComponent? mobState))
|
||||
{
|
||||
if (mobState.CurrentState == Mobstate)
|
||||
if (mobState.CurrentState == mobstate)
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -23,7 +25,7 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
|
||||
public override string GuidebookExplanation(IPrototypeManager prototype)
|
||||
{
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-mob-state-condition", ("state", Mobstate));
|
||||
return Loc.GetString("reagent-effect-condition-guidebook-mob-state-condition", ("state", mobstate));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,13 +11,13 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
/// </summary>
|
||||
public sealed partial class OrganType : ReagentEffectCondition
|
||||
{
|
||||
[DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<MetabolizerTypePrototype>))]
|
||||
[DataField("type", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<MetabolizerTypePrototype>))]
|
||||
public string Type = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Does this condition pass when the organ has the type, or when it doesn't have the type?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("shouldHave")]
|
||||
public bool ShouldHave = true;
|
||||
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
|
||||
@@ -13,14 +13,14 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
/// </summary>
|
||||
public sealed partial class ReagentThreshold : ReagentEffectCondition
|
||||
{
|
||||
[DataField]
|
||||
[DataField("min")]
|
||||
public FixedPoint2 Min = FixedPoint2.Zero;
|
||||
|
||||
[DataField]
|
||||
[DataField("max")]
|
||||
public FixedPoint2 Max = FixedPoint2.MaxValue;
|
||||
|
||||
// TODO use ReagentId
|
||||
[DataField]
|
||||
[DataField("reagent")]
|
||||
public string? Reagent;
|
||||
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
|
||||
@@ -9,10 +9,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
/// </summary>
|
||||
public sealed partial class SolutionTemperature : ReagentEffectCondition
|
||||
{
|
||||
[DataField]
|
||||
[DataField("min")]
|
||||
public float Min = 0.0f;
|
||||
|
||||
[DataField]
|
||||
[DataField("max")]
|
||||
public float Max = float.PositiveInfinity;
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
{
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace Content.Server.Chemistry.ReagentEffectConditions
|
||||
{
|
||||
public sealed partial class TotalDamage : ReagentEffectCondition
|
||||
{
|
||||
[DataField]
|
||||
[DataField("max")]
|
||||
public FixedPoint2 Max = FixedPoint2.MaxValue;
|
||||
|
||||
[DataField]
|
||||
[DataField("min")]
|
||||
public FixedPoint2 Min = FixedPoint2.Zero;
|
||||
|
||||
public override bool Condition(ReagentEffectArgs args)
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
@@ -17,11 +17,12 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
return;
|
||||
|
||||
// TODO see if this is correct
|
||||
var solutionContainerSystem = args.EntityManager.System<SolutionContainerSystem>();
|
||||
if (!solutionContainerSystem.TryGetSolution(args.SolutionEntity, _solution, out var solutionContainer))
|
||||
if (!EntitySystem.Get<SolutionContainerSystem>()
|
||||
.TryGetSolution(args.SolutionEntity, _solution, out var solutionContainer))
|
||||
return;
|
||||
|
||||
if (solutionContainerSystem.TryAddReagent(solutionContainer.Value, args.Reagent.ID, args.Quantity, out var accepted))
|
||||
if (EntitySystem.Get<SolutionContainerSystem>()
|
||||
.TryAddReagent(args.SolutionEntity, solutionContainer, args.Reagent.ID, args.Quantity, out var accepted))
|
||||
args.Source?.RemoveReagent(args.Reagent.ID, accepted);
|
||||
}
|
||||
|
||||
|
||||
@@ -10,13 +10,13 @@ public sealed partial class AdjustAlert : ReagentEffect
|
||||
[DataField("alertType", required: true)]
|
||||
public AlertType Type;
|
||||
|
||||
[DataField]
|
||||
[DataField("clear")]
|
||||
public bool Clear;
|
||||
|
||||
[DataField]
|
||||
[DataField("cooldown")]
|
||||
public bool Cooldown;
|
||||
|
||||
[DataField]
|
||||
[DataField("time")]
|
||||
public float Time;
|
||||
|
||||
//JUSTIFICATION: This just changes some visuals, doesn't need to be documented.
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Body.Prototypes;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using JetBrains.Annotations;
|
||||
@@ -13,7 +14,7 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// <summary>
|
||||
/// The reagent ID to remove. Only one of this and <see cref="Group"/> should be active.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||
[DataField("reagent", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||
public string? Reagent = null;
|
||||
// TODO use ReagentId
|
||||
|
||||
@@ -21,39 +22,41 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// The metabolism group to remove, if the reagent satisfies any.
|
||||
/// Only one of this and <see cref="Reagent"/> should be active.
|
||||
/// </summary>
|
||||
[DataField(customTypeSerializer: typeof(PrototypeIdSerializer<MetabolismGroupPrototype>))]
|
||||
[DataField("group", customTypeSerializer:typeof(PrototypeIdSerializer<MetabolismGroupPrototype>))]
|
||||
public string? Group = null;
|
||||
|
||||
[DataField(required: true)]
|
||||
[DataField("amount", required: true)]
|
||||
public FixedPoint2 Amount = default!;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
if (args.Source == null)
|
||||
return;
|
||||
|
||||
var amount = Amount;
|
||||
amount *= args.Scale;
|
||||
|
||||
if (Reagent != null)
|
||||
if (args.Source != null)
|
||||
{
|
||||
if (amount < 0 && args.Source.ContainsPrototype(Reagent))
|
||||
args.Source.RemoveReagent(Reagent, -amount);
|
||||
if (amount > 0)
|
||||
args.Source.AddReagent(Reagent, amount);
|
||||
}
|
||||
else if (Group != null)
|
||||
{
|
||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
foreach (var quant in args.Source.Contents.ToArray())
|
||||
var solutionSys = args.EntityManager.EntitySysManager.GetEntitySystem<SolutionContainerSystem>();
|
||||
var amount = Amount;
|
||||
|
||||
amount *= args.Scale;
|
||||
|
||||
if (Reagent != null)
|
||||
{
|
||||
var proto = prototypeMan.Index<ReagentPrototype>(quant.Reagent.Prototype);
|
||||
if (proto.Metabolisms != null && proto.Metabolisms.ContainsKey(Group))
|
||||
if (amount < 0 && args.Source.ContainsPrototype(Reagent))
|
||||
solutionSys.RemoveReagent(args.SolutionEntity, args.Source, Reagent, -amount);
|
||||
if (amount > 0)
|
||||
solutionSys.TryAddReagent(args.SolutionEntity, args.Source, Reagent, amount, out _);
|
||||
}
|
||||
else if (Group != null)
|
||||
{
|
||||
var prototypeMan = IoCManager.Resolve<IPrototypeManager>();
|
||||
foreach (var quant in args.Source.Contents.ToArray())
|
||||
{
|
||||
if (amount < 0)
|
||||
args.Source.RemoveReagent(quant.Reagent, amount);
|
||||
if (amount > 0)
|
||||
args.Source.AddReagent(quant.Reagent, amount);
|
||||
var proto = prototypeMan.Index<ReagentPrototype>(quant.Reagent.Prototype);
|
||||
if (proto.Metabolisms != null && proto.Metabolisms.ContainsKey(Group))
|
||||
{
|
||||
if (amount < 0)
|
||||
solutionSys.RemoveReagent(args.SolutionEntity, args.Source, quant.Reagent, amount);
|
||||
if (amount > 0)
|
||||
solutionSys.TryAddReagent(args.SolutionEntity, args.Source, quant.Reagent, amount, out _);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
public sealed partial class AdjustTemperature : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("amount")]
|
||||
public float Amount;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
using Content.Server.Zombies;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
using Robust.Shared.Configuration;
|
||||
using Content.Server.Zombies;
|
||||
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class CauseZombieInfection : ReagentEffect
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using Content.Server.Body.Systems;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using JetBrains.Annotations;
|
||||
using Content.Server.Body.Systems;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects
|
||||
@@ -11,7 +11,7 @@ namespace Content.Server.Chemistry.ReactionEffects
|
||||
[UsedImplicitly]
|
||||
public sealed partial class ChemCleanBloodstream : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("cleanseRate")]
|
||||
public float CleanseRate = 3.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -15,7 +15,7 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// <summary>
|
||||
/// How much eye damage to add.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("amount")]
|
||||
public int Amount = -1;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
using Content.Server.Medical;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Medical;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
@@ -12,10 +12,10 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
public sealed partial class ChemVomit : ReagentEffect
|
||||
{
|
||||
/// How many units of thirst to add each time we vomit
|
||||
[DataField]
|
||||
[DataField("thirstAmount")]
|
||||
public float ThirstAmount = -8f;
|
||||
/// How many units of hunger to add each time we vomit
|
||||
[DataField]
|
||||
[DataField("hungerAmount")]
|
||||
public float HungerAmount = -8f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class CreateGas : ReagentEffect
|
||||
{
|
||||
[DataField(required: true)]
|
||||
[DataField("gas", required: true)]
|
||||
public Gas Gas = default!;
|
||||
|
||||
/// <summary>
|
||||
/// For each unit consumed, how many moles of gas should be created?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("multiplier")]
|
||||
public float Multiplier = 3f;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
using Content.Server.Zombies;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Configuration;
|
||||
using Content.Server.Zombies;
|
||||
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class CureZombieInfection : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("innoculate")]
|
||||
public bool Innoculate;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -9,13 +9,13 @@ public sealed partial class Drunk : ReagentEffect
|
||||
/// <summary>
|
||||
/// BoozePower is how long each metabolism cycle will make the drunk effect last for.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("boozePower")]
|
||||
public float BoozePower = 3f;
|
||||
|
||||
/// <summary>
|
||||
/// Whether speech should be slurred.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("slurSpeech")]
|
||||
public bool SlurSpeech = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -6,14 +6,14 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class Electrocute : ReagentEffect
|
||||
{
|
||||
[DataField] public int ElectrocuteTime = 2;
|
||||
[DataField("electrocuteTime")] public int ElectrocuteTime = 2;
|
||||
|
||||
[DataField] public int ElectrocuteDamageScale = 5;
|
||||
[DataField("electrocuteDamageScale")] public int ElectrocuteDamageScale = 5;
|
||||
|
||||
/// <remarks>
|
||||
/// true - refresh electrocute time, false - accumulate electrocute time
|
||||
/// </remarks>
|
||||
[DataField] public bool Refresh = true;
|
||||
[DataField("refresh")] public bool Refresh = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-electrocute", ("chance", Probability), ("time", ElectrocuteTime));
|
||||
|
||||
@@ -16,7 +16,7 @@ public sealed partial class Emote : ReagentEffect
|
||||
[DataField("emote", customTypeSerializer: typeof(PrototypeIdSerializer<EmotePrototype>))]
|
||||
public string? EmoteId;
|
||||
|
||||
[DataField]
|
||||
[DataField("showInChat")]
|
||||
public bool ShowInChat;
|
||||
|
||||
// JUSTIFICATION: Emoting is flavor, so same reason popup messages are not in here.
|
||||
|
||||
@@ -10,7 +10,7 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
[UsedImplicitly]
|
||||
public sealed partial class FlammableReaction : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("multiplier")]
|
||||
public float Multiplier = 0.05f;
|
||||
|
||||
public override bool ShouldLog => true;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Damage;
|
||||
using Content.Shared.Damage.Prototypes;
|
||||
@@ -5,8 +7,6 @@ using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Localizations;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Shared.Prototypes;
|
||||
using System.Linq;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
@@ -19,19 +19,19 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// <summary>
|
||||
/// Damage to apply every metabolism cycle. Damage Ignores resistances.
|
||||
/// </summary>
|
||||
[DataField(required: true)]
|
||||
[JsonPropertyName("damage")]
|
||||
[DataField("damage", required: true)]
|
||||
public DamageSpecifier Damage = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Should this effect scale the damage by the amount of chemical in the solution?
|
||||
/// Useful for touch reactions, like styptic powder or acid.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[JsonPropertyName("scaleByQuantity")]
|
||||
[DataField("scaleByQuantity")]
|
||||
public bool ScaleByQuantity;
|
||||
|
||||
[DataField]
|
||||
[DataField("ignoreResistances")]
|
||||
[JsonPropertyName("ignoreResistances")]
|
||||
public bool IgnoreResistances = true;
|
||||
|
||||
|
||||
@@ -7,10 +7,10 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class ModifyBleedAmount : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("scaled")]
|
||||
public bool Scaled = false;
|
||||
|
||||
[DataField]
|
||||
[DataField("amount")]
|
||||
public float Amount = -1.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -8,10 +8,10 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class ModifyBloodLevel : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("scaled")]
|
||||
public bool Scaled = false;
|
||||
|
||||
[DataField]
|
||||
[DataField("amount")]
|
||||
public FixedPoint2 Amount = 1.0f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -15,19 +15,19 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
/// <summary>
|
||||
/// How much the entities' walk speed is multiplied by.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("walkSpeedModifier")]
|
||||
public float WalkSpeedModifier { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// How much the entities' run speed is multiplied by.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("sprintSpeedModifier")]
|
||||
public float SprintSpeedModifier { get; set; } = 1;
|
||||
|
||||
/// <summary>
|
||||
/// How long the modifier applies (in seconds) when metabolized.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("statusLifetime")]
|
||||
public float StatusLifetime = 2f;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class Oxygenate : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("factor")]
|
||||
public float Factor = 1f;
|
||||
|
||||
// JUSTIFICATION: This is internal magic that players never directly interact with.
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
using Content.Server.Stunnable;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Server.Stunnable;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects;
|
||||
|
||||
public sealed partial class Paralyze : ReagentEffect
|
||||
{
|
||||
[DataField] public double ParalyzeTime = 2;
|
||||
[DataField("paralyzeTime")] public double ParalyzeTime = 2;
|
||||
|
||||
/// <remarks>
|
||||
/// true - refresh paralyze time, false - accumulate paralyze time
|
||||
/// </remarks>
|
||||
[DataField] public bool Refresh = true;
|
||||
[DataField("refresh")] public bool Refresh = true;
|
||||
|
||||
protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys)
|
||||
=> Loc.GetString("reagent-effect-guidebook-paralyze",
|
||||
|
||||
@@ -1,19 +1,16 @@
|
||||
using Content.Server.Botany.Components;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using Content.Server.Botany.Components;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
|
||||
namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
{
|
||||
[ImplicitDataDefinitionForInheritors]
|
||||
public abstract partial class PlantAdjustAttribute : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
public float Amount { get; protected set; } = 1;
|
||||
|
||||
[DataField]
|
||||
public float Prob { get; protected set; } = 1; // = (80);
|
||||
[DataField("amount")] public float Amount { get; protected set; } = 1;
|
||||
[DataField("prob")] public float Prob { get; protected set; } = 1; // = (80);
|
||||
|
||||
/// <summary>
|
||||
/// Checks if the plant holder can metabolize the reagent or not. Checks if it has an alive plant by default.
|
||||
|
||||
@@ -11,13 +11,13 @@ namespace Content.Server.Chemistry.ReagentEffects.PlantMetabolism
|
||||
[DataDefinition]
|
||||
public sealed partial class RobustHarvest : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("potencyLimit")]
|
||||
public int PotencyLimit = 50;
|
||||
|
||||
[DataField]
|
||||
[DataField("potencyIncrease")]
|
||||
public int PotencyIncrease = 3;
|
||||
|
||||
[DataField]
|
||||
[DataField("potencySeedlessThreshold")]
|
||||
public int PotencySeedlessThreshold = 30;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -8,13 +8,13 @@ namespace Content.Server.Chemistry.ReagentEffects
|
||||
{
|
||||
public sealed partial class PopupMessage : ReagentEffect
|
||||
{
|
||||
[DataField(required: true)]
|
||||
[DataField("messages", required: true)]
|
||||
public string[] Messages = default!;
|
||||
|
||||
[DataField]
|
||||
[DataField("type")]
|
||||
public PopupRecipients Type = PopupRecipients.Local;
|
||||
|
||||
[DataField]
|
||||
[DataField("visualType")]
|
||||
public PopupType VisualType = PopupType.Small;
|
||||
|
||||
// JUSTIFICATION: This is purely cosmetic.
|
||||
|
||||
@@ -17,25 +17,25 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
[UsedImplicitly]
|
||||
public sealed partial class GenericStatusEffect : ReagentEffect
|
||||
{
|
||||
[DataField(required: true)]
|
||||
[DataField("key", required: true)]
|
||||
public string Key = default!;
|
||||
|
||||
[DataField]
|
||||
[DataField("component")]
|
||||
public string Component = String.Empty;
|
||||
|
||||
[DataField]
|
||||
[DataField("time")]
|
||||
public float Time = 2.0f;
|
||||
|
||||
/// <remarks>
|
||||
/// true - refresh status effect time, false - accumulate status effect time
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[DataField("refresh")]
|
||||
public bool Refresh = true;
|
||||
|
||||
/// <summary>
|
||||
/// Should this effect add the status effect, remove time from it, or set its cooldown?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("type")]
|
||||
public StatusEffectMetabolismType Type = StatusEffectMetabolismType.Add;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -11,19 +11,19 @@ namespace Content.Server.Chemistry.ReagentEffects.StatusEffects
|
||||
/// </summary>
|
||||
public sealed partial class Jitter : ReagentEffect
|
||||
{
|
||||
[DataField]
|
||||
[DataField("amplitude")]
|
||||
public float Amplitude = 10.0f;
|
||||
|
||||
[DataField]
|
||||
[DataField("frequency")]
|
||||
public float Frequency = 4.0f;
|
||||
|
||||
[DataField]
|
||||
[DataField("time")]
|
||||
public float Time = 2.0f;
|
||||
|
||||
/// <remarks>
|
||||
/// true - refresh jitter time, false - accumulate jitter time
|
||||
/// </remarks>
|
||||
[DataField]
|
||||
[DataField("refresh")]
|
||||
public bool Refresh = true;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Content.Server.Decals;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
@@ -5,7 +6,6 @@ using Content.Shared.Decals;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Chemistry.TileReactions;
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed partial class CleanDecalsReaction : ITileReaction
|
||||
/// <summary>
|
||||
/// For every cleaned decal we lose this much reagent.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("cleanCost")]
|
||||
public FixedPoint2 CleanCost { get; private set; } = FixedPoint2.New(0.25f);
|
||||
|
||||
public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using Content.Server.Chemistry.Containers.EntitySystems;
|
||||
using System.Linq;
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Fluids.Components;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using System.Linq;
|
||||
|
||||
namespace Content.Server.Chemistry.TileReactions;
|
||||
|
||||
@@ -28,7 +28,7 @@ public sealed partial class CleanTileReaction : ITileReaction
|
||||
/// <summary>
|
||||
/// What reagent to replace the tile conents with.
|
||||
/// </summary>
|
||||
[DataField("reagent", customTypeSerializer: typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||
[DataField("reagent", customTypeSerializer:typeof(PrototypeIdSerializer<ReagentPrototype>))]
|
||||
public string ReplacementReagent = "Water";
|
||||
|
||||
FixedPoint2 ITileReaction.TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume)
|
||||
@@ -43,16 +43,17 @@ public sealed partial class CleanTileReaction : ITileReaction
|
||||
foreach (var entity in entities)
|
||||
{
|
||||
if (!puddleQuery.TryGetComponent(entity, out var puddle) ||
|
||||
!solutionContainerSystem.TryGetSolution(entity, puddle.SolutionName, out var puddleSolution, out _))
|
||||
!solutionContainerSystem.TryGetSolution(entity, puddle.SolutionName, out var puddleSolution))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var purgeable = solutionContainerSystem.SplitSolutionWithout(puddleSolution.Value, purgeAmount, ReplacementReagent, reagent.ID);
|
||||
var purgeable =
|
||||
solutionContainerSystem.SplitSolutionWithout(entity, puddleSolution, purgeAmount, ReplacementReagent, reagent.ID);
|
||||
|
||||
purgeAmount -= purgeable.Volume;
|
||||
|
||||
solutionContainerSystem.TryAddSolution(puddleSolution.Value, new Solution(ReplacementReagent, purgeable.Volume));
|
||||
solutionContainerSystem.TryAddSolution(entity, puddleSolution, new Solution(ReplacementReagent, purgeable.Volume));
|
||||
|
||||
if (purgeable.Volume <= FixedPoint2.Zero)
|
||||
break;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Chemistry.Reaction;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Maps;
|
||||
@@ -7,23 +8,22 @@ using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Random;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Server.Chemistry.TileReactions;
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class CreateEntityTileReaction : ITileReaction
|
||||
{
|
||||
[DataField(required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
[DataField("entity", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Entity = default!;
|
||||
|
||||
[DataField]
|
||||
[DataField("usage")]
|
||||
public FixedPoint2 Usage = FixedPoint2.New(1);
|
||||
|
||||
/// <summary>
|
||||
/// How many of the whitelisted entity can fit on one tile?
|
||||
/// </summary>
|
||||
[DataField]
|
||||
[DataField("maxOnTile")]
|
||||
public int MaxOnTile = 1;
|
||||
|
||||
/// <summary>
|
||||
@@ -32,7 +32,7 @@ public sealed partial class CreateEntityTileReaction : ITileReaction
|
||||
[DataField("maxOnTileWhitelist")]
|
||||
public EntityWhitelist? Whitelist;
|
||||
|
||||
[DataField]
|
||||
[DataField("randomOffsetMax")]
|
||||
public float RandomOffsetMax = 0.0f;
|
||||
|
||||
public FixedPoint2 TileReact(TileRef tile, ReagentPrototype reagent, FixedPoint2 reactVolume)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user