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; solution.MaxVolume = _initialMaxVolume;
} }
public bool TryTransferSolution(Solution solution) public bool CanTransferSolution(Solution solution)
{ {
if (!Owner.TryGetComponent(out SolutionContainerComponent? solutionComponent)) 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 // TODO: For now no partial transfers. Potentially change by design
if (solution.TotalVolume + solutionComponent.CurrentVolume > solutionComponent.MaxVolume) if (!solutionComponent.CanAddSolution(solution))
{ {
return false; return false;
} }
return true;
}
public bool TryTransferSolution(Solution solution)
{
if (!CanTransferSolution(solution))
return false;
var solutionComponent = Owner.GetComponent<SolutionContainerComponent>();
// Add solution to _stomachContents // Add solution to _stomachContents
solutionComponent.TryAddSolution(solution, false, true); solutionComponent.TryAddSolution(solution, false, true);
// Add each reagent to _reagentDeltas. Used to track how long each reagent has been in the stomach // 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 Content.Shared.Utility;
using Robust.Shared.GameObjects; using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -22,6 +24,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
[RegisterComponent] [RegisterComponent]
public class InjectorComponent : SharedInjectorComponent, IAfterInteract, IUse public class InjectorComponent : SharedInjectorComponent, IAfterInteract, IUse
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
/// <summary> /// <summary>
/// Whether or not the injector is able to draw from containers or if it's a single use /// Whether or not the injector is able to draw from containers or if it's a single use
/// device that can only inject. /// device that can only inject.
@@ -186,11 +190,27 @@ namespace Content.Server.GameObjects.Components.Chemistry
// Move units from attackSolution to targetSolution // Move units from attackSolution to targetSolution
var removedSolution = solution.SplitSolution(realTransferAmount); var removedSolution = solution.SplitSolution(realTransferAmount);
if (!targetBloodstream.TryTransferSolution(removedSolution)) if (!solution.CanAddSolution(removedSolution))
{ {
return; 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)); Owner.PopupMessage(user, Loc.GetString("You inject {0}u into {1:theName}!", removedSolution.TotalVolume, targetBloodstream.Owner));
Dirty(); Dirty();
} }
@@ -214,11 +234,19 @@ namespace Content.Server.GameObjects.Components.Chemistry
// Move units from attackSolution to targetSolution // Move units from attackSolution to targetSolution
var removedSolution = solution.SplitSolution(realTransferAmount); var removedSolution = solution.SplitSolution(realTransferAmount);
if (!targetSolution.TryAddSolution(removedSolution)) if (!targetSolution.CanAddSolution(removedSolution))
{ {
return; 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)); Owner.PopupMessage(user, Loc.GetString("You transfter {0}u to {1:theName}", removedSolution.TotalVolume, targetSolution.Owner));
Dirty(); Dirty();
} }

View File

@@ -11,6 +11,8 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Log;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -21,6 +23,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
public class PillComponent : FoodComponent, IUse, IAfterInteract public class PillComponent : FoodComponent, IUse, IAfterInteract
{ {
[Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "Pill"; public override string Name => "Pill";
@@ -46,7 +49,10 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
base.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) bool IUse.UseEntity(UseEntityEventArgs eventArgs)
@@ -86,13 +92,24 @@ namespace Content.Server.GameObjects.Components.Chemistry
var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume); var transferAmount = ReagentUnit.Min(_transferAmount, _contents.CurrentVolume);
var split = _contents.SplitSolution(transferAmount); var split = _contents.SplitSolution(transferAmount);
if (!stomach.TryTransferSolution(split))
if (!stomach.CanTransferSolution(split))
{ {
_contents.TryAddSolution(split); _contents.TryAddSolution(split);
trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!")); trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!"));
return false; 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) if (_useSound != null)
{ {
_entitySystem.GetEntitySystem<AudioSystem>() _entitySystem.GetEntitySystem<AudioSystem>()

View File

@@ -393,9 +393,14 @@ namespace Content.Server.GameObjects.Components.Chemistry
return true; return true;
} }
public bool CanAddSolution(Solution solution)
{
return solution.TotalVolume <= (MaxVolume - Solution.TotalVolume);
}
public bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false) public bool TryAddSolution(Solution solution, bool skipReactionCheck = false, bool skipColor = false)
{ {
if (solution.TotalVolume > (MaxVolume - Solution.TotalVolume)) if (!CanAddSolution(solution))
return false; return false;
Solution.AddSolution(solution); Solution.AddSolution(solution);

View File

@@ -157,7 +157,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
var transferAmount = ReagentUnit.Min(TransferAmount, _contents.CurrentVolume); var transferAmount = ReagentUnit.Min(TransferAmount, _contents.CurrentVolume);
var split = _contents.SplitSolution(transferAmount); var split = _contents.SplitSolution(transferAmount);
if (stomachComponent.TryTransferSolution(split)) if (stomachComponent.CanTransferSolution(split))
{ {
if (_useSound == null) if (_useSound == null)
{ {
@@ -167,6 +167,17 @@ namespace Content.Server.GameObjects.Components.Nutrition
EntitySystem.Get<AudioSystem>().PlayFromEntity(_useSound, target, AudioParams.Default.WithVolume(-2f)); EntitySystem.Get<AudioSystem>().PlayFromEntity(_useSound, target, AudioParams.Default.WithVolume(-2f));
target.PopupMessage(Loc.GetString("Slurp")); target.PopupMessage(Loc.GetString("Slurp"));
UpdateAppearance(); 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; return true;
} }

View File

@@ -17,6 +17,7 @@ using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects; using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC; using Robust.Shared.IoC;
using Robust.Shared.Localization; using Robust.Shared.Localization;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
@@ -27,6 +28,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
public class FoodComponent : Component, IUse, IAfterInteract public class FoodComponent : Component, IUse, IAfterInteract
{ {
[Dependency] private readonly IEntitySystemManager _entitySystem = default!; [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
public override string Name => "Food"; public override string Name => "Food";
@@ -169,13 +171,22 @@ namespace Content.Server.GameObjects.Components.Nutrition
var transferAmount = ReagentUnit.Min(_transferAmount, solution.CurrentVolume); var transferAmount = ReagentUnit.Min(_transferAmount, solution.CurrentVolume);
var split = solution.SplitSolution(transferAmount); 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!")); trueTarget.PopupMessage(user, Loc.GetString("You can't eat any more!"));
return false; 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>() _entitySystem.GetEntitySystem<AudioSystem>()
.PlayFromEntity(_useSound, trueTarget, AudioParams.Default.WithVolume(-1f)); .PlayFromEntity(_useSound, trueTarget, AudioParams.Default.WithVolume(-1f));
trueTarget.PopupMessage(user, Loc.GetString("Nom")); 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 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 #region Enumeration