Adds missing reactions to chemical stuff.

- Adds ingestion reaction for food, drinks, and pills.
- Adds injection reaction for syringes.
This commit is contained in:
Víctor Aguilera Puerto
2020-09-26 14:48:24 +02:00
parent 62288dd7ec
commit 4eb5891c4a
7 changed files with 107 additions and 19 deletions

View File

@@ -72,7 +72,7 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
solution.MaxVolume = _initialMaxVolume;
}
public bool TryTransferSolution(Solution solution)
public bool CanTransferSolution(Solution solution)
{
if (!Owner.TryGetComponent(out SolutionContainerComponent? solutionComponent))
{
@@ -80,11 +80,21 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
}
// TODO: For now no partial transfers. Potentially change by design
if (solution.TotalVolume + solutionComponent.CurrentVolume > solutionComponent.MaxVolume)
if (!solutionComponent.CanAddSolution(solution))
{
return false;
}
return true;
}
public bool TryTransferSolution(Solution solution)
{
if (!CanTransferSolution(solution))
return false;
var solutionComponent = Owner.GetComponent<SolutionContainerComponent>();
// Add solution to _stomachContents
solutionComponent.TryAddSolution(solution, false, true);
// Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach

View File

@@ -8,7 +8,9 @@ using Content.Shared.Interfaces.GameObjects.Components;
using Content.Shared.Utility;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -22,6 +24,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
[RegisterComponent]
public class InjectorComponent : SharedInjectorComponent, IAfterInteract, IUse
{
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary>
/// Whether or not the injector is able to draw from containers or if it's a single use
/// device that can only inject.
@@ -126,7 +130,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
else
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You aren't able to transfer to {0:theName}!", targetSolution.Owner));
}
}
}
else if (_toggleState == InjectorToggleMode.Draw)
{
@@ -186,11 +190,27 @@ namespace Content.Server.GameObjects.Components.Chemistry
// Move units from attackSolution to targetSolution
var removedSolution = solution.SplitSolution(realTransferAmount);
if (!targetBloodstream.TryTransferSolution(removedSolution))
if (!solution.CanAddSolution(removedSolution))
{
return;
}
// TODO: Account for partial transfer.
foreach (var (reagentId, quantity) in removedSolution.Contents)
{
if(!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
removedSolution.RemoveReagent(reagentId, reagent.ReactionEntity(solution.Owner, ReactionMethod.Injection, quantity));
}
solution.TryAddSolution(removedSolution);
foreach (var (reagentId, quantity) in removedSolution.Contents)
{
if(!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
reagent.ReactionEntity(targetBloodstream.Owner, ReactionMethod.Injection, quantity);
}
Owner.PopupMessage(user, Loc.GetString("You inject {0}u into {1:theName}!", removedSolution.TotalVolume, targetBloodstream.Owner));
Dirty();
}
@@ -214,11 +234,19 @@ namespace Content.Server.GameObjects.Components.Chemistry
// Move units from attackSolution to targetSolution
var removedSolution = solution.SplitSolution(realTransferAmount);
if (!targetSolution.TryAddSolution(removedSolution))
if (!targetSolution.CanAddSolution(removedSolution))
{
return;
}
foreach (var (reagentId, quantity) in removedSolution.Contents)
{
if(!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
removedSolution.RemoveReagent(reagentId, reagent.ReactionEntity(targetSolution.Owner, ReactionMethod.Injection, quantity));
}
targetSolution.TryAddSolution(removedSolution);
Owner.PopupMessage(user, Loc.GetString("You transfter {0}u to {1:theName}", removedSolution.TotalVolume, targetSolution.Owner));
Dirty();
}

View File

@@ -11,6 +11,8 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -21,6 +23,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
public class PillComponent : FoodComponent, IUse, IAfterInteract
{
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "Pill";
@@ -45,8 +48,11 @@ namespace Content.Server.GameObjects.Components.Chemistry
public override void Initialize()
{
base.Initialize();
_contents = Owner.GetComponent<SolutionContainerComponent>();
if (!Owner.EnsureComponent(out _contents))
{
Logger.Error($"Prototype {Owner.Prototype?.ID} had a {nameof(PillComponent)} without a {nameof(SolutionContainerComponent)}!");
}
}
bool IUse.UseEntity(UseEntityEventArgs eventArgs)
@@ -86,13 +92,24 @@ namespace Content.Server.GameObjects.Components.Chemistry
var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume);
var split = _contents.SplitSolution(transferAmount);
if (!stomach.TryTransferSolution(split))
if (!stomach.CanTransferSolution(split))
{
_contents.TryAddSolution(split);
trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!"));
return false;
}
// TODO: Account for partial transfer.
foreach (var (reagentId, quantity) in split.Contents)
{
if (!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
split.RemoveReagent(reagentId, reagent.ReactionEntity(trueTarget, ReactionMethod.Ingestion, quantity));
}
stomach.TryTransferSolution(split);
if (_useSound != null)
{
_entitySystem.GetEntitySystem<AudioSystem>()

View File

@@ -91,7 +91,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
serializer.DataField(this, x => MaxVolume, "maxVol", ReagentUnit.New(0));
serializer.DataField(this, x => Solution, "contents", new Solution());
serializer.DataField(this, x => Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom);
serializer.DataField(this, x => Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom);
serializer.DataField(ref _fillInitState, "fillingState", string.Empty);
serializer.DataField(ref _fillInitSteps, "fillingSteps", 7);
}
@@ -147,7 +147,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
return false;
}
Solution.RemoveSolution(quantity);
OnSolutionChanged(false);
return true;
@@ -179,7 +179,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
continue;
}
if (mixColor == default)
{
mixColor = proto.SubstanceColor;
@@ -229,13 +229,13 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
return;
}
if (!hands.GetActiveHand.Owner.TryGetComponent<SolutionContainerComponent>(out var handSolutionComp) ||
!handSolutionComp.CanRemoveSolutions ||
!component.CanAddSolutions)
{
return;
}
}
var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume, ReagentUnit.New(10));
@@ -243,7 +243,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
{
return;
}
var transferSolution = handSolutionComp.SplitSolution(transferQuantity);
component.TryAddSolution(transferSolution);
}
@@ -393,9 +393,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
return true;
}
public bool CanAddSolution(Solution solution)
{
return solution.TotalVolume <= (MaxVolume - Solution.TotalVolume);
}
public bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
{
if (solution.TotalVolume > (MaxVolume - Solution.TotalVolume))
if (!CanAddSolution(solution))
return false;
Solution.AddSolution(solution);

View File

@@ -145,7 +145,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
{
target.PopupMessage(Loc.GetString("{0:theName} is empty!", Owner));
}
return false;
}
@@ -157,7 +157,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
var transferAmount = ReagentUnit.Min(TransferAmount, _contents.CurrentVolume);
var split = _contents.SplitSolution(transferAmount);
if (stomachComponent.TryTransferSolution(split))
if (stomachComponent.CanTransferSolution(split))
{
if (_useSound == null)
{
@@ -167,6 +167,17 @@ namespace Content.Server.GameObjects.Components.Nutrition
EntitySystem.Get<AudioSystem>().PlayFromEntity(_useSound, target, AudioParams.Default.WithVolume(-2f));
target.PopupMessage(Loc.GetString("Slurp"));
UpdateAppearance();
// TODO: Account for partial transfer.
foreach (var (reagentId, quantity) in split.Contents)
{
if (!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
split.RemoveReagent(reagentId, reagent.ReactionEntity(target, ReactionMethod.Ingestion, quantity));
}
stomachComponent.TryTransferSolution(split);
return true;
}

View File

@@ -17,6 +17,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables;
@@ -27,6 +28,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
public class FoodComponent : Component, IUse, IAfterInteract
{
[Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "Food";
@@ -169,13 +171,22 @@ namespace Content.Server.GameObjects.Components.Nutrition
var transferAmount = ReagentUnit.Min(_transferAmount, solution.CurrentVolume);
var split = solution.SplitSolution(transferAmount);
if (!stomach.TryTransferSolution(split))
if (!stomach.CanTransferSolution(split))
{
solution.TryAddSolution(split);
trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!"));
return false;
}
// TODO: Account for partial transfer.
foreach (var (reagentId, quantity) in split.Contents)
{
if (!_prototypeManager.TryIndex(reagentId, out ReagentPrototype reagent)) continue;
split.RemoveReagent(reagentId, reagent.ReactionEntity(target, ReactionMethod.Ingestion, quantity));
}
stomach.TryTransferSolution(split);
_entitySystem.GetEntitySystem<AudioSystem>()
.PlayFromEntity(_useSound, trueTarget, AudioParams.Default.WithVolume(-1f));
trueTarget.PopupMessage(user, Loc.GetString("Nom"));

View File

@@ -264,6 +264,12 @@ namespace Content.Shared.Chemistry
}
public int CompareTo(ReagentQuantity other) { return Quantity.Float().CompareTo(other.Quantity.Float()); }
public void Deconstruct(out string reagentId, out ReagentUnit quantity)
{
reagentId = ReagentId;
quantity = Quantity;
}
}
#region Enumeration