Add text coloring for inspected solution containers, code cleanup (#2010)

* Initial commit

* remove helper

* fixes

* small fix
This commit is contained in:
nuke
2020-09-09 18:32:31 -04:00
committed by GitHub
parent f7a5bad839
commit 753a627c75
56 changed files with 981 additions and 726 deletions

View File

@@ -64,7 +64,7 @@ namespace Content.Client
factory.Register<SharedLatheComponent>(); factory.Register<SharedLatheComponent>();
factory.Register<SharedSpawnPointComponent>(); factory.Register<SharedSpawnPointComponent>();
factory.Register<SharedSolutionComponent>(); factory.Register<SharedSolutionContainerComponent>();
factory.Register<SharedVendingMachineComponent>(); factory.Register<SharedVendingMachineComponent>();
factory.Register<SharedWiresComponent>(); factory.Register<SharedWiresComponent>();

View File

@@ -10,7 +10,7 @@ namespace Content.Server.AI.Utility.Considerations.Nutrition.Drink
{ {
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (!target.TryGetComponent(out SolutionComponent drink)) if (!target.TryGetComponent(out SolutionContainerComponent drink))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -10,7 +10,7 @@ namespace Content.Server.AI.Utility.Considerations.Nutrition.Food
{ {
var target = context.GetState<TargetEntityState>().GetValue(); var target = context.GetState<TargetEntityState>().GetValue();
if (!target.TryGetComponent(out SolutionComponent food)) if (!target.TryGetComponent(out SolutionContainerComponent food))
{ {
return 0.0f; return 0.0f;
} }

View File

@@ -41,7 +41,7 @@ namespace Content.Server.Atmos
public void AfterInteract(AfterInteractEventArgs eventArgs) public void AfterInteract(AfterInteractEventArgs eventArgs)
{ {
if (!Owner.TryGetComponent(out SolutionComponent tank)) if (!Owner.TryGetComponent(out SolutionContainerComponent tank))
return; return;
if (tank.Solution.GetReagentQuantity(_fuelType) == 0) if (tank.Solution.GetReagentQuantity(_fuelType) == 0)

View File

@@ -40,7 +40,7 @@ namespace Content.Server.Chemistry.ReactionEffects
float floatIntensity = (float)intensity; float floatIntensity = (float)intensity;
if (solutionEntity == null) if (solutionEntity == null)
return; return;
if(!solutionEntity.TryGetComponent(out SolutionComponent solution)) if(!solutionEntity.TryGetComponent(out SolutionContainerComponent solution))
return; return;
//Handle scaling //Handle scaling

View File

@@ -22,7 +22,7 @@ namespace Content.Server.GameObjects.Components.Body.Circulatory
/// <summary> /// <summary>
/// Internal solution for reagent storage /// Internal solution for reagent storage
/// </summary> /// </summary>
[ViewVariables] private SolutionComponent _internalSolution; [ViewVariables] private SolutionContainerComponent _internalSolution;
/// <summary> /// <summary>
/// Empty volume of internal solution /// Empty volume of internal solution
@@ -31,13 +31,13 @@ namespace Content.Server.GameObjects.Components.Body.Circulatory
[ViewVariables] public GasMixture Air { get; set; } [ViewVariables] public GasMixture Air { get; set; }
[ViewVariables] public SolutionComponent Solution => _internalSolution; [ViewVariables] public SolutionContainerComponent Solution => _internalSolution;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_internalSolution = Owner.EnsureComponent<SolutionComponent>(); _internalSolution = Owner.EnsureComponent<SolutionContainerComponent>();
_internalSolution.MaxVolume = _initialMaxVolume; _internalSolution.MaxVolume = _initialMaxVolume;
} }

View File

@@ -24,10 +24,10 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
/// </summary> /// </summary>
public ReagentUnit MaxVolume public ReagentUnit MaxVolume
{ {
get => Owner.TryGetComponent(out SolutionComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero; get => Owner.TryGetComponent(out SolutionContainerComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero;
set set
{ {
if (Owner.TryGetComponent(out SolutionComponent? solution)) if (Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
solution.MaxVolume = value; solution.MaxVolume = value;
} }
@@ -64,9 +64,9 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
{ {
base.Startup(); base.Startup();
if (!Owner.EnsureComponent(out SolutionComponent solution)) if (!Owner.EnsureComponent(out SolutionContainerComponent solution))
{ {
Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}"); Logger.Warning($"Entity {Owner} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
} }
solution.MaxVolume = _initialMaxVolume; solution.MaxVolume = _initialMaxVolume;
@@ -74,7 +74,7 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
public bool TryTransferSolution(Solution solution) public bool TryTransferSolution(Solution solution)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solutionComponent)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solutionComponent))
{ {
return false; return false;
} }
@@ -104,7 +104,7 @@ namespace Content.Server.GameObjects.Components.Body.Digestive
/// <param name="frameTime">The time since the last update in seconds.</param> /// <param name="frameTime">The time since the last update in seconds.</param>
public void Update(float frameTime) public void Update(float frameTime)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solutionComponent) || if (!Owner.TryGetComponent(out SolutionContainerComponent? solutionComponent) ||
!Owner.TryGetComponent(out BloodstreamComponent? bloodstream)) !Owner.TryGetComponent(out BloodstreamComponent? bloodstream))
{ {
return; return;

View File

@@ -42,14 +42,12 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
[ViewVariables] private ContainerSlot _beakerContainer = default!; [ViewVariables] private ContainerSlot _beakerContainer = default!;
[ViewVariables] private string _packPrototypeId = ""; [ViewVariables] private string _packPrototypeId = "";
[ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null; [ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null;
[ViewVariables] private bool _bufferModeTransfer = true; [ViewVariables] private bool _bufferModeTransfer = true;
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
[ViewVariables] private readonly SolutionComponent BufferSolution = new SolutionComponent(); [ViewVariables] private readonly SolutionContainerComponent BufferSolution = new SolutionContainerComponent();
[ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ChemMasterUiKey.Key); [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ChemMasterUiKey.Key);
@@ -179,7 +177,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
"", Owner.Name, new List<Solution.ReagentQuantity>(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume); "", Owner.Name, new List<Solution.ReagentQuantity>(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
} }
var solution = beaker.GetComponent<SolutionComponent>(); var solution = beaker.GetComponent<SolutionContainerComponent>();
return new ChemMasterBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume, return new ChemMasterBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume,
beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume); beaker.Name, Owner.Name, solution.ReagentList.ToList(), BufferSolution.ReagentList.ToList(), _bufferModeTransfer, BufferSolution.CurrentVolume, BufferSolution.MaxVolume);
} }
@@ -191,7 +189,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
/// <summary> /// <summary>
/// If this component contains an entity with a <see cref="SolutionComponent"/>, eject it. /// If this component contains an entity with a <see cref="SolutionContainerComponent"/>, eject it.
/// Tries to eject into user's hands first, then ejects onto chem master if both hands are full. /// Tries to eject into user's hands first, then ejects onto chem master if both hands are full.
/// </summary> /// </summary>
private void TryEject(IEntity user) private void TryEject(IEntity user)
@@ -213,7 +211,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
if (!HasBeaker && _bufferModeTransfer) return; if (!HasBeaker && _bufferModeTransfer) return;
var beaker = _beakerContainer.ContainedEntity; var beaker = _beakerContainer.ContainedEntity;
var beakerSolution = beaker.GetComponent<SolutionComponent>(); var beakerSolution = beaker.GetComponent<SolutionContainerComponent>();
if (isBuffer) if (isBuffer)
{ {
foreach (var reagent in BufferSolution.Solution.Contents) foreach (var reagent in BufferSolution.Solution.Contents)
@@ -283,7 +281,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume); var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);
bottle.TryGetComponent<SolutionComponent>(out var bottleSolution); bottle.TryGetComponent<SolutionContainerComponent>(out var bottleSolution);
bottleSolution?.Solution.AddSolution(bufferSolution); bottleSolution?.Solution.AddSolution(bufferSolution);
//Try to give them the bottle //Try to give them the bottle
@@ -317,7 +315,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume); var bufferSolution = BufferSolution.Solution.SplitSolution(actualVolume);
pill.TryGetComponent<SolutionComponent>(out var pillSolution); pill.TryGetComponent<SolutionContainerComponent>(out var pillSolution);
pillSolution?.Solution.AddSolution(bufferSolution); pillSolution?.Solution.AddSolution(bufferSolution);
//Try to give them the bottle //Try to give them the bottle
@@ -368,7 +366,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// <summary> /// <summary>
/// Called when you click the owner entity with something in your active hand. If the entity in your hand /// Called when you click the owner entity with something in your active hand. If the entity in your hand
/// contains a <see cref="SolutionComponent"/>, if you have hands, and if the chem master doesn't already /// contains a <see cref="SolutionContainerComponent"/>, if you have hands, and if the chem master doesn't already
/// hold a container, it will be added to the chem master. /// hold a container, it will be added to the chem master.
/// </summary> /// </summary>
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param> /// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
@@ -377,27 +375,27 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
if (!args.User.TryGetComponent(out IHandsComponent? hands)) if (!args.User.TryGetComponent(out IHandsComponent? hands))
{ {
Owner.PopupMessage(args.User, Loc.GetString("You have no hands.")); Owner.PopupMessage(args.User, Loc.GetString("You have no hands!"));
return true; return true;
} }
if (hands.GetActiveHand == null) if (hands.GetActiveHand == null)
{ {
Owner.PopupMessage(args.User, Loc.GetString("You have nothing on your hand.")); Owner.PopupMessage(args.User, Loc.GetString("You have nothing in your hand!"));
return false; return false;
} }
var activeHandEntity = hands.GetActiveHand.Owner; var activeHandEntity = hands.GetActiveHand.Owner;
if (activeHandEntity.TryGetComponent<SolutionComponent>(out var solution)) if (activeHandEntity.TryGetComponent<SolutionContainerComponent>(out var solution))
{ {
if (HasBeaker) if (HasBeaker)
{ {
Owner.PopupMessage(args.User, Loc.GetString("This ChemMaster already has a container in it.")); Owner.PopupMessage(args.User, Loc.GetString("This ChemMaster already has a container in it."));
} }
else if ((solution.Capabilities & SolutionCaps.FitsInDispenser) == 0) //Close enough to a chem master... else if (!solution.CanUseWithChemDispenser)
{ {
//If it can't fit in the chem master, don't put it in. For example, buckets and mop buckets can't fit. //If it can't fit in the chem master, don't put it in. For example, buckets and mop buckets can't fit.
Owner.PopupMessage(args.User, Loc.GetString("That can't fit in the ChemMaster.")); Owner.PopupMessage(args.User, Loc.GetString("The {0:theName} is too large for the ChemMaster!", activeHandEntity));
} }
else else
{ {
@@ -407,7 +405,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
else else
{ {
Owner.PopupMessage(args.User, Loc.GetString("You can't put this in the ChemMaster.")); Owner.PopupMessage(args.User, Loc.GetString("You can't put {0:theName} in the ChemMaster!", activeHandEntity));
} }
return true; return true;

View File

@@ -61,12 +61,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
base.Startup(); base.Startup();
Owner.EnsureComponent<SolutionComponent>(); var solution = Owner.EnsureComponent<SolutionContainerComponent>();
solution.Capabilities = SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom;
if (Owner.TryGetComponent(out SolutionComponent? solution))
{
solution.Capabilities |= SolutionCaps.Injector;
}
// Set _toggleState based on prototype // Set _toggleState based on prototype
_toggleState = _injectOnly ? InjectorToggleMode.Inject : InjectorToggleMode.Draw; _toggleState = _injectOnly ? InjectorToggleMode.Inject : InjectorToggleMode.Draw;
@@ -111,30 +107,51 @@ namespace Content.Server.GameObjects.Components.Chemistry
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return; if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
//Make sure we have the attacking entity //Make sure we have the attacking entity
if (eventArgs.Target == null || !Owner.TryGetComponent(out SolutionComponent? solution) || !solution.Injector) if (eventArgs.Target == null || !Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return; return;
} }
var targetEntity = eventArgs.Target; var targetEntity = eventArgs.Target;
//Handle injecting/drawing for solutions
if (targetEntity.TryGetComponent<SolutionComponent>(out var targetSolution) && targetSolution.Injectable) // Handle injecting/drawing for solutions
if (targetEntity.TryGetComponent<SolutionContainerComponent>(out var targetSolution))
{ {
if (_toggleState == InjectorToggleMode.Inject) if (_toggleState == InjectorToggleMode.Inject)
{ {
TryInject(targetSolution, eventArgs.User); if (solution.CanRemoveSolutions && targetSolution.CanAddSolutions)
{
TryInject(targetSolution, eventArgs.User);
}
else
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You aren't able to transfer to {0:theName}!", targetSolution.Owner));
}
} }
else if (_toggleState == InjectorToggleMode.Draw) else if (_toggleState == InjectorToggleMode.Draw)
{ {
TryDraw(targetSolution, eventArgs.User); if (targetSolution.CanRemoveSolutions && solution.CanAddSolutions)
{
TryDraw(targetSolution, eventArgs.User);
}
else
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You aren't able to draw from {0:theName}!", targetSolution.Owner));
}
} }
} }
else //Handle injecting into bloodstream else // Handle injecting into bloodstream
{ {
if (targetEntity.TryGetComponent(out BloodstreamComponent? bloodstream) && if (targetEntity.TryGetComponent(out BloodstreamComponent? bloodstream) && _toggleState == InjectorToggleMode.Inject)
_toggleState == InjectorToggleMode.Inject)
{ {
TryInjectIntoBloodstream(bloodstream, eventArgs.User); if (solution.CanRemoveSolutions)
{
TryInjectIntoBloodstream(bloodstream, eventArgs.User);
}
else
{
eventArgs.User.PopupMessage(eventArgs.User, Loc.GetString("You aren't able to inject {0:theName}!", targetEntity));
}
} }
} }
} }
@@ -152,88 +169,91 @@ namespace Content.Server.GameObjects.Components.Chemistry
private void TryInjectIntoBloodstream(BloodstreamComponent targetBloodstream, IEntity user) private void TryInjectIntoBloodstream(BloodstreamComponent targetBloodstream, IEntity user)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution) || if (!Owner.TryGetComponent(out SolutionContainerComponent? solution) || solution.CurrentVolume == 0)
solution.CurrentVolume == 0)
{ {
return; return;
} }
//Get transfer amount. May be smaller than _transferAmount if not enough room // Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetBloodstream.EmptyVolume); var realTransferAmount = ReagentUnit.Min(_transferAmount, targetBloodstream.EmptyVolume);
if (realTransferAmount <= 0) if (realTransferAmount <= 0)
{ {
Owner.PopupMessage(user, Loc.GetString("Container full.")); Owner.PopupMessage(user, Loc.GetString("You aren't able to inject {0:theName}!", targetBloodstream.Owner));
return; return;
} }
//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 (!targetBloodstream.TryTransferSolution(removedSolution))
{ {
return; return;
} }
Owner.PopupMessage(user, Loc.GetString("Injected {0}u", removedSolution.TotalVolume)); Owner.PopupMessage(user, Loc.GetString("You inject {0}u into {1:theName}!", removedSolution.TotalVolume, targetBloodstream.Owner));
Dirty(); Dirty();
} }
private void TryInject(SolutionComponent targetSolution, IEntity user) private void TryInject(SolutionContainerComponent targetSolution, IEntity user)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution) || if (!Owner.TryGetComponent(out SolutionContainerComponent? solution) || solution.CurrentVolume == 0)
solution.CurrentVolume == 0)
{ {
return; return;
} }
//Get transfer amount. May be smaller than _transferAmount if not enough room // Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.EmptyVolume); var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.EmptyVolume);
if (realTransferAmount <= 0) if (realTransferAmount <= 0)
{ {
Owner.PopupMessage(user, Loc.GetString("Container full.")); Owner.PopupMessage(user, Loc.GetString("{0:theName} is already full!", targetSolution.Owner));
return; return;
} }
//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.TryAddSolution(removedSolution))
{ {
return; return;
} }
Owner.PopupMessage(user, Loc.GetString("Injected {0}u", removedSolution.TotalVolume)); Owner.PopupMessage(user, Loc.GetString("You transfter {0}u to {1:theName}", removedSolution.TotalVolume, targetSolution.Owner));
Dirty(); Dirty();
} }
private void TryDraw(SolutionComponent targetSolution, IEntity user) private void TryDraw(SolutionContainerComponent targetSolution, IEntity user)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution) || if (!Owner.TryGetComponent(out SolutionContainerComponent? solution) || solution.EmptyVolume == 0)
solution.EmptyVolume == 0)
{ {
return; return;
} }
//Get transfer amount. May be smaller than _transferAmount if not enough room // Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.CurrentVolume); var realTransferAmount = ReagentUnit.Min(_transferAmount, targetSolution.CurrentVolume);
if (realTransferAmount <= 0) if (realTransferAmount <= 0)
{ {
Owner.PopupMessage(user, Loc.GetString("Container empty")); Owner.PopupMessage(user, Loc.GetString("{0:theName} is empty!", targetSolution.Owner));
return; return;
} }
//Move units from attackSolution to targetSolution // Move units from attackSolution to targetSolution
var removedSolution = targetSolution.SplitSolution(realTransferAmount); var removedSolution = targetSolution.SplitSolution(realTransferAmount);
if (!solution.TryAddSolution(removedSolution)) if (!solution.TryAddSolution(removedSolution))
{ {
return; return;
} }
Owner.PopupMessage(user, Loc.GetString("Drew {0}u", removedSolution.TotalVolume)); Owner.PopupMessage(user, Loc.GetString("Drew {0}u from {1:theName}", removedSolution.TotalVolume, targetSolution.Owner));
Dirty(); Dirty();
} }
public override ComponentState GetComponentState() public override ComponentState GetComponentState()
{ {
Owner.TryGetComponent(out SolutionComponent? solution); Owner.TryGetComponent(out SolutionContainerComponent? solution);
var currentVolume = solution?.CurrentVolume ?? ReagentUnit.Zero; var currentVolume = solution?.CurrentVolume ?? ReagentUnit.Zero;
var maxVolume = solution?.MaxVolume ?? ReagentUnit.Zero; var maxVolume = solution?.MaxVolume ?? ReagentUnit.Zero;

View File

@@ -29,7 +29,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
[ViewVariables] [ViewVariables]
private string _trashPrototype; private string _trashPrototype;
[ViewVariables] [ViewVariables]
private SolutionComponent _contents; private SolutionContainerComponent _contents;
[ViewVariables] [ViewVariables]
private ReagentUnit _transferAmount; private ReagentUnit _transferAmount;
@@ -45,7 +45,8 @@ namespace Content.Server.GameObjects.Components.Chemistry
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
_contents = Owner.GetComponent<SolutionComponent>();
_contents = Owner.GetComponent<SolutionContainerComponent>();
} }
bool IUse.UseEntity(UseEntityEventArgs eventArgs) bool IUse.UseEntity(UseEntityEventArgs eventArgs)

View File

@@ -48,22 +48,22 @@ namespace Content.Server.GameObjects.Components.Chemistry
async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs) async Task<bool> IInteractUsing.InteractUsing(InteractUsingEventArgs eventArgs)
{ {
//Get target solution component //Get target solution component
if (!Owner.TryGetComponent<SolutionComponent>(out var targetSolution)) if (!Owner.TryGetComponent<SolutionContainerComponent>(out var targetSolution))
return false; return false;
//Get attack solution component //Get attack solution component
var attackEntity = eventArgs.Using; var attackEntity = eventArgs.Using;
if (!attackEntity.TryGetComponent<SolutionComponent>(out var attackSolution)) if (!attackEntity.TryGetComponent<SolutionContainerComponent>(out var attackSolution))
return false; return false;
// Calculate possibe solution transfer // Calculate possibe solution transfer
if (targetSolution.CanPourIn && attackSolution.CanPourOut) if (targetSolution.CanAddSolutions && attackSolution.CanRemoveSolutions)
{ {
// default logic (beakers and glasses) // default logic (beakers and glasses)
// transfer solution from object in hand to attacked // transfer solution from object in hand to attacked
return TryTransfer(eventArgs, attackSolution, targetSolution); return TryTransfer(eventArgs, attackSolution, targetSolution);
} }
else if (targetSolution.CanPourOut && attackSolution.CanPourIn) else if (targetSolution.CanRemoveSolutions && attackSolution.CanAddSolutions)
{ {
// storage tanks and sinks logic // storage tanks and sinks logic
// drain solution from attacked object to object in hand // drain solution from attacked object to object in hand
@@ -74,26 +74,38 @@ namespace Content.Server.GameObjects.Components.Chemistry
return false; return false;
} }
bool TryTransfer(InteractUsingEventArgs eventArgs, SolutionComponent fromSolution, SolutionComponent toSolution) bool TryTransfer(InteractUsingEventArgs eventArgs, SolutionContainerComponent fromSolution, SolutionContainerComponent toSolution)
{ {
var fromEntity = fromSolution.Owner; var fromEntity = fromSolution.Owner;
if (!fromEntity.TryGetComponent<PourableComponent>(out var fromPourable))
return false;
//Get transfer amount. May be smaller than _transferAmount if not enough room if (!fromEntity.TryGetComponent<PourableComponent>(out var fromPourable))
var realTransferAmount = ReagentUnit.Min(fromPourable.TransferAmount, toSolution.EmptyVolume);
if (realTransferAmount <= 0) //Special message if container is full
{ {
Owner.PopupMessage(eventArgs.User, Loc.GetString("Container is full"));
return false; return false;
} }
//Get transfer amount. May be smaller than _transferAmount if not enough room
var realTransferAmount = ReagentUnit.Min(fromPourable.TransferAmount, toSolution.EmptyVolume);
if (realTransferAmount <= 0) // Special message if container is full
{
Owner.PopupMessage(eventArgs.User, Loc.GetString("{0:theName} is full!", toSolution.Owner));
return false;
}
//Move units from attackSolution to targetSolution //Move units from attackSolution to targetSolution
var removedSolution = fromSolution.SplitSolution(realTransferAmount); var removedSolution = fromSolution.SplitSolution(realTransferAmount);
if (!toSolution.TryAddSolution(removedSolution))
return false;
Owner.PopupMessage(eventArgs.User, Loc.GetString("Transferred {0}u", removedSolution.TotalVolume)); if (removedSolution.TotalVolume <= ReagentUnit.Zero)
{
return false;
}
if (!toSolution.TryAddSolution(removedSolution))
{
return false;
}
Owner.PopupMessage(eventArgs.User, Loc.GetString("You transfer {0}u to {1:theName}.", removedSolution.TotalVolume, toSolution.Owner));
return true; return true;
} }

View File

@@ -47,9 +47,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
[ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null; [ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null;
[ViewVariables] private ReagentUnit _dispenseAmount = ReagentUnit.New(10); [ViewVariables] private ReagentUnit _dispenseAmount = ReagentUnit.New(10);
[ViewVariables] private SolutionContainerComponent? Solution => _beakerContainer.ContainedEntity.GetComponent<SolutionContainerComponent>();
[ViewVariables]
private SolutionComponent? Solution => _beakerContainer.ContainedEntity?.GetComponent<SolutionComponent>();
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
@@ -210,7 +208,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
"", Inventory, Owner.Name, null, _dispenseAmount); "", Inventory, Owner.Name, null, _dispenseAmount);
} }
var solution = beaker.GetComponent<SolutionComponent>(); var solution = beaker.GetComponent<SolutionContainerComponent>();
return new ReagentDispenserBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume, return new ReagentDispenserBoundUserInterfaceState(Powered, true, solution.CurrentVolume, solution.MaxVolume,
beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount); beaker.Name, Inventory, Owner.Name, solution.ReagentList.ToList(), _dispenseAmount);
} }
@@ -222,7 +220,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
/// <summary> /// <summary>
/// If this component contains an entity with a <see cref="SolutionComponent"/>, eject it. /// If this component contains an entity with a <see cref="SolutionContainerComponent"/>, eject it.
/// Tries to eject into user's hands first, then ejects onto dispenser if both hands are full. /// Tries to eject into user's hands first, then ejects onto dispenser if both hands are full.
/// </summary> /// </summary>
private void TryEject(IEntity user) private void TryEject(IEntity user)
@@ -241,26 +239,26 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
/// <summary> /// <summary>
/// If this component contains an entity with a <see cref="SolutionComponent"/>, remove all of it's reagents / solutions. /// If this component contains an entity with a <see cref="SolutionContainerComponent"/>, remove all of it's reagents / solutions.
/// </summary> /// </summary>
private void TryClear() private void TryClear()
{ {
if (!HasBeaker) return; if (!HasBeaker) return;
var solution = _beakerContainer.ContainedEntity.GetComponent<SolutionComponent>(); var solution = _beakerContainer.ContainedEntity.GetComponent<SolutionContainerComponent>();
solution.RemoveAllSolution(); solution.RemoveAllSolution();
UpdateUserInterface(); UpdateUserInterface();
} }
/// <summary> /// <summary>
/// If this component contains an entity with a <see cref="SolutionComponent"/>, attempt to dispense the specified reagent to it. /// If this component contains an entity with a <see cref="SolutionContainerComponent"/>, attempt to dispense the specified reagent to it.
/// </summary> /// </summary>
/// <param name="dispenseIndex">The index of the reagent in <c>Inventory</c>.</param> /// <param name="dispenseIndex">The index of the reagent in <c>Inventory</c>.</param>
private void TryDispense(int dispenseIndex) private void TryDispense(int dispenseIndex)
{ {
if (!HasBeaker) return; if (!HasBeaker) return;
var solution = _beakerContainer.ContainedEntity.GetComponent<SolutionComponent>(); var solution = _beakerContainer.ContainedEntity.GetComponent<SolutionContainerComponent>();
solution.TryAddReagent(Inventory[dispenseIndex].ID, _dispenseAmount, out _); solution.TryAddReagent(Inventory[dispenseIndex].ID, _dispenseAmount, out _);
UpdateUserInterface(); UpdateUserInterface();
@@ -292,7 +290,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// <summary> /// <summary>
/// Called when you click the owner entity with something in your active hand. If the entity in your hand /// Called when you click the owner entity with something in your active hand. If the entity in your hand
/// contains a <see cref="SolutionComponent"/>, if you have hands, and if the dispenser doesn't already /// contains a <see cref="SolutionContainerComponent"/>, if you have hands, and if the dispenser doesn't already
/// hold a container, it will be added to the dispenser. /// hold a container, it will be added to the dispenser.
/// </summary> /// </summary>
/// <param name="args">Data relevant to the event such as the actor which triggered it.</param> /// <param name="args">Data relevant to the event such as the actor which triggered it.</param>
@@ -312,13 +310,13 @@ namespace Content.Server.GameObjects.Components.Chemistry
} }
var activeHandEntity = hands.GetActiveHand.Owner; var activeHandEntity = hands.GetActiveHand.Owner;
if (activeHandEntity.TryGetComponent<SolutionComponent>(out var solution)) if (activeHandEntity.TryGetComponent<SolutionContainerComponent>(out var solution))
{ {
if (HasBeaker) if (HasBeaker)
{ {
Owner.PopupMessage(args.User, Loc.GetString("This dispenser already has a container in it.")); Owner.PopupMessage(args.User, Loc.GetString("This dispenser already has a container in it."));
} }
else if ((solution.Capabilities & SolutionCaps.FitsInDispenser) == 0) else if ((solution.Capabilities & SolutionContainerCaps.FitsInDispenser) == 0)
{ {
//If it can't fit in the dispenser, don't put it in. For example, buckets and mop buckets can't fit. //If it can't fit in the dispenser, don't put it in. For example, buckets and mop buckets can't fit.
Owner.PopupMessage(args.User, Loc.GetString("That can't fit in the dispenser.")); Owner.PopupMessage(args.User, Loc.GetString("That can't fit in the dispenser."));

View File

@@ -20,6 +20,7 @@ using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using Robust.Shared.Utility; using Robust.Shared.Utility;
using Robust.Shared.ViewVariables; using Robust.Shared.ViewVariables;
using System;
namespace Content.Server.GameObjects.Components.Chemistry namespace Content.Server.GameObjects.Components.Chemistry
{ {
@@ -27,41 +28,26 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// ECS component that manages a liquid solution of reagents. /// ECS component that manages a liquid solution of reagents.
/// </summary> /// </summary>
[RegisterComponent] [RegisterComponent]
public class SolutionComponent : SharedSolutionComponent, IExamine public class SolutionContainerComponent : SharedSolutionContainerComponent, IExamine
{ {
[Dependency] private readonly IPrototypeManager _prototypeManager = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!; [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
private IEnumerable<ReactionPrototype> _reactions; private IEnumerable<ReactionPrototype> _reactions;
private AudioSystem _audioSystem;
private ChemistrySystem _chemistrySystem;
private SpriteComponent _spriteComponent;
private Solution _containedSolution = new Solution();
private ReagentUnit _maxVolume;
private SolutionCaps _capabilities;
private string _fillInitState; private string _fillInitState;
private int _fillInitSteps; private int _fillInitSteps;
private string _fillPathString = "Objects/Specific/Chemistry/fillings.rsi"; private string _fillPathString = "Objects/Specific/Chemistry/fillings.rsi";
private ResourcePath _fillPath; private ResourcePath _fillPath;
private SpriteSpecifier _fillSprite; private SpriteSpecifier _fillSprite;
private AudioSystem _audioSystem;
/// <summary> private ChemistrySystem _chemistrySystem;
/// The maximum volume of the container. private SpriteComponent _spriteComponent;
/// </summary>
[ViewVariables(VVAccess.ReadWrite)]
public ReagentUnit MaxVolume
{
get => _maxVolume;
set => _maxVolume = value; // Note that the contents won't spill out if the capacity is reduced.
}
/// <summary> /// <summary>
/// The total volume of all the of the reagents in the container. /// The total volume of all the of the reagents in the container.
/// </summary> /// </summary>
[ViewVariables] [ViewVariables]
public ReagentUnit CurrentVolume => _containedSolution.TotalVolume; public ReagentUnit CurrentVolume => Solution.TotalVolume;
/// <summary> /// <summary>
/// The volume without reagents remaining in the container. /// The volume without reagents remaining in the container.
@@ -79,49 +65,35 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// The current capabilities of this container (is the top open to pour? can I inject it into another object?). /// The current capabilities of this container (is the top open to pour? can I inject it into another object?).
/// </summary> /// </summary>
[ViewVariables(VVAccess.ReadWrite)] [ViewVariables(VVAccess.ReadWrite)]
public SolutionCaps Capabilities public SolutionContainerCaps Capabilities { get; set; }
{
get => _capabilities;
set => _capabilities = value;
}
/// <summary>
/// The contained solution.
/// </summary>
[ViewVariables] [ViewVariables]
public Solution Solution public Solution Solution { get; set; }
{
get => _containedSolution;
set => _containedSolution = value;
}
public IReadOnlyList<Solution.ReagentQuantity> ReagentList => _containedSolution.Contents;
/// <summary> /// <summary>
/// Shortcut for Capabilities PourIn flag to avoid binary operators. /// The maximum volume of the container.
/// </summary> /// </summary>
public bool CanPourIn => (Capabilities & SolutionCaps.PourIn) != 0; [ViewVariables(VVAccess.ReadWrite)]
/// <summary> public ReagentUnit MaxVolume { get; set; }
/// Shortcut for Capabilities PourOut flag to avoid binary operators.
/// </summary>
public bool CanPourOut => (Capabilities & SolutionCaps.PourOut) != 0;
/// <summary>
/// Shortcut for Capabilities Injectable flag
/// </summary>
public bool Injectable => (Capabilities & SolutionCaps.Injectable) != 0;
/// <summary>
/// Shortcut for Capabilities Injector flag
/// </summary>
public bool Injector => (Capabilities & SolutionCaps.Injector) != 0;
public bool NoExamine => (Capabilities & SolutionCaps.NoExamine) != 0; public IReadOnlyList<Solution.ReagentQuantity> ReagentList => Solution.Contents;
public bool CanExamineContents => (Capabilities & SolutionContainerCaps.NoExamine) == 0;
public bool CanUseWithChemDispenser => (Capabilities & SolutionContainerCaps.FitsInDispenser) != 0;
public bool CanAddSolutions => (Capabilities & SolutionContainerCaps.AddTo) != 0;
public bool CanRemoveSolutions => (Capabilities & SolutionContainerCaps.RemoveFrom) != 0;
/// <inheritdoc /> /// <inheritdoc />
public override void ExposeData(ObjectSerializer serializer) public override void ExposeData(ObjectSerializer serializer)
{ {
base.ExposeData(serializer); base.ExposeData(serializer);
serializer.DataField(ref _maxVolume, "maxVol", ReagentUnit.New(0)); serializer.DataField(this, x => MaxVolume, "maxVol", ReagentUnit.New(0));
serializer.DataField(ref _containedSolution, "contents", _containedSolution); serializer.DataField(this, x => Solution, "contents", new Solution());
serializer.DataField(ref _capabilities, "caps", SolutionCaps.None); serializer.DataField(this, x => Capabilities, "caps", SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom);
serializer.DataField(ref _fillInitState, "fillingState", ""); serializer.DataField(ref _fillInitState, "fillingState", string.Empty);
serializer.DataField(ref _fillInitSteps, "fillingSteps", 7); serializer.DataField(ref _fillInitSteps, "fillingSteps", 7);
} }
@@ -149,15 +121,18 @@ namespace Content.Server.GameObjects.Components.Chemistry
public void RemoveAllSolution() public void RemoveAllSolution()
{ {
_containedSolution.RemoveAllSolution(); Solution.RemoveAllSolution();
OnSolutionChanged(false); OnSolutionChanged(false);
} }
public bool TryRemoveReagent(string reagentId, ReagentUnit quantity) public bool TryRemoveReagent(string reagentId, ReagentUnit quantity)
{ {
if (!ContainsReagent(reagentId, out var currentQuantity)) return false; if (!ContainsReagent(reagentId, out var currentQuantity))
{
return false;
}
_containedSolution.RemoveReagent(reagentId, quantity); Solution.RemoveReagent(reagentId, quantity);
OnSolutionChanged(false); OnSolutionChanged(false);
return true; return true;
} }
@@ -170,23 +145,25 @@ namespace Content.Server.GameObjects.Components.Chemistry
public bool TryRemoveSolution(ReagentUnit quantity) public bool TryRemoveSolution(ReagentUnit quantity)
{ {
if (CurrentVolume == 0) if (CurrentVolume == 0)
{
return false; return false;
}
_containedSolution.RemoveSolution(quantity);
Solution.RemoveSolution(quantity);
OnSolutionChanged(false); OnSolutionChanged(false);
return true; return true;
} }
public Solution SplitSolution(ReagentUnit quantity) public Solution SplitSolution(ReagentUnit quantity)
{ {
var solutionSplit = _containedSolution.SplitSolution(quantity); var solutionSplit = Solution.SplitSolution(quantity);
OnSolutionChanged(false); OnSolutionChanged(false);
return solutionSplit; return solutionSplit;
} }
protected void RecalculateColor() protected void RecalculateColor()
{ {
if (_containedSolution.TotalVolume == 0) if (Solution.TotalVolume == 0)
{ {
SubstanceColor = Color.Transparent; SubstanceColor = Color.Transparent;
return; return;
@@ -195,16 +172,23 @@ namespace Content.Server.GameObjects.Components.Chemistry
Color mixColor = default; Color mixColor = default;
var runningTotalQuantity = ReagentUnit.New(0); var runningTotalQuantity = ReagentUnit.New(0);
foreach (var reagent in _containedSolution) foreach (var reagent in Solution)
{ {
runningTotalQuantity += reagent.Quantity; runningTotalQuantity += reagent.Quantity;
if(!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto)) if (!_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
{
continue; continue;
}
if (mixColor == default) if (mixColor == default)
{
mixColor = proto.SubstanceColor; mixColor = proto.SubstanceColor;
mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, continue;
(1 / runningTotalQuantity.Float()) * reagent.Quantity.Float()); }
var interpolateValue = (1 / runningTotalQuantity.Float()) * reagent.Quantity.Float();
mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, interpolateValue);
} }
SubstanceColor = mixColor; SubstanceColor = mixColor;
@@ -214,56 +198,53 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// Transfers solution from the held container to the target container. /// Transfers solution from the held container to the target container.
/// </summary> /// </summary>
[Verb] [Verb]
private sealed class FillTargetVerb : Verb<SolutionComponent> private sealed class FillTargetVerb : Verb<SolutionContainerComponent>
{ {
protected override void GetData(IEntity user, SolutionComponent component, VerbData data) protected override void GetData(IEntity user, SolutionContainerComponent component, VerbData data)
{ {
if (!ActionBlockerSystem.CanInteract(user) || if (!ActionBlockerSystem.CanInteract(user) ||
!user.TryGetComponent<HandsComponent>(out var hands) || !user.TryGetComponent<HandsComponent>(out var hands) ||
hands.GetActiveHand == null || hands.GetActiveHand == null ||
hands.GetActiveHand.Owner == component.Owner || hands.GetActiveHand.Owner == component.Owner ||
!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution)) !hands.GetActiveHand.Owner.TryGetComponent<SolutionContainerComponent>(out var solution) ||
!solution.CanRemoveSolutions ||
!component.CanAddSolutions)
{ {
data.Visibility = VerbVisibility.Invisible; data.Visibility = VerbVisibility.Invisible;
return; return;
} }
if ((solution.Capabilities & SolutionCaps.PourOut) != 0 && var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
(component.Capabilities & SolutionCaps.PourIn) != 0) var myName = component.Owner.Prototype?.Name ?? "<Item>";
{
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
var myName = component.Owner.Prototype?.Name ?? "<Item>";
var locHeldEntityName = Loc.GetString(heldEntityName); var locHeldEntityName = Loc.GetString(heldEntityName);
var locMyName = Loc.GetString(myName); var locMyName = Loc.GetString(myName);
data.Text = Loc.GetString("Transfer liquid from [{0}] to [{1}].", locHeldEntityName, locMyName); data.Visibility = VerbVisibility.Visible;
return; data.Text = Loc.GetString("Transfer liquid from [{0}] to [{1}].", locHeldEntityName, locMyName);
}
data.Visibility = VerbVisibility.Invisible;
} }
protected override void Activate(IEntity user, SolutionComponent component) protected override void Activate(IEntity user, SolutionContainerComponent component)
{ {
if (!user.TryGetComponent<HandsComponent>(out var hands)) if (!user.TryGetComponent<HandsComponent>(out var hands) || hands.GetActiveHand == null)
{
return; return;
}
if (hands.GetActiveHand == null)
return; if (!hands.GetActiveHand.Owner.TryGetComponent<SolutionContainerComponent>(out var handSolutionComp) ||
!handSolutionComp.CanRemoveSolutions ||
if (!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp)) !component.CanAddSolutions)
return; {
if ((handSolutionComp.Capabilities & SolutionCaps.PourOut) == 0 || (component.Capabilities & SolutionCaps.PourIn) == 0)
return; return;
}
var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume, ReagentUnit.New(10)); var transferQuantity = ReagentUnit.Min(component.MaxVolume - component.CurrentVolume, handSolutionComp.CurrentVolume, ReagentUnit.New(10));
// nothing to transfer
if (transferQuantity <= 0) if (transferQuantity <= 0)
{
return; return;
}
var transferSolution = handSolutionComp.SplitSolution(transferQuantity); var transferSolution = handSolutionComp.SplitSolution(transferQuantity);
component.TryAddSolution(transferSolution); component.TryAddSolution(transferSolution);
} }
@@ -271,44 +252,37 @@ namespace Content.Server.GameObjects.Components.Chemistry
void IExamine.Examine(FormattedMessage message, bool inDetailsRange) void IExamine.Examine(FormattedMessage message, bool inDetailsRange)
{ {
if (NoExamine) if (!CanExamineContents)
{ {
return; return;
} }
message.AddText(Loc.GetString("Contains:\n"));
if (ReagentList.Count == 0) if (ReagentList.Count == 0)
{ {
message.AddText("Nothing.\n"); message.AddText(Loc.GetString("It's empty."));
} }
foreach (var reagent in ReagentList) else if (ReagentList.Count == 1)
{ {
var reagent = ReagentList[0];
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto)) if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
{ {
if (inDetailsRange) var colorStr = $" [color={proto.GetSubstanceTextColor().ToHexNoAlpha()}]";
{ message.AddText(Loc.GetString("It contains a"));
message.AddText($"{proto.Name}: {reagent.Quantity}u\n"); message.AddMarkup(colorStr + Loc.GetString(proto.PhysicalDescription) + "[/color] ");
} message.AddText(Loc.GetString("substance."));
else
{
//This is trash but it shows the general idea
var color = proto.SubstanceColor;
var colorIsh = "Red";
if (color.G > color.R)
{
colorIsh = "Green";
}
if (color.B > color.G && color.B > color.R)
{
colorIsh = "Blue";
}
message.AddText(Loc.GetString("A {0} liquid\n", colorIsh));
}
} }
else }
else
{
var reagent = ReagentList.Max();
if (_prototypeManager.TryIndex(reagent.ReagentId, out ReagentPrototype proto))
{ {
message.AddText(Loc.GetString("Unknown reagent: {0}u\n", reagent.Quantity)); var colorStr = $" [color={SubstanceColor.ToHexNoAlpha()}]";
message.AddText(Loc.GetString("It contains a"));
message.AddMarkup(colorStr + Loc.GetString(proto.PhysicalDescription) + "[/color] ");
message.AddText(Loc.GetString("mixture of substances."));
} }
} }
} }
@@ -317,55 +291,53 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// Transfers solution from a target container to the held container. /// Transfers solution from a target container to the held container.
/// </summary> /// </summary>
[Verb] [Verb]
private sealed class EmptyTargetVerb : Verb<SolutionComponent> private sealed class EmptyTargetVerb : Verb<SolutionContainerComponent>
{ {
protected override void GetData(IEntity user, SolutionComponent component, VerbData data) protected override void GetData(IEntity user, SolutionContainerComponent component, VerbData data)
{ {
if (!ActionBlockerSystem.CanInteract(user) || if (!ActionBlockerSystem.CanInteract(user) ||
!user.TryGetComponent<HandsComponent>(out var hands) || !user.TryGetComponent<HandsComponent>(out var hands) ||
hands.GetActiveHand == null || hands.GetActiveHand == null ||
hands.GetActiveHand.Owner == component.Owner || hands.GetActiveHand.Owner == component.Owner ||
!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var solution)) !hands.GetActiveHand.Owner.TryGetComponent<SolutionContainerComponent>(out var solution) ||
!solution.CanAddSolutions ||
!component.CanRemoveSolutions)
{ {
data.Visibility = VerbVisibility.Invisible; data.Visibility = VerbVisibility.Invisible;
return; return;
} }
if ((solution.Capabilities & SolutionCaps.PourIn) != 0 && var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
(component.Capabilities & SolutionCaps.PourOut) != 0) var myName = component.Owner.Prototype?.Name ?? "<Item>";
var locHeldEntityName = Loc.GetString(heldEntityName);
var locMyName = Loc.GetString(myName);
data.Visibility = VerbVisibility.Visible;
data.Text = Loc.GetString("Transfer liquid from [{0}] to [{1}].", locMyName, locHeldEntityName);
return;
}
protected override void Activate(IEntity user, SolutionContainerComponent component)
{
if (!user.TryGetComponent<HandsComponent>(out var hands) || hands.GetActiveHand == null)
{ {
var heldEntityName = hands.GetActiveHand.Owner?.Prototype?.Name ?? "<Item>";
var myName = component.Owner.Prototype?.Name ?? "<Item>";
var locHeldEntityName = Loc.GetString(heldEntityName);
var locMyName = Loc.GetString(myName);
data.Text = Loc.GetString("Transfer liquid from [{0}] to [{1}].", locMyName, locHeldEntityName);
return; return;
} }
data.Visibility = VerbVisibility.Invisible; if(!hands.GetActiveHand.Owner.TryGetComponent<SolutionContainerComponent>(out var handSolutionComp) ||
} !handSolutionComp.CanAddSolutions ||
!component.CanRemoveSolutions)
protected override void Activate(IEntity user, SolutionComponent component) {
{
if (!user.TryGetComponent<HandsComponent>(out var hands))
return;
if (hands.GetActiveHand == null)
return;
if(!hands.GetActiveHand.Owner.TryGetComponent<SolutionComponent>(out var handSolutionComp))
return;
if ((handSolutionComp.Capabilities & SolutionCaps.PourIn) == 0 || (component.Capabilities & SolutionCaps.PourOut) == 0)
return; return;
}
var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume, ReagentUnit.New(10)); var transferQuantity = ReagentUnit.Min(handSolutionComp.MaxVolume - handSolutionComp.CurrentVolume, component.CurrentVolume, ReagentUnit.New(10));
// pulling from an empty container, pointless to continue
if (transferQuantity <= 0) if (transferQuantity <= 0)
{
return; return;
}
var transferSolution = component.SplitSolution(transferQuantity); var transferSolution = component.SplitSolution(transferQuantity);
handSolutionComp.TryAddSolution(transferSolution); handSolutionComp.TryAddSolution(transferSolution);
@@ -401,7 +373,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
public bool TryAddReagent(string reagentId, ReagentUnit quantity, out ReagentUnit acceptedQuantity, bool skipReactionCheck = false, bool skipColor = false) public bool TryAddReagent(string reagentId, ReagentUnit quantity, out ReagentUnit acceptedQuantity, bool skipReactionCheck = false, bool skipColor = false)
{ {
var toAcceptQuantity = MaxVolume - _containedSolution.TotalVolume; var toAcceptQuantity = MaxVolume - Solution.TotalVolume;
if (quantity > toAcceptQuantity) if (quantity > toAcceptQuantity)
{ {
acceptedQuantity = toAcceptQuantity; acceptedQuantity = toAcceptQuantity;
@@ -412,7 +384,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
acceptedQuantity = quantity; acceptedQuantity = quantity;
} }
_containedSolution.AddReagent(reagentId, acceptedQuantity); Solution.AddReagent(reagentId, acceptedQuantity);
if (!skipColor) { if (!skipColor) {
RecalculateColor(); RecalculateColor();
} }
@@ -424,10 +396,10 @@ namespace Content.Server.GameObjects.Components.Chemistry
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 - _containedSolution.TotalVolume)) if (solution.TotalVolume > (MaxVolume - Solution.TotalVolume))
return false; return false;
_containedSolution.AddSolution(solution); Solution.AddSolution(solution);
if (!skipColor) { if (!skipColor) {
RecalculateColor(); RecalculateColor();
} }
@@ -487,18 +459,20 @@ namespace Content.Server.GameObjects.Components.Chemistry
TryRemoveReagent(reactant.Key, amountToRemove); TryRemoveReagent(reactant.Key, amountToRemove);
} }
} }
//Add products
// Add products
foreach (var product in reaction.Products) foreach (var product in reaction.Products)
{ {
TryAddReagent(product.Key, product.Value * unitReactions, out var acceptedQuantity, true); TryAddReagent(product.Key, product.Value * unitReactions, out var acceptedQuantity, true);
} }
//Trigger reaction effects
// Trigger reaction effects
foreach (var effect in reaction.Effects) foreach (var effect in reaction.Effects)
{ {
effect.React(Owner, unitReactions.Double()); effect.React(Owner, unitReactions.Double());
} }
//Play reaction sound client-side // Play reaction sound client-side
_audioSystem.PlayAtCoords("/Audio/Effects/Chemistry/bubbles.ogg", Owner.Transform.Coordinates); _audioSystem.PlayAtCoords("/Audio/Effects/Chemistry/bubbles.ogg", Owner.Transform.Coordinates);
} }
@@ -510,7 +484,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
/// <returns>Return true if the solution contains the reagent.</returns> /// <returns>Return true if the solution contains the reagent.</returns>
public bool ContainsReagent(string reagentId, out ReagentUnit quantity) public bool ContainsReagent(string reagentId, out ReagentUnit quantity)
{ {
foreach (var reagent in _containedSolution.Contents) foreach (var reagent in Solution.Contents)
{ {
if (reagent.ReagentId == reagentId) if (reagent.ReagentId == reagentId)
{ {
@@ -518,43 +492,50 @@ namespace Content.Server.GameObjects.Components.Chemistry
return true; return true;
} }
} }
quantity = ReagentUnit.New(0); quantity = ReagentUnit.New(0);
return false; return false;
} }
public string GetMajorReagentId() public string GetMajorReagentId()
{ {
if (_containedSolution.Contents.Count == 0) if (Solution.Contents.Count == 0)
{ {
return ""; return "";
} }
var majorReagent = _containedSolution.Contents.OrderByDescending(reagent => reagent.Quantity).First();;
var majorReagent = Solution.Contents.OrderByDescending(reagent => reagent.Quantity).First();;
return majorReagent.ReagentId; return majorReagent.ReagentId;
} }
protected void UpdateFillIcon() protected void UpdateFillIcon()
{ {
if (string.IsNullOrEmpty(_fillInitState)) return; if (string.IsNullOrEmpty(_fillInitState))
{
return;
}
var percentage = (CurrentVolume / MaxVolume).Double(); var percentage = (CurrentVolume / MaxVolume).Double();
var level = ContentHelpers.RoundToLevels(percentage * 100, 100, _fillInitSteps); var level = ContentHelpers.RoundToLevels(percentage * 100, 100, _fillInitSteps);
//Transformed glass uses special fancy sprites so we don't bother //Transformed glass uses special fancy sprites so we don't bother
if (level == 0 || Owner.TryGetComponent<TransformableContainerComponent>(out var transformableContainerComponent) if (level == 0 || (Owner.TryGetComponent<TransformableContainerComponent>(out var transformComp) && transformComp.Transformed))
&& transformableContainerComponent.Transformed)
{ {
_spriteComponent.LayerSetColor(1, Color.Transparent); _spriteComponent.LayerSetColor(1, Color.Transparent);
return; return;
} }
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState+level);
_fillSprite = new SpriteSpecifier.Rsi(_fillPath, _fillInitState + level);
_spriteComponent.LayerSetSprite(1, _fillSprite); _spriteComponent.LayerSetSprite(1, _fillSprite);
_spriteComponent.LayerSetColor(1,SubstanceColor); _spriteComponent.LayerSetColor(1, SubstanceColor);
} }
protected virtual void OnSolutionChanged(bool skipColor) protected virtual void OnSolutionChanged(bool skipColor)
{ {
if (!skipColor) if (!skipColor)
{
RecalculateColor(); RecalculateColor();
}
UpdateFillIcon(); UpdateFillIcon();
_chemistrySystem.HandleSolutionChange(Owner); _chemistrySystem.HandleSolutionChange(Owner);

View File

@@ -42,13 +42,13 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
base.Startup(); base.Startup();
if (!Owner.EnsureComponent(out SolutionComponent solution)) if (!Owner.EnsureComponent(out SolutionContainerComponent solution))
{ {
Logger.Warning( Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}"); $"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
} }
solution.Capabilities |= SolutionCaps.FitsInDispenser; solution.Capabilities |= SolutionContainerCaps.FitsInDispenser;
} }
public void CancelTransformation() public void CancelTransformation()
@@ -68,7 +68,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
void ISolutionChange.SolutionChanged(SolutionChangeEventArgs eventArgs) void ISolutionChange.SolutionChanged(SolutionChangeEventArgs eventArgs)
{ {
var solution = eventArgs.Owner.GetComponent<SolutionComponent>(); var solution = eventArgs.Owner.GetComponent<SolutionContainerComponent>();
//Transform container into initial state when emptied //Transform container into initial state when emptied
if (_currentReagent != null && solution.ReagentList.Count == 0) if (_currentReagent != null && solution.ReagentList.Count == 0)
{ {

View File

@@ -31,10 +31,10 @@ namespace Content.Server.GameObjects.Components.Chemistry
{ {
base.Initialize(); base.Initialize();
if (!Owner.EnsureComponent(out SolutionComponent _)) if (!Owner.EnsureComponent(out SolutionContainerComponent _))
{ {
Logger.Warning( Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}"); $"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
} }
} }
@@ -59,7 +59,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
public void Update() public void Update()
{ {
if (!Owner.TryGetComponent(out SolutionComponent contents)) if (!Owner.TryGetComponent(out SolutionContainerComponent contents))
return; return;
if (!_running) if (!_running)
@@ -94,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Chemistry
return false; return false;
} }
if (!Owner.TryGetComponent(out SolutionComponent contents)) if (!Owner.TryGetComponent(out SolutionContainerComponent contents))
{ {
return false; return false;
} }

View File

@@ -24,17 +24,17 @@ namespace Content.Server.GameObjects.Components.Fluids
public ReagentUnit MaxVolume public ReagentUnit MaxVolume
{ {
get => Owner.TryGetComponent(out SolutionComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero; get => Owner.TryGetComponent(out SolutionContainerComponent? solution) ? solution.MaxVolume : ReagentUnit.Zero;
set set
{ {
if (Owner.TryGetComponent(out SolutionComponent? solution)) if (Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
solution.MaxVolume = value; solution.MaxVolume = value;
} }
} }
} }
public ReagentUnit CurrentVolume => Owner.TryGetComponent(out SolutionComponent? solution) public ReagentUnit CurrentVolume => Owner.TryGetComponent(out SolutionContainerComponent? solution)
? solution.CurrentVolume ? solution.CurrentVolume
: ReagentUnit.Zero; : ReagentUnit.Zero;
@@ -50,12 +50,12 @@ namespace Content.Server.GameObjects.Components.Fluids
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
Owner.EnsureComponent<SolutionComponent>(); Owner.EnsureComponent<SolutionContainerComponent>();
} }
private bool TryGiveToMop(MopComponent mopComponent) private bool TryGiveToMop(MopComponent mopComponent)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? contents)) if (!Owner.TryGetComponent(out SolutionContainerComponent? contents))
{ {
return false; return false;
} }
@@ -88,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Fluids
public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs) public async Task<bool> InteractUsing(InteractUsingEventArgs eventArgs)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? contents)) if (!Owner.TryGetComponent(out SolutionContainerComponent? contents))
{ {
return false; return false;
} }

View File

@@ -1,48 +0,0 @@
using Content.Server.GameObjects.Components.Chemistry;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Localization;
namespace Content.Server.GameObjects.Components.Fluids
{
[RegisterComponent]
public class CanSpillComponent : Component
{
public override string Name => "CanSpill";
// TODO: If the Owner doesn't have a SolutionComponent straight up just have this remove itself?
/// <summary>
/// Transfers solution from the held container to the target container.
/// </summary>
[Verb]
private sealed class FillTargetVerb : Verb<CanSpillComponent>
{
protected override void GetData(IEntity user, CanSpillComponent component, VerbData data)
{
if (!ActionBlockerSystem.CanInteract(user) ||
!component.Owner.TryGetComponent(out SolutionComponent solutionComponent))
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = Loc.GetString("Spill liquid");
data.Visibility = solutionComponent.CurrentVolume > ReagentUnit.Zero
? VerbVisibility.Visible
: VerbVisibility.Disabled;
}
protected override void Activate(IEntity user, CanSpillComponent component)
{
var solutionComponent = component.Owner.GetComponent<SolutionComponent>();
// Need this as when we split the component's owner may be deleted
var entityLocation = component.Owner.Transform.Coordinates;
var solution = solutionComponent.SplitSolution(solutionComponent.CurrentVolume);
solution.SpillAt(entityLocation, "PuddleSmear");
}
}
}
}

View File

@@ -22,14 +22,14 @@ namespace Content.Server.GameObjects.Components.Fluids
{ {
public override string Name => "Mop"; public override string Name => "Mop";
public SolutionComponent? Contents => Owner.GetComponentOrNull<SolutionComponent>(); public SolutionContainerComponent? Contents => Owner.GetComponentOrNull<SolutionContainerComponent>();
public ReagentUnit MaxVolume public ReagentUnit MaxVolume
{ {
get => Owner.GetComponentOrNull<SolutionComponent>()?.MaxVolume ?? ReagentUnit.Zero; get => Owner.GetComponentOrNull<SolutionContainerComponent>()?.MaxVolume ?? ReagentUnit.Zero;
set set
{ {
if (Owner.TryGetComponent(out SolutionComponent? solution)) if (Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
solution.MaxVolume = value; solution.MaxVolume = value;
} }
@@ -37,7 +37,7 @@ namespace Content.Server.GameObjects.Components.Fluids
} }
public ReagentUnit CurrentVolume => public ReagentUnit CurrentVolume =>
Owner.GetComponentOrNull<SolutionComponent>()?.CurrentVolume ?? ReagentUnit.Zero; Owner.GetComponentOrNull<SolutionContainerComponent>()?.CurrentVolume ?? ReagentUnit.Zero;
// Currently there's a separate amount for pickup and dropoff so // Currently there's a separate amount for pickup and dropoff so
// Picking up a puddle requires multiple clicks // Picking up a puddle requires multiple clicks
@@ -60,15 +60,15 @@ namespace Content.Server.GameObjects.Components.Fluids
{ {
base.Initialize(); base.Initialize();
if (!Owner.EnsureComponent(out SolutionComponent _)) if (!Owner.EnsureComponent(out SolutionContainerComponent _))
{ {
Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}"); Logger.Warning($"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
} }
} }
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? contents)) return; if (!Owner.TryGetComponent(out SolutionContainerComponent? contents)) return;
if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return; if (!eventArgs.InRangeUnobstructed(ignoreInsideBlocker: true, popup: true)) return;
if (CurrentVolume <= 0) if (CurrentVolume <= 0)
@@ -76,7 +76,6 @@ namespace Content.Server.GameObjects.Components.Fluids
return; return;
} }
//Solution solution;
if (eventArgs.Target == null) if (eventArgs.Target == null)
{ {
// Drop the liquid on the mop on to the ground // Drop the liquid on the mop on to the ground
@@ -98,7 +97,7 @@ namespace Content.Server.GameObjects.Components.Fluids
if (transferAmount == 0) if (transferAmount == 0)
{ {
if(puddleComponent.EmptyHolder) //The puddle doesn't actually *have* reagents, for example vomit because there's no "vomit" reagent. if (puddleComponent.EmptyHolder) //The puddle doesn't actually *have* reagents, for example vomit because there's no "vomit" reagent.
{ {
puddleComponent.Owner.Delete(); puddleComponent.Owner.Delete();
transferAmount = ReagentUnit.Min(ReagentUnit.New(5), CurrentVolume); transferAmount = ReagentUnit.Min(ReagentUnit.New(5), CurrentVolume);

View File

@@ -94,7 +94,7 @@ namespace Content.Server.GameObjects.Components.Fluids
private ReagentUnit _overflowVolume; private ReagentUnit _overflowVolume;
private ReagentUnit OverflowLeft => CurrentVolume - OverflowVolume; private ReagentUnit OverflowLeft => CurrentVolume - OverflowVolume;
private SolutionComponent _contents; private SolutionContainerComponent _contents;
public bool EmptyHolder => _contents.ReagentList.Count == 0; public bool EmptyHolder => _contents.ReagentList.Count == 0;
private int _spriteVariants; private int _spriteVariants;
// Whether the underlying solution color should be used // Whether the underlying solution color should be used
@@ -118,13 +118,13 @@ namespace Content.Server.GameObjects.Components.Fluids
{ {
base.Initialize(); base.Initialize();
if (Owner.TryGetComponent(out SolutionComponent solutionComponent)) if (Owner.TryGetComponent(out SolutionContainerComponent solutionComponent))
{ {
_contents = solutionComponent; _contents = solutionComponent;
} }
else else
{ {
_contents = Owner.AddComponent<SolutionComponent>(); _contents = Owner.AddComponent<SolutionContainerComponent>();
} }
_snapGrid = Owner.EnsureComponent<SnapGridComponent>(); _snapGrid = Owner.EnsureComponent<SnapGridComponent>();

View File

@@ -0,0 +1,59 @@
using Content.Server.GameObjects.Components.Chemistry;
using Content.Shared.Chemistry;
using Content.Shared.GameObjects.EntitySystems;
using Content.Shared.GameObjects.Verbs;
using Content.Shared.Interfaces;
using Robust.Shared.GameObjects;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.Localization;
namespace Content.Server.GameObjects.Components.Fluids
{
[RegisterComponent]
public class SpillableComponent : Component
{
public override string Name => "Spillable";
/// <summary>
/// Transfers solution from the held container to the floor.
/// </summary>
[Verb]
private sealed class SpillTargetVerb : Verb<SpillableComponent>
{
protected override void GetData(IEntity user, SpillableComponent component, VerbData data)
{
if (!ActionBlockerSystem.CanInteract(user) ||
!component.Owner.TryGetComponent(out SolutionContainerComponent solutionComponent) ||
!solutionComponent.CanRemoveSolutions)
{
data.Visibility = VerbVisibility.Invisible;
return;
}
data.Text = Loc.GetString("Spill liquid");
data.Visibility = solutionComponent.CurrentVolume > ReagentUnit.Zero ? VerbVisibility.Visible : VerbVisibility.Disabled;
}
protected override void Activate(IEntity user, SpillableComponent component)
{
if (component.Owner.TryGetComponent<SolutionContainerComponent>(out var solutionComponent))
{
if (!solutionComponent.CanRemoveSolutions)
{
user.PopupMessage(user, Loc.GetString("You can't pour anything from {0:theName}!", component.Owner));
}
if (solutionComponent.CurrentVolume.Float() <= 0)
{
user.PopupMessage(user, Loc.GetString("{0:theName} is empty!", component.Owner));
}
// Need this as when we split the component's owner may be deleted
var entityLocation = component.Owner.Transform.Coordinates;
var solution = solutionComponent.SplitSolution(solutionComponent.CurrentVolume);
solution.SpillAt(entityLocation, "PuddleSmear");
}
}
}
}
}

View File

@@ -45,16 +45,16 @@ namespace Content.Server.GameObjects.Components.Fluids
set => _sprayVelocity = value; set => _sprayVelocity = value;
} }
public ReagentUnit CurrentVolume => Owner.GetComponentOrNull<SolutionComponent>()?.CurrentVolume ?? ReagentUnit.Zero; public ReagentUnit CurrentVolume => Owner.GetComponentOrNull<SolutionContainerComponent>()?.CurrentVolume ?? ReagentUnit.Zero;
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
if (!Owner.EnsureComponent(out SolutionComponent _)) if (!Owner.EnsureComponent(out SolutionContainerComponent _))
{ {
Logger.Warning( Logger.Warning(
$"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionComponent)}"); $"Entity {Owner.Name} at {Owner.Transform.MapPosition} didn't have a {nameof(SolutionContainerComponent)}");
} }
} }
@@ -78,7 +78,7 @@ namespace Content.Server.GameObjects.Components.Fluids
if (eventArgs.ClickLocation.GetGridId(_serverEntityManager) != playerPos.GetGridId(_serverEntityManager)) if (eventArgs.ClickLocation.GetGridId(_serverEntityManager) != playerPos.GetGridId(_serverEntityManager))
return; return;
if (!Owner.TryGetComponent(out SolutionComponent contents)) if (!Owner.TryGetComponent(out SolutionContainerComponent contents))
return; return;
var direction = (eventArgs.ClickLocation.Position - playerPos.Position).Normalized; var direction = (eventArgs.ClickLocation.Position - playerPos.Position).Normalized;

View File

@@ -48,7 +48,7 @@ namespace Content.Server.GameObjects.Components.Interactable
private bool _welderLit; private bool _welderLit;
private WelderSystem _welderSystem = default!; private WelderSystem _welderSystem = default!;
private SpriteComponent? _spriteComponent; private SpriteComponent? _spriteComponent;
private SolutionComponent? _solutionComponent; private SolutionContainerComponent? _solutionComponent;
private PointLightComponent? _pointLightComponent; private PointLightComponent? _pointLightComponent;
public string? WeldSoundCollection { get; set; } public string? WeldSoundCollection { get; set; }

View File

@@ -63,7 +63,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
private uint _currentCookTimerTime = 1; private uint _currentCookTimerTime = 1;
private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered;
private bool _hasContents => Owner.TryGetComponent(out SolutionComponent? solution) && (solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0); private bool _hasContents => Owner.TryGetComponent(out SolutionContainerComponent? solution) && (solution.ReagentList.Count > 0 || _storage.ContainedEntities.Count > 0);
private bool _uiDirty = true; private bool _uiDirty = true;
private bool _lostPower = false; private bool _lostPower = false;
private int _currentCookTimeButtonIndex = 0; private int _currentCookTimeButtonIndex = 0;
@@ -88,7 +88,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
{ {
base.Initialize(); base.Initialize();
Owner.EnsureComponent<SolutionComponent>(); Owner.EnsureComponent<SolutionContainerComponent>();
_storage = ContainerManagerComponent.Ensure<Container>("microwave_entity_container", Owner, out var existed); _storage = ContainerManagerComponent.Ensure<Container>("microwave_entity_container", Owner, out var existed);
_audioSystem = EntitySystem.Get<AudioSystem>(); _audioSystem = EntitySystem.Get<AudioSystem>();
@@ -165,7 +165,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
_uiDirty = true; _uiDirty = true;
} }
if (_uiDirty && Owner.TryGetComponent(out SolutionComponent? solution)) if (_uiDirty && Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
UserInterface?.SetState(new MicrowaveUpdateUserInterfaceState UserInterface?.SetState(new MicrowaveUpdateUserInterfaceState
( (
@@ -216,13 +216,13 @@ namespace Content.Server.GameObjects.Components.Kitchen
if (itemEntity.TryGetComponent<PourableComponent>(out var attackPourable)) if (itemEntity.TryGetComponent<PourableComponent>(out var attackPourable))
{ {
if (!itemEntity.TryGetComponent<SolutionComponent>(out var attackSolution) if (!itemEntity.TryGetComponent<SolutionContainerComponent>(out var attackSolution)
|| !attackSolution.CanPourOut) || !attackSolution.CanRemoveSolutions)
{ {
return false; return false;
} }
if (!Owner.TryGetComponent(out SolutionComponent? solution)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return false; return false;
} }
@@ -355,7 +355,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
private void VaporizeReagents() private void VaporizeReagents()
{ {
if (Owner.TryGetComponent(out SolutionComponent? solution)) if (Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
solution.RemoveAllSolution(); solution.RemoveAllSolution();
} }
@@ -363,7 +363,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
private void VaporizeReagentQuantity(Solution.ReagentQuantity reagentQuantity) private void VaporizeReagentQuantity(Solution.ReagentQuantity reagentQuantity)
{ {
if (Owner.TryGetComponent(out SolutionComponent? solution)) if (Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
solution?.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity); solution?.TryRemoveReagent(reagentQuantity.ReagentId, reagentQuantity.Quantity);
} }
@@ -399,7 +399,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
private void SubtractContents(FoodRecipePrototype recipe) private void SubtractContents(FoodRecipePrototype recipe)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return; return;
} }
@@ -434,7 +434,7 @@ namespace Content.Server.GameObjects.Components.Kitchen
private MicrowaveSuccessState CanSatisfyRecipe(FoodRecipePrototype recipe, Dictionary<string,int> solids) private MicrowaveSuccessState CanSatisfyRecipe(FoodRecipePrototype recipe, Dictionary<string,int> solids)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return MicrowaveSuccessState.RecipeFail; return MicrowaveSuccessState.RecipeFail;
} }

View File

@@ -35,7 +35,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
public override string Name => "Drink"; public override string Name => "Drink";
[ViewVariables] [ViewVariables]
private SolutionComponent _contents; private SolutionContainerComponent _contents;
[ViewVariables] [ViewVariables]
private string _useSound; private string _useSound;
[ViewVariables] [ViewVariables]
@@ -56,9 +56,9 @@ namespace Content.Server.GameObjects.Components.Nutrition
{ {
base.ExposeData(serializer); base.ExposeData(serializer);
serializer.DataField(ref _useSound, "useSound", "/Audio/Items/drink.ogg"); serializer.DataField(ref _useSound, "useSound", "/Audio/Items/drink.ogg");
serializer.DataField(ref _defaultToOpened, "isOpen", false); //For things like cups of coffee. serializer.DataField(ref _defaultToOpened, "isOpen", false); // For things like cups of coffee.
serializer.DataField(ref _soundCollection, "openSounds","canOpenSounds"); serializer.DataField(ref _soundCollection, "openSounds", "canOpenSounds");
serializer.DataField(ref _pressurized, "pressurized",false); serializer.DataField(ref _pressurized, "pressurized", false);
serializer.DataField(ref _burstSound, "burstSound", "/Audio/Effects/flash_bang.ogg"); serializer.DataField(ref _burstSound, "burstSound", "/Audio/Effects/flash_bang.ogg");
} }
@@ -66,14 +66,13 @@ namespace Content.Server.GameObjects.Components.Nutrition
{ {
base.Initialize(); base.Initialize();
Owner.TryGetComponent(out _appearanceComponent); Owner.TryGetComponent(out _appearanceComponent);
if(!Owner.TryGetComponent(out _contents))
if (!Owner.TryGetComponent(out _contents))
{ {
_contents = Owner.AddComponent<SolutionComponent>(); _contents = Owner.AddComponent<SolutionContainerComponent>();
} }
_contents.Capabilities = SolutionCaps.PourIn _contents.Capabilities = SolutionContainerCaps.AddTo | SolutionContainerCaps.RemoveFrom;
| SolutionCaps.PourOut
| SolutionCaps.Injectable;
Opened = _defaultToOpened; Opened = _defaultToOpened;
UpdateAppearance(); UpdateAppearance();
} }
@@ -83,11 +82,11 @@ namespace Content.Server.GameObjects.Components.Nutrition
UpdateAppearance(); UpdateAppearance();
} }
private void UpdateAppearance() private void UpdateAppearance()
{ {
_appearanceComponent?.SetData(SharedFoodComponent.FoodVisuals.Visual, _contents.CurrentVolume.Float()); _appearanceComponent?.SetData(SharedFoodComponent.FoodVisuals.Visual, _contents.CurrentVolume.Float());
} }
bool IUse.UseEntity(UseEntityEventArgs args) bool IUse.UseEntity(UseEntityEventArgs args)
{ {
if (!Opened) if (!Opened)
@@ -100,13 +99,20 @@ namespace Content.Server.GameObjects.Components.Nutrition
Opened = true; Opened = true;
return false; return false;
} }
if (_contents.CurrentVolume.Float() <= 0)
{
args.User.PopupMessage(Loc.GetString("{0:theName} is empty!", Owner));
return true;
}
return TryUseDrink(args.User); return TryUseDrink(args.User);
} }
//Force feeding a drink to someone. //Force feeding a drink to someone.
void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs) void IAfterInteract.AfterInteract(AfterInteractEventArgs eventArgs)
{ {
TryUseDrink(eventArgs.Target); TryUseDrink(eventArgs.Target, forced: true);
} }
public void Examine(FormattedMessage message, bool inDetailsRange) public void Examine(FormattedMessage message, bool inDetailsRange)
@@ -118,25 +124,28 @@ namespace Content.Server.GameObjects.Components.Nutrition
var color = Empty ? "gray" : "yellow"; var color = Empty ? "gray" : "yellow";
var openedText = Loc.GetString(Empty ? "Empty" : "Opened"); var openedText = Loc.GetString(Empty ? "Empty" : "Opened");
message.AddMarkup(Loc.GetString("[color={0}]{1}[/color]", color, openedText)); message.AddMarkup(Loc.GetString("[color={0}]{1}[/color]", color, openedText));
} }
private bool TryUseDrink(IEntity target) private bool TryUseDrink(IEntity target, bool forced = false)
{ {
if (target == null) if (target == null || !_contents.CanRemoveSolutions)
{ {
return false; return false;
} }
if (!Opened) if (!Opened)
{ {
target.PopupMessage(Loc.GetString("Open it first!")); target.PopupMessage(Loc.GetString("Open {0:theName} first!", Owner));
return false; return false;
} }
if (_contents.CurrentVolume.Float() <= 0) if (_contents.CurrentVolume.Float() <= 0)
{ {
target.PopupMessage(Loc.GetString("It's empty!")); if (!forced)
{
target.PopupMessage(Loc.GetString("{0:theName} is empty!", Owner));
}
return false; return false;
} }
@@ -147,18 +156,23 @@ 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.TryTransferSolution(split))
{ {
if (_useSound == null) return false; if (_useSound == null)
{
return false;
}
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();
return true; return true;
} }
//Stomach was full or can't handle whatever solution we have. // Stomach was full or can't handle whatever solution we have.
_contents.TryAddSolution(split); _contents.TryAddSolution(split);
target.PopupMessage(Loc.GetString("You've had enough {0}!", Owner.Name)); target.PopupMessage(Loc.GetString("You've had enough {0:theName}!", Owner));
return false; return false;
} }
@@ -167,7 +181,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
if (_pressurized && if (_pressurized &&
!Opened && !Opened &&
_random.Prob(0.25f) && _random.Prob(0.25f) &&
Owner.TryGetComponent(out SolutionComponent component)) Owner.TryGetComponent(out SolutionContainerComponent component))
{ {
Opened = true; Opened = true;

View File

@@ -41,7 +41,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
{ {
get get
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return 0; return 0;
} }
@@ -83,7 +83,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
public override void Initialize() public override void Initialize()
{ {
base.Initialize(); base.Initialize();
Owner.EnsureComponent<SolutionComponent>(); Owner.EnsureComponent<SolutionContainerComponent>();
} }
bool IUse.UseEntity(UseEntityEventArgs eventArgs) bool IUse.UseEntity(UseEntityEventArgs eventArgs)
@@ -110,7 +110,7 @@ namespace Content.Server.GameObjects.Components.Nutrition
public virtual bool TryUseFood(IEntity? user, IEntity? target, UtensilComponent? utensilUsed = null) public virtual bool TryUseFood(IEntity? user, IEntity? target, UtensilComponent? utensilUsed = null)
{ {
if (!Owner.TryGetComponent(out SolutionComponent? solution)) if (!Owner.TryGetComponent(out SolutionContainerComponent? solution))
{ {
return false; return false;
} }

View File

@@ -6,6 +6,7 @@ using Robust.Shared.Maths;
using Robust.Shared.Prototypes; using Robust.Shared.Prototypes;
using Robust.Shared.Serialization; using Robust.Shared.Serialization;
using YamlDotNet.RepresentationModel; using YamlDotNet.RepresentationModel;
using System;
namespace Content.Shared.Chemistry namespace Content.Shared.Chemistry
{ {
@@ -19,6 +20,7 @@ namespace Content.Shared.Chemistry
private string _id; private string _id;
private string _name; private string _name;
private string _description; private string _description;
private string _physicalDescription;
private Color _substanceColor; private Color _substanceColor;
private List<IMetabolizable> _metabolism; private List<IMetabolizable> _metabolism;
private string _spritePath; private string _spritePath;
@@ -26,7 +28,9 @@ namespace Content.Shared.Chemistry
public string ID => _id; public string ID => _id;
public string Name => _name; public string Name => _name;
public string Description => _description; public string Description => _description;
public string PhysicalDescription => _physicalDescription;
public Color SubstanceColor => _substanceColor; public Color SubstanceColor => _substanceColor;
//List of metabolism effects this reagent has, should really only be used server-side. //List of metabolism effects this reagent has, should really only be used server-side.
public List<IMetabolizable> Metabolism => _metabolism; public List<IMetabolizable> Metabolism => _metabolism;
public string SpriteReplacementPath => _spritePath; public string SpriteReplacementPath => _spritePath;
@@ -43,13 +47,36 @@ namespace Content.Shared.Chemistry
serializer.DataField(ref _id, "id", string.Empty); serializer.DataField(ref _id, "id", string.Empty);
serializer.DataField(ref _name, "name", string.Empty); serializer.DataField(ref _name, "name", string.Empty);
serializer.DataField(ref _description, "desc", string.Empty); serializer.DataField(ref _description, "desc", string.Empty);
serializer.DataField(ref _physicalDescription, "physicalDesc", string.Empty);
serializer.DataField(ref _substanceColor, "color", Color.White); serializer.DataField(ref _substanceColor, "color", Color.White);
serializer.DataField(ref _spritePath, "spritePath", string.Empty); serializer.DataField(ref _spritePath, "spritePath", string.Empty);
if (_moduleManager.IsServerModule) if (_moduleManager.IsServerModule)
serializer.DataField(ref _metabolism, "metabolism", new List<IMetabolizable> {new DefaultMetabolizable()}); {
serializer.DataField(ref _metabolism, "metabolism", new List<IMetabolizable> { new DefaultMetabolizable() });
}
else else
{
_metabolism = new List<IMetabolizable> { new DefaultMetabolizable() }; _metabolism = new List<IMetabolizable> { new DefaultMetabolizable() };
}
}
/// <summary>
/// If the substance color is too dark we user a lighter version to make the text color readable when the user examines a solution.
/// </summary>
public Color GetSubstanceTextColor()
{
var highestValue = MathF.Max(SubstanceColor.R, MathF.Max(SubstanceColor.G, SubstanceColor.B));
var difference = 0.5f - highestValue;
if (difference > 0f)
{
return new Color(SubstanceColor.R + difference,
SubstanceColor.G + difference,
SubstanceColor.B + difference);
}
return SubstanceColor;
} }
} }
} }

View File

@@ -246,7 +246,7 @@ namespace Content.Shared.Chemistry
} }
[Serializable, NetSerializable] [Serializable, NetSerializable]
public readonly struct ReagentQuantity public readonly struct ReagentQuantity: IComparable<ReagentQuantity>
{ {
public readonly string ReagentId; public readonly string ReagentId;
public readonly ReagentUnit Quantity; public readonly ReagentUnit Quantity;
@@ -262,6 +262,8 @@ namespace Content.Shared.Chemistry
{ {
return $"{ReagentId}:{Quantity}"; return $"{ReagentId}:{Quantity}";
} }
public int CompareTo(ReagentQuantity other) { return Quantity.Float().CompareTo(other.Quantity.Float()); }
} }
#region Enumeration #region Enumeration

View File

@@ -8,15 +8,19 @@ namespace Content.Shared.Chemistry
/// </summary> /// </summary>
[Flags] [Flags]
[Serializable, NetSerializable] [Serializable, NetSerializable]
public enum SolutionCaps public enum SolutionContainerCaps
{ {
None = 0, None = 0,
PourIn = 1, /// <summary>
PourOut = 2, /// Can solutions be added into the container?
/// </summary>
AddTo = 1,
Injector = 4, /// <summary>
Injectable = 8, /// Can solutions be removed from the container?
/// </summary>
RemoveFrom = 2,
/// <summary> /// <summary>
/// Allows the container to be placed in a <c>ReagentDispenserComponent</c>. /// Allows the container to be placed in a <c>ReagentDispenserComponent</c>.
@@ -24,8 +28,11 @@ namespace Content.Shared.Chemistry
/// <para>Allows us to have obscenely large containers that are harder to abuse in chem dispensers /// <para>Allows us to have obscenely large containers that are harder to abuse in chem dispensers
/// since they can't be placed directly in them.</para> /// since they can't be placed directly in them.</para>
/// </summary> /// </summary>
FitsInDispenser = 16, FitsInDispenser = 4,
NoExamine = 32, /// <summary>
/// Can people examine the solution in the container or is it impossible to see?
/// </summary>
NoExamine = 8,
} }
} }

View File

@@ -4,9 +4,9 @@ using Robust.Shared.Serialization;
namespace Content.Shared.GameObjects.Components.Chemistry namespace Content.Shared.GameObjects.Components.Chemistry
{ {
public class SharedSolutionComponent : Component public class SharedSolutionContainerComponent : Component
{ {
public override string Name => "Solution"; public override string Name => "SolutionContainer";
/// <inheritdoc /> /// <inheritdoc />
public sealed override uint? NetID => ContentNetIDs.SOLUTION; public sealed override uint? NetID => ContentNetIDs.SOLUTION;
@@ -28,13 +28,13 @@ namespace Content.Shared.GameObjects.Components.Chemistry
{ {
base.HandleComponentState(curState, nextState); base.HandleComponentState(curState, nextState);
if(curState == null) if (curState == null)
{
return; return;
}
var compState = (SolutionComponentState)curState;
// var compState = (SolutionComponentState)curState;
//TODO: Make me work! // Is there anything we even need to sync with client?
} }
} }
} }

View File

@@ -580,8 +580,8 @@ entities:
pos: -15.694785,24.608267 pos: -15.694785,24.608267
rot: -1.5707963267948966 rad rot: -1.5707963267948966 rad
type: Transform type: Transform
- caps: PourIn, PourOut, Injectable - caps: AddTo, RemoveFrom
type: Solution type: SolutionContainer
- anchored: False - anchored: False
type: Collidable type: Collidable
- uid: 60 - uid: 60
@@ -718,8 +718,8 @@ entities:
pos: -3.470539,16.956116 pos: -3.470539,16.956116
rot: -1.5707963267948966 rad rot: -1.5707963267948966 rad
type: Transform type: Transform
- caps: PourIn, PourOut, Injectable - caps: AddTo, RemoveFrom
type: Solution type: SolutionContainer
- anchored: False - anchored: False
type: Collidable type: Collidable
- uid: 74 - uid: 74
@@ -1037,8 +1037,8 @@ entities:
- parent: 857 - parent: 857
pos: 8.661116,25.513401 pos: 8.661116,25.513401
type: Transform type: Transform
- caps: PourIn, PourOut, Injectable - caps: AddTo, RemoveFrom
type: Solution type: SolutionContainer
- anchored: False - anchored: False
type: Collidable type: Collidable
- uid: 114 - uid: 114
@@ -22848,7 +22848,7 @@ entities:
rot: 3.141592653589793 rad rot: 3.141592653589793 rad
type: Transform type: Transform
- fillingSteps: 0 - fillingSteps: 0
type: Solution type: SolutionContainer
- anchored: False - anchored: False
type: Collidable type: Collidable
- uid: 1219 - uid: 1219
@@ -32479,8 +32479,8 @@ entities:
pos: -8.476567,-17.420076 pos: -8.476567,-17.420076
rot: -1.5707963267948966 rad rot: -1.5707963267948966 rad
type: Transform type: Transform
- caps: PourIn, PourOut, Injectable - caps: AddTo, RemoveFrom
type: Solution type: SolutionContainer
- anchored: False - anchored: False
type: Collidable type: Collidable
- uid: 2454 - uid: 2454

View File

@@ -118,8 +118,8 @@
- type: entity - type: entity
parent: GlovesBase parent: GlovesBase
id: GlovesGray id: GlovesGray
name: gray gloves name: grey gloves
description: Regular gray gloves that do not keep you from frying. description: Regular grey gloves that do not keep you from frying.
components: components:
- type: Sprite - type: Sprite
sprite: Clothing/Gloves/gray.rsi sprite: Clothing/Gloves/gray.rsi

View File

@@ -28,7 +28,7 @@
parent: HatBase parent: HatBase
id: HatMouseGray id: HatMouseGray
name: mouse gray name: mouse gray
description: This is a head of a gray mouse. Squeak! description: This is a head of a grey mouse. Squeak!
components: components:
- type: Sprite - type: Sprite
sprite: Clothing/Head/mouse_gray.rsi sprite: Clothing/Head/mouse_gray.rsi

View File

@@ -10,9 +10,9 @@
- type: Microwave - type: Microwave
- type: Clickable - type: Clickable
- type: InteractionOutline - type: InteractionOutline
- type: Solution - type: SolutionContainer
maxVol: 100 maxVol: 100
caps: 1 caps: AddTo
- type: Appearance - type: Appearance
visuals: visuals:
- type: MicrowaveVisualizer - type: MicrowaveVisualizer

View File

@@ -13,7 +13,7 @@
heavyImpactRange: 2 heavyImpactRange: 2
lightImpactRange: 6 lightImpactRange: 6
flashRange: 5 flashRange: 5
- type: Solution - type: SolutionContainer
contents: contents:
reagents: reagents:
- ReagentId: chem.WeldingFuel - ReagentId: chem.WeldingFuel

View File

@@ -27,9 +27,9 @@
Anchored: false Anchored: false
- type: Destructible - type: Destructible
deadThreshold: 10 deadThreshold: 10
- type: Solution - type: SolutionContainer
maxVol: 1500 maxVol: 1500
caps: 2 caps: RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 100.0 transferAmount: 100.0
placement: placement:

View File

@@ -17,7 +17,7 @@
id: WaterTankFull id: WaterTankFull
suffix: Full suffix: Full
components: components:
- type: Solution - type: SolutionContainer
contents: contents:
reagents: reagents:
- ReagentId: chem.H2O - ReagentId: chem.H2O

View File

@@ -18,9 +18,9 @@
- type: Hunger - type: Hunger
- type: Thirst - type: Thirst
# Organs # Organs
- type: Solution - type: SolutionContainer
maxVol: 250 maxVol: 250
caps: 32 caps: AddTo, RemoveFrom, NoExamine
- type: Bloodstream - type: Bloodstream
max_volume: 100 max_volume: 100
- type: Stomach - type: Stomach

View File

@@ -6,8 +6,9 @@
id: DrinkBase id: DrinkBase
abstract: true abstract: true
components: components:
- type: Solution - type: SolutionContainer
maxVol: 50 maxVol: 50
caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: Drink - type: Drink
@@ -15,7 +16,7 @@
state: icon state: icon
- type: Icon - type: Icon
state: icon state: icon
- type: CanSpill - type: Spillable
- type: entity - type: entity
parent: DrinkBase parent: DrinkBase
@@ -35,10 +36,10 @@
sprite: Objects/Consumable/Drinks/glass_clear.rsi sprite: Objects/Consumable/Drinks/glass_clear.rsi
- type: Icon - type: Icon
sprite: Objects/Consumable/Drinks/glass_clear.rsi sprite: Objects/Consumable/Drinks/glass_clear.rsi
- type: Solution - type: SolutionContainer
fillingState: glass fillingState: glass
maxVol: 50 maxVol: 50
caps: 16 caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: TransformableContainer - type: TransformableContainer
@@ -47,9 +48,9 @@
parent: DrinkGlassBase parent: DrinkGlassBase
id: DrinkAleglass id: DrinkAleglass
name: ale name: ale
description: A dark alchoholic beverage made by malted barley and yeast. description: A dark alchoholic beverage made with malted barley and yeast.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -66,7 +67,7 @@
name: anti-freeze name: anti-freeze
description: Ultimate refreshment. description: Ultimate refreshment.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -84,7 +85,7 @@
name: atomic bomb glass name: atomic bomb glass
description: Nuclear proliferation never tasted so good. description: Nuclear proliferation never tasted so good.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -102,7 +103,7 @@
name: b-52 glass name: b-52 glass
description: Coffee, Irish Cream, and cognac. You will get bombed. description: Coffee, Irish Cream, and cognac. You will get bombed.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -144,7 +145,7 @@
name: beer # beer it is. coffee. beer? coff-ee? be-er? c-o... b-e name: beer # beer it is. coffee. beer? coff-ee? be-er? c-o... b-e
description: An alcoholic beverage made from malted grains, hops, yeast, and water. description: An alcoholic beverage made from malted grains, hops, yeast, and water.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -161,7 +162,7 @@
name: beer glass name: beer glass
description: An alcoholic beverage made from malted grains, hops, yeast, and water. description: An alcoholic beverage made from malted grains, hops, yeast, and water.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -305,7 +306,7 @@
name: coffee name: coffee
description: Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant. description: Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -322,7 +323,7 @@
name: cognac glass name: cognac glass
description: A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. Classy as fornication. description: A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. Classy as fornication.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -339,7 +340,7 @@
name: space cola bottle name: space cola bottle
description: Cola. in space description: Cola. in space
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -356,7 +357,7 @@
name: cream name: cream
description: Dairy product composed of the higher-fat layer skimmed from the top of milk before homogenization. description: Dairy product composed of the higher-fat layer skimmed from the top of milk before homogenization.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -373,7 +374,7 @@
name: cuba libre glass name: cuba libre glass
description: Rum, mixed with cola. Viva la revolucion. description: Rum, mixed with cola. Viva la revolucion.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -642,7 +643,7 @@
name: milk name: milk
description: An opaque white liquid produced by the mammary glands of mammals. description: An opaque white liquid produced by the mammary glands of mammals.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -804,7 +805,7 @@
name: ice glass name: ice glass
description: Water frozen into a solid state. description: Water frozen into a solid state.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -821,7 +822,7 @@
name: irish car bomb name: irish car bomb
description: Mmm, tastes like chocolate cake... description: Mmm, tastes like chocolate cake...
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -838,7 +839,7 @@
name: irish coffee glass name: irish coffee glass
description: Coffee, and alcohol. More fun than a Mimosa to drink in the morning. description: Coffee, and alcohol. More fun than a Mimosa to drink in the morning.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -855,7 +856,7 @@
name: irish cream glass name: irish cream glass
description: Whiskey-imbued cream, what else would you expect from the Irish. description: Whiskey-imbued cream, what else would you expect from the Irish.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -908,7 +909,7 @@
name: kahlua glass name: kahlua glass
description: A widely known, Mexican coffee-flavoured liqueur. description: A widely known, Mexican coffee-flavoured liqueur.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1045,7 +1046,7 @@
name: the manly dorf glass name: the manly dorf glass
description: Beer and Ale, brought together in a delicious mix. Intended for true men only. description: Beer and Ale, brought together in a delicious mix. Intended for true men only.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1098,7 +1099,7 @@
name: milk jug name: milk jug
description: An opaque white liquid produced by the mammary glands of mammals. description: An opaque white liquid produced by the mammary glands of mammals.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1597,7 +1598,7 @@
name: syndicate bomb name: syndicate bomb
description: Tastes like terrorism! description: Tastes like terrorism!
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1614,7 +1615,7 @@
name: tea glass name: tea glass
description: Tasty black tea. Contains caffeine. description: Tasty black tea. Contains caffeine.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1631,7 +1632,7 @@
name: teapot # short and stout name: teapot # short and stout
description: An elegant teapot. It simply oozes class. description: An elegant teapot. It simply oozes class.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1822,7 +1823,7 @@
name: whiskey cola glass name: whiskey cola glass
description: Whiskey, mixed with cola. Surprisingly refreshing. description: Whiskey, mixed with cola. Surprisingly refreshing.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1839,7 +1840,7 @@
name: special blend whiskey glass name: special blend whiskey glass
description: Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything. description: Just when you thought regular station whiskey was good... This silky, amber goodness has to come along and ruin everything.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -1892,7 +1893,7 @@
name: wine glass name: wine glass
description: An premium alchoholic beverage made from distilled grape juice. description: An premium alchoholic beverage made from distilled grape juice.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:

View File

@@ -5,14 +5,15 @@
components: components:
- type: Drink - type: Drink
openSounds: bottleOpenSounds openSounds: bottleOpenSounds
- type: Solution - type: SolutionContainer
caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: Sprite - type: Sprite
state: icon state: icon
- type: Icon - type: Icon
state: icon state: icon
- type: CanSpill - type: Spillable
- type: entity - type: entity
parent: DrinkBottleBaseFull parent: DrinkBottleBaseFull
@@ -44,7 +45,7 @@
name: magm-ale name: magm-ale
description: A true dorf's drink of choice. description: A true dorf's drink of choice.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:
@@ -73,7 +74,7 @@
name: cognac bottle name: cognac bottle
description: A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time. description: A sweet and strongly alchoholic drink, made after numerous distillations and years of maturing. You might as well not scream 'SHITCURITY' this time.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:
@@ -114,7 +115,7 @@
name: kahlua bottle name: kahlua bottle
description: A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK description: A widely known, Mexican coffee-flavoured liqueur. In production since 1936, HONK
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:
@@ -191,7 +192,7 @@
name: vodka bottle name: vodka bottle
description: Aah, vodka. Prime choice of drink AND fuel by Russians worldwide. description: Aah, vodka. Prime choice of drink AND fuel by Russians worldwide.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:
@@ -208,7 +209,7 @@
name: uncle git's special reserve name: uncle git's special reserve
description: A premium single-malt whiskey, gently matured inside the tunnels of a nuclear shelter. TUNNEL WHISKEY RULES. description: A premium single-malt whiskey, gently matured inside the tunnels of a nuclear shelter. TUNNEL WHISKEY RULES.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:
@@ -225,7 +226,7 @@
name: doublebearded bearded special wine bottle name: doublebearded bearded special wine bottle
description: A faint aura of unease and asspainery surrounds the bottle. description: A faint aura of unease and asspainery surrounds the bottle.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 80 maxVol: 80
contents: contents:
reagents: reagents:

View File

@@ -6,8 +6,9 @@
- type: Drink - type: Drink
openSounds: canOpenSounds openSounds: canOpenSounds
pressurized: true pressurized: true
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
caps: AddTo, RemoveFrom
contents: contents:
reagents: reagents:
- ReagentId: chem.Cola - ReagentId: chem.Cola
@@ -18,7 +19,7 @@
state: icon state: icon
- type: Icon - type: Icon
state: icon state: icon
- type: CanSpill - type: Spillable
- type: entity - type: entity
parent: DrinkCanBaseFull parent: DrinkCanBaseFull
@@ -26,7 +27,7 @@
name: space cola name: space cola
description: A refreshing beverage. description: A refreshing beverage.
components: components:
- type: Solution - type: SolutionContainer
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/cola.rsi sprite: Objects/Consumable/Drinks/cola.rsi
- type: Icon - type: Icon
@@ -37,8 +38,8 @@
- type: entity - type: entity
parent: DrinkCanBaseFull parent: DrinkCanBaseFull
id: DrinkIceTeaCan id: DrinkIceTeaCan
name: ice tea can name: iced tea can
description: A can of refreshing ice tea. description: A refreshing can of iced tea.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/ice_tea_can.rsi sprite: Objects/Consumable/Drinks/ice_tea_can.rsi
@@ -51,7 +52,7 @@
parent: DrinkCanBaseFull parent: DrinkCanBaseFull
id: DrinkLemonLimeCan id: DrinkLemonLimeCan
name: lemon-lime can name: lemon-lime can
description: You wanted ORANGE. It gave you Lemon Lime. description: You wanted ORANGE. It gave you Lemon-Lime.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/lemon-lime.rsi sprite: Objects/Consumable/Drinks/lemon-lime.rsi
@@ -64,7 +65,7 @@
parent: DrinkCanBaseFull parent: DrinkCanBaseFull
id: DrinkGrapeCan id: DrinkGrapeCan
name: grape soda can name: grape soda can
description: 'Sweetened drink with a grape flavor and a deep purple color.' description: Sweetened drink with a grape flavor and a deep purple color.
components: components:
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/purple_can.rsi sprite: Objects/Consumable/Drinks/purple_can.rsi
@@ -156,8 +157,8 @@
- type: entity - type: entity
parent: DrinkCanBaseFull parent: DrinkCanBaseFull
id: DrinkEnergyDrink id: DrinkEnergyDrink
name: Energy drink name: red bool energy drink
description: '' description: A can of Red Bool, with enough caffeine to kill a horse.
components: components:
- type: Drink - type: Drink
- type: Sprite - type: Sprite

View File

@@ -5,8 +5,9 @@
name: base cup name: base cup
abstract: true abstract: true
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: Drink - type: Drink
@@ -15,7 +16,7 @@
state: icon state: icon
- type: Icon - type: Icon
state: icon state: icon
- type: CanSpill - type: Spillable
- type: entity - type: entity
parent: DrinkBaseCup parent: DrinkBaseCup
@@ -23,7 +24,7 @@
name: golden cup name: golden cup
description: A golden cup description: A golden cup
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/golden_cup.rsi sprite: Objects/Consumable/Drinks/golden_cup.rsi
@@ -36,7 +37,7 @@
name: insulated pitcher name: insulated pitcher
description: A stainless steel insulated pitcher. Everyone's best friend in the morning. description: A stainless steel insulated pitcher. Everyone's best friend in the morning.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 15 maxVol: 15
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/pitcher.rsi sprite: Objects/Consumable/Drinks/pitcher.rsi
@@ -55,7 +56,7 @@
name: mug name: mug
description: A plain white mug. description: A plain white mug.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug.rsi sprite: Objects/Consumable/Drinks/mug.rsi
@@ -74,7 +75,7 @@
name: mug black name: mug black
description: A sleek black mug. description: A sleek black mug.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_black.rsi sprite: Objects/Consumable/Drinks/mug_black.rsi
@@ -93,7 +94,7 @@
name: mug blue name: mug blue
description: A blue and black mug. description: A blue and black mug.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_blue.rsi sprite: Objects/Consumable/Drinks/mug_blue.rsi
@@ -112,7 +113,7 @@
name: mug green name: mug green
description: A pale green and pink mug. description: A pale green and pink mug.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_green.rsi sprite: Objects/Consumable/Drinks/mug_green.rsi
@@ -131,7 +132,7 @@
name: mug heart name: mug heart
description: A white mug, it prominently features a red heart. description: A white mug, it prominently features a red heart.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_heart.rsi sprite: Objects/Consumable/Drinks/mug_heart.rsi
@@ -150,7 +151,7 @@
name: mug metal name: mug metal
description: A metal mug. You're not sure which metal. description: A metal mug. You're not sure which metal.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_metal.rsi sprite: Objects/Consumable/Drinks/mug_metal.rsi
@@ -169,7 +170,7 @@
name: mug moebius name: mug moebius
description: A mug with a Moebius Laboratories logo on it. Not even your morning coffee is safe from corporate advertising. description: A mug with a Moebius Laboratories logo on it. Not even your morning coffee is safe from corporate advertising.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_moebius.rsi sprite: Objects/Consumable/Drinks/mug_moebius.rsi
@@ -188,7 +189,7 @@
name: "#1 mug" name: "#1 mug"
description: "A white mug, it prominently features a #1." description: "A white mug, it prominently features a #1."
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_one.rsi sprite: Objects/Consumable/Drinks/mug_one.rsi
@@ -207,7 +208,7 @@
name: mug rainbow name: mug rainbow
description: A rainbow mug. The colors are almost as blinding as a welder. description: A rainbow mug. The colors are almost as blinding as a welder.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_rainbow.rsi sprite: Objects/Consumable/Drinks/mug_rainbow.rsi
@@ -226,7 +227,7 @@
name: mug red name: mug red
description: A red and black mug. description: A red and black mug.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
- type: Sprite - type: Sprite
sprite: Objects/Consumable/Drinks/mug_red.rsi sprite: Objects/Consumable/Drinks/mug_red.rsi
@@ -257,7 +258,7 @@
name: Coffee name: Coffee
description: Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant. description: Coffee is a brewed drink prepared from roasted seeds, commonly called coffee beans, of the coffee plant.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -274,7 +275,7 @@
name: Teacup name: Teacup
description: A plain white porcelain teacup. description: A plain white porcelain teacup.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:
@@ -295,9 +296,9 @@
parent: DrinkBaseCup parent: DrinkBaseCup
id: DrinkLean id: DrinkLean
name: Lean name: Lean
description: Bro Drake has such a cool fade bro Drake is the best bro c'mon bro he's description: Bro Drake has such a cool fade bro Drake is the best bro c'mon bro.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 20 maxVol: 20
contents: contents:
reagents: reagents:

File diff suppressed because it is too large Load Diff

View File

@@ -4,8 +4,9 @@
name: flour name: flour
description: Not to be confused with flower. description: Not to be confused with flower.
components: components:
- type: Solution - type: SolutionContainer
maxVol: 50 maxVol: 50
caps: AddTo, RemoveFrom
contents: contents:
reagents: reagents:
- ReagentId: chem.Flour - ReagentId: chem.Flour
@@ -19,4 +20,4 @@
- type: Icon - type: Icon
sprite: Objects/Consumable/Food/flour.rsi sprite: Objects/Consumable/Food/flour.rsi
state: icon state: icon
- type: CanSpill - type: Spillable

View File

@@ -11,13 +11,14 @@
state: icon state: icon
- type: Icon - type: Icon
state: icon state: icon
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: Drink - type: Drink
isOpen: true isOpen: true
- type: CanSpill - type: Spillable
# Containers # Containers

View File

@@ -14,9 +14,9 @@
- type: Item - type: Item
sprite: Objects/Misc/fire_extinguisher.rsi sprite: Objects/Misc/fire_extinguisher.rsi
size: 10 size: 10
- type: Solution - type: SolutionContainer
maxVol: 1000 maxVol: 1000
caps: 9 caps: AddTo, RemoveFrom, NoExamine
contents: contents:
reagents: reagents:
- ReagentId: chem.H2O - ReagentId: chem.H2O

View File

@@ -11,13 +11,13 @@
- type: Item - type: Item
sprite: Objects/Specific/Chemistry/beakers.rsi sprite: Objects/Specific/Chemistry/beakers.rsi
HeldPrefix: beaker HeldPrefix: beaker
- type: Solution - type: SolutionContainer
fillingState: beaker fillingState: beaker
maxVol: 50 maxVol: 50
caps: 27 caps: AddTo, RemoveFrom, FitsInDispenser # can add and remove solutions and fits in the chemmaster.
- type: Pourable - type: Pourable
transferAmount: 5.0 transferAmount: 5.0
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: large beaker name: large beaker
@@ -32,13 +32,13 @@
- type: Item - type: Item
sprite: Objects/Specific/Chemistry/beakers.rsi sprite: Objects/Specific/Chemistry/beakers.rsi
HeldPrefix: beaker HeldPrefix: beaker
- type: Solution - type: SolutionContainer
fillingState: beakerlarge fillingState: beakerlarge
maxVol: 100 maxVol: 100
caps: 27 caps: AddTo, RemoveFrom, FitsInDispenser
- type: Pourable - type: Pourable
transferAmount: 5.0 transferAmount: 5.0
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: dropper name: dropper
@@ -50,14 +50,14 @@
texture: Objects/Specific/Chemistry/dropper.rsi/dropper.png texture: Objects/Specific/Chemistry/dropper.rsi/dropper.png
- type: Icon - type: Icon
texture: Objects/Specific/Chemistry/dropper.rsi/dropper.png texture: Objects/Specific/Chemistry/dropper.rsi/dropper.png
- type: Solution - type: SolutionContainer
fillingState: dropper fillingState: dropper
fillingSteps: 2 fillingSteps: 2
maxVol: 5 maxVol: 5
caps: 19 caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5.0 transferAmount: 5.0
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: syringe name: syringe
@@ -69,14 +69,14 @@
texture: Objects/Specific/Chemistry/syringe.rsi/0.png texture: Objects/Specific/Chemistry/syringe.rsi/0.png
- type: Icon - type: Icon
texture: Objects/Specific/Chemistry/syringe.rsi/0.png texture: Objects/Specific/Chemistry/syringe.rsi/0.png
- type: Solution - type: SolutionContainer
fillingState: syringe fillingState: syringe
fillingSteps: 5 fillingSteps: 5
maxVol: 15 maxVol: 15
caps: 19 caps: AddTo, RemoveFrom
- type: Injector - type: Injector
injectOnly: false injectOnly: false
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: bottle name: bottle
@@ -84,15 +84,16 @@
id: bottle id: bottle
components: components:
- type: Drink - type: Drink
- type: Solution - type: SolutionContainer
maxVol: 30 maxVol: 30
caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5 transferAmount: 5
- type: Sprite - type: Sprite
texture: Objects/Specific/Chemistry/bottle.rsi/bottle.png texture: Objects/Specific/Chemistry/bottle.rsi/bottle.png
- type: Icon - type: Icon
texture: Objects/Specific/Chemistry/bottle.rsi/bottle.png texture: Objects/Specific/Chemistry/bottle.rsi/bottle.png
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: pill name: pill
@@ -101,8 +102,9 @@
description: It's not a suppository. description: It's not a suppository.
components: components:
- type: Pill - type: Pill
- type: Solution - type: SolutionContainer
maxVol: 50 maxVol: 50
caps: RemoveFrom
- type: Sprite - type: Sprite
texture: Objects/Specific/Chemistry/pills.rsi/pill.png texture: Objects/Specific/Chemistry/pills.rsi/pill.png
- type: Icon - type: Icon

View File

@@ -14,9 +14,9 @@
size: 10 size: 10
sprite: Objects/Specific/Janitorial/mop.rsi sprite: Objects/Specific/Janitorial/mop.rsi
- type: Mop - type: Mop
- type: Solution - type: SolutionContainer
maxVol: 10 maxVol: 10
caps: 1 caps: AddTo, RemoveFrom
- type: LoopingSound - type: LoopingSound
- type: entity - type: entity
@@ -33,9 +33,9 @@
- type: InteractionOutline - type: InteractionOutline
- type: Bucket - type: Bucket
- type: LoopingSound - type: LoopingSound
- type: Solution - type: SolutionContainer
maxVol: 500 maxVol: 500
caps: 3 caps: AddTo, RemoveFrom
- type: Collidable - type: Collidable
shapes: shapes:
- !type:PhysShapeAabb - !type:PhysShapeAabb
@@ -49,14 +49,14 @@
- type: Physics - type: Physics
mass: 5 mass: 5
anchored: false anchored: false
- type: CanSpill - type: Spillable
- type: Pullable - type: Pullable
- type: entity - type: entity
parent: BaseItem parent: BaseItem
name: bucket name: bucket
id: Bucket id: Bucket
description: "Dear God." description: It's a boring old bucket.
components: components:
- type: Clickable - type: Clickable
- type: Sprite - type: Sprite
@@ -66,9 +66,9 @@
texture: Objects/Specific/Janitorial/bucket.png texture: Objects/Specific/Janitorial/bucket.png
- type: Bucket - type: Bucket
- type: LoopingSound - type: LoopingSound
- type: Solution - type: SolutionContainer
maxVol: 500 maxVol: 500
caps: 3 caps: AddTo, RemoveFrom
- type: Collidable - type: Collidable
shapes: shapes:
- !type:PhysShapeAabb - !type:PhysShapeAabb
@@ -79,7 +79,7 @@
- type: Physics - type: Physics
mass: 5 mass: 5
anchored: false anchored: false
- type: CanSpill - type: Spillable
- type: entity - type: entity
name: wet floor sign name: wet floor sign
@@ -190,12 +190,12 @@
texture: Objects/Specific/Janitorial/cleaner.png texture: Objects/Specific/Janitorial/cleaner.png
- type: Icon - type: Icon
texture: Objects/Specific/Janitorial/cleaner.png texture: Objects/Specific/Janitorial/cleaner.png
- type: Solution - type: SolutionContainer
maxVol: 100 maxVol: 100
caps: 1 caps: AddTo, RemoveFrom
- type: Pourable - type: Pourable
transferAmount: 5.0 transferAmount: 5.0
- type: CanSpill - type: Spillable
- type: Spray - type: Spray
transferAmount: 10 transferAmount: 10
sprayVelocity: 5 sprayVelocity: 5

View File

@@ -89,9 +89,9 @@
- type: ItemCooldown - type: ItemCooldown
- type: MeleeWeapon - type: MeleeWeapon
- type: ItemStatus - type: ItemStatus
- type: Solution - type: SolutionContainer
maxVol: 100 maxVol: 100
caps: 9 caps: AddTo, NoExamine
contents: contents:
reagents: reagents:
- ReagentId: chem.WeldingFuel - ReagentId: chem.WeldingFuel

View File

@@ -4,7 +4,7 @@
name: "reagent item" name: "reagent item"
abstract: true abstract: true
components: components:
- type: Solution - type: SolutionContainer
maxVol: 5 maxVol: 5
- type: entity - type: entity
@@ -14,7 +14,7 @@
components: components:
- type: SnapGrid - type: SnapGrid
offset: Center offset: Center
- type: Solution - type: SolutionContainer
maxVol: 50 maxVol: 50
- type: Vapor - type: Vapor
- type: Physics - type: Physics

View File

@@ -7,8 +7,8 @@
offset: Center offset: Center
- type: Sprite - type: Sprite
drawdepth: FloorObjects drawdepth: FloorObjects
- type: Solution - type: SolutionContainer
caps: 1 caps: AddTo, RemoveFrom
- type: Puddle - type: Puddle
spill_sound: /Audio/Effects/Fluids/splat.ogg spill_sound: /Audio/Effects/Fluids/splat.ogg
recolor: true recolor: true

View File

@@ -2,6 +2,7 @@
id: chem.Nutriment id: chem.Nutriment
name: nutriment name: nutriment
desc: All the vitamins, minerals, and carbohydrates the body needs in pure form. desc: All the vitamins, minerals, and carbohydrates the body needs in pure form.
physicalDesc: opaque
color: "#664330" color: "#664330"
metabolism: metabolism:
- !type:DefaultFood - !type:DefaultFood
@@ -11,6 +12,7 @@
id: chem.H2SO4 id: chem.H2SO4
name: sulfuric acid name: sulfuric acid
desc: A highly corrosive, oily, colorless liquid. desc: A highly corrosive, oily, colorless liquid.
physicalDesc: oily
color: "#BF8C00" color: "#BF8C00"
boilingPoint: 337.0 boilingPoint: 337.0
meltingPoint: 10.31 meltingPoint: 10.31
@@ -18,7 +20,8 @@
- type: reagent - type: reagent
id: chem.H2O id: chem.H2O
name: water name: water
desc: A tasty colorless liquid. desc: A colorless liquid that humans need in order to survive.
physicalDesc: translucent
color: "#c0e0ff20" color: "#c0e0ff20"
boilingPoint: 100.0 boilingPoint: 100.0
meltingPoint: 0.0 meltingPoint: 0.0
@@ -30,6 +33,7 @@
id: chem.Ice id: chem.Ice
name: ice name: ice
desc: Frozen water. desc: Frozen water.
physicalDesc: frosty
color: "#bed8e6" color: "#bed8e6"
meltingPoint: 0.0 meltingPoint: 0.0
boilingPoint: 100.0 boilingPoint: 100.0
@@ -38,7 +42,8 @@
id: chem.Phoron id: chem.Phoron
name: phoron name: phoron
desc: Funky, space-magic pixie dust. You probably shouldn't eat this, but we both know you will anyways. desc: Funky, space-magic pixie dust. You probably shouldn't eat this, but we both know you will anyways.
color: "#500064" physicalDesc: gaseous
color: "#7e009e"
boilingPoint: -127.3 # Random values picked between the actual values for CO2 and O2 boilingPoint: -127.3 # Random values picked between the actual values for CO2 and O2
meltingPoint: -186.4 meltingPoint: -186.4
@@ -46,6 +51,7 @@
id: chem.Ethanol id: chem.Ethanol
name: ethanol name: ethanol
desc: A simple alcohol, makes you drunk if consumed, flammable. desc: A simple alcohol, makes you drunk if consumed, flammable.
physicalDesc: strong-smelling
color: "#b05b3c" color: "#b05b3c"
boilingPoint: 78.2 boilingPoint: 78.2
meltingPoint: -114.1 meltingPoint: -114.1
@@ -54,6 +60,7 @@
id: chem.Glucose id: chem.Glucose
name: glucose name: glucose
desc: A simple sugar found in many foods. desc: A simple sugar found in many foods.
physicalDesc: syrupy
color: "#ffffff" color: "#ffffff"
boilingPoint: 340282300000000000000000000000000000000 #Fun fact: Glucose can't boil. So let's just set it to the maximum float value. boilingPoint: 340282300000000000000000000000000000000 #Fun fact: Glucose can't boil. So let's just set it to the maximum float value.
meltingPoint: 146.0 meltingPoint: 146.0
@@ -62,6 +69,7 @@
id: chem.Ammonia id: chem.Ammonia
name: ammonia name: ammonia
desc: An effective fertilizer which is better than what is available to the botanist initially, though it isn't as powerful as Diethylamine desc: An effective fertilizer which is better than what is available to the botanist initially, though it isn't as powerful as Diethylamine
physicalDesc: pungent
color: "#77b58e" color: "#77b58e"
boilingPoint: -33.0 boilingPoint: -33.0
meltingPoint: -77.7 meltingPoint: -77.7
@@ -70,6 +78,7 @@
id: chem.Bleach id: chem.Bleach
name: bleach name: bleach
desc: Heavy duty cleaner that can clean tiles the same as Space Cleaner and also decontaminate clothes. Extremely toxic when ingested. desc: Heavy duty cleaner that can clean tiles the same as Space Cleaner and also decontaminate clothes. Extremely toxic when ingested.
physicalDesc: strong-smelling
color: "#a1000b" color: "#a1000b"
boilingPoint: 111.0 boilingPoint: 111.0
meltingPoint: -5.0 meltingPoint: -5.0
@@ -78,6 +87,7 @@
id: chem.Diethylamine id: chem.Diethylamine
name: diethylamine name: diethylamine
desc: A very potent fertilizer. desc: A very potent fertilizer.
physicalDesc: strong-smelling
color: "#a1000b" color: "#a1000b"
boilingPoint: 55.5 boilingPoint: 55.5
meltingPoint: -50.0 meltingPoint: -50.0
@@ -86,6 +96,7 @@
id: chem.FoamingAgent id: chem.FoamingAgent
name: foaming agent name: foaming agent
desc: Makes foam such as that required in metal foam grenades desc: Makes foam such as that required in metal foam grenades
physicalDesc: foamy
color: "#215263" color: "#215263"
boilingPoint: 418.0 # I went with ammonium lauryl sulfate as the basis for this boilingPoint: 418.0 # I went with ammonium lauryl sulfate as the basis for this
meltingPoint: 7.4 # I made this up meltingPoint: 7.4 # I made this up
@@ -94,6 +105,7 @@
id: chem.PolytrinicAcid id: chem.PolytrinicAcid
name: polytrinic acid name: polytrinic acid
desc: An extremely corrosive chemical substance. The slightest touch of it will melt off most masks and headgear, and it deals extreme damage to anyone who comes directly into contact with it. Spraying it on other items will usually melt them too, which does make it useful if the clown has covered the entire hallway in banana peels. desc: An extremely corrosive chemical substance. The slightest touch of it will melt off most masks and headgear, and it deals extreme damage to anyone who comes directly into contact with it. Spraying it on other items will usually melt them too, which does make it useful if the clown has covered the entire hallway in banana peels.
physicalDesc: strong-smelling
color: "#a1000b" color: "#a1000b"
boilingPoint: 78.2 # This isn't a real chemical... boilingPoint: 78.2 # This isn't a real chemical...
meltingPoint: -19.4 meltingPoint: -19.4
@@ -102,7 +114,8 @@
id: chem.SpaceCleaner id: chem.SpaceCleaner
name: space cleaner name: space cleaner
desc: This is able to clean almost all surfaces of almost anything that may dirty them. The janitor is likely to appreciate refills. desc: This is able to clean almost all surfaces of almost anything that may dirty them. The janitor is likely to appreciate refills.
color: "#215263" physicalDesc: lemony fresh
color: "#c8ff69"
boilingPoint: 147.0 # Made this up, loosely based on bleach boilingPoint: 147.0 # Made this up, loosely based on bleach
meltingPoint: -11.0 meltingPoint: -11.0
@@ -110,6 +123,7 @@
id: chem.SpaceLube id: chem.SpaceLube
name: space lube name: space lube
desc: Space Lube is a high performance lubricant intended for maintenance of extremely complex mechanical equipment (and certainly not used to make people slip). desc: Space Lube is a high performance lubricant intended for maintenance of extremely complex mechanical equipment (and certainly not used to make people slip).
physicalDesc: shiny
color: "#77b58e" color: "#77b58e"
boilingPoint: 290.0 # Glycerin boilingPoint: 290.0 # Glycerin
meltingPoint: 18.2 meltingPoint: 18.2
@@ -118,6 +132,7 @@
id: chem.TableSalt id: chem.TableSalt
name: table salt name: table salt
desc: Commonly known as salt, Sodium Chloride is often used to season food or kill borers instantly. desc: Commonly known as salt, Sodium Chloride is often used to season food or kill borers instantly.
physicalDesc: grainy
color: "#a1000b" color: "#a1000b"
boilingPoint: 1465.0 boilingPoint: 1465.0
meltingPoint: 800.7 meltingPoint: 800.7
@@ -126,7 +141,8 @@
id: chem.Thermite id: chem.Thermite
name: thermite name: thermite
desc: A mixture that becomes extremely hot when ignited, and which can burn straight through walls when applied and ignited. It'll slowly inflict burn damage to anybody dumb enough to ingest it, but can't be ignited inside inside said dumb person. desc: A mixture that becomes extremely hot when ignited, and which can burn straight through walls when applied and ignited. It'll slowly inflict burn damage to anybody dumb enough to ingest it, but can't be ignited inside inside said dumb person.
color: "#77b58e" physicalDesc: grainy
color: "#757245"
boilingPoint: 2977.0 # Aluminum oxide boilingPoint: 2977.0 # Aluminum oxide
meltingPoint: 2030.0 meltingPoint: 2030.0
@@ -134,7 +150,8 @@
id: chem.UnstableMutagen id: chem.UnstableMutagen
name: unstable mutagen name: unstable mutagen
desc: Causes mutations when injected into living people or plants. High doses may be lethal, especially in humans. desc: Causes mutations when injected into living people or plants. High doses may be lethal, especially in humans.
color: "#77b58e" physicalDesc: glowing
color: "#00ff5f"
boilingPoint: 340282300000000000000000000000000000000 # Ethidium bromide, which doesn't boil. boilingPoint: 340282300000000000000000000000000000000 # Ethidium bromide, which doesn't boil.
meltingPoint: 261.0 meltingPoint: 261.0
@@ -142,6 +159,7 @@
id: chem.WeldingFuel id: chem.WeldingFuel
name: welding fuel name: welding fuel
desc: Used by welders to weld. desc: Used by welders to weld.
physicalDesc: oily
color: "#a76b1c" color: "#a76b1c"
boilingPoint: -84.7 # Acetylene. Close enough. boilingPoint: -84.7 # Acetylene. Close enough.
meltingPoint: -80.7 meltingPoint: -80.7

View File

@@ -2,6 +2,7 @@
id: chem.Whiskey id: chem.Whiskey
name: whiskey name: whiskey
desc: An alcoholic beverage made from fermented grain mash desc: An alcoholic beverage made from fermented grain mash
physicalDesc: strong-smelling
color: "#664300" color: "#664300"
spritePath: whiskeyglass.rsi spritePath: whiskeyglass.rsi
@@ -9,13 +10,15 @@
id: chem.Ale id: chem.Ale
name: ale name: ale
desc: A type of beer brewed using a warm fermentation method, resulting in a sweet, full-bodied and fruity taste. desc: A type of beer brewed using a warm fermentation method, resulting in a sweet, full-bodied and fruity taste.
color: "#664300" physicalDesc: bubbly
color: "#663100"
spritePath: aleglass.rsi spritePath: aleglass.rsi
- type: reagent - type: reagent
id: chem.Wine id: chem.Wine
name: wine name: wine
desc: An alcoholic drink made from fermented grapes desc: An alcoholic drink made from fermented grapes
physicalDesc: translucent
color: "#7E4043" color: "#7E4043"
spritePath: wineglass.rsi spritePath: wineglass.rsi
@@ -23,19 +26,36 @@
id: chem.Beer id: chem.Beer
name: beer name: beer
desc: A cold pint of pale lager. desc: A cold pint of pale lager.
color: "#664300" physicalDesc: bubbly
color: "#cfa85f"
spritePath: beerglass.rsi spritePath: beerglass.rsi
- type: reagent - type: reagent
id: chem.Vodka id: chem.Vodka
name: vodka name: vodka
desc: The glass contain wodka. Xynta. desc: The glass contain wodka. Xynta.
color: "#664300" physicalDesc: strong-smelling
color: "#d1d1d155"
- type: reagent
id: chem.Moonshine
name: moonshine
desc: Artisanal homemade liquor. What could go wrong?
physicalDesc: strong-smelling
color: "#d1d7d155"
- type: reagent
id: chem.Tequila
name: tequila
desc: This stuff will get you fucked up.
physicalDesc: strong-smelling
color: "#d7d1d155"
- type: reagent - type: reagent
id: chem.Kahlua id: chem.Kahlua
name: kahlua name: kahlua
desc: A widely known, Mexican coffee-flavoured liqueur. In production since 1936! desc: A widely known, Mexican coffee-flavoured liqueur. In production since 1936!
physicalDesc: cloudy
color: "#664300" color: "#664300"
spritePath: kahluaglass.rsi spritePath: kahluaglass.rsi
@@ -43,6 +63,7 @@
id: chem.Cognac id: chem.Cognac
name: cognac name: cognac
desc: A sweet and strongly alcoholic drink, twice distilled and left to mature for several years. Classy as fornication. desc: A sweet and strongly alcoholic drink, twice distilled and left to mature for several years. Classy as fornication.
physicalDesc: strong-smelling
color: "#AB3C05" color: "#AB3C05"
spritePath: cognacglass.rsi spritePath: cognacglass.rsi
@@ -50,6 +71,7 @@
id: chem.ManlyDorf id: chem.ManlyDorf
name: manly dorf name: manly dorf
desc: A dwarfy concoction made from ale and beer. Intended for stout dwarves only. desc: A dwarfy concoction made from ale and beer. Intended for stout dwarves only.
physicalDesc: bubbly
color: "#664300" color: "#664300"
spritePath: manlydorfglass.rsi spritePath: manlydorfglass.rsi
@@ -57,6 +79,7 @@
id: chem.CubaLibre id: chem.CubaLibre
name: cuba libre name: cuba libre
desc: A classic mix of rum and cola. desc: A classic mix of rum and cola.
physicalDesc: bubbly
color: "#3E1B00" color: "#3E1B00"
spritePath: cubalibreglass.rsi spritePath: cubalibreglass.rsi
@@ -64,6 +87,7 @@
id: chem.IrishCarBomb id: chem.IrishCarBomb
name: irish car bomb name: irish car bomb
desc: A troubling mixture of irish cream and ale. desc: A troubling mixture of irish cream and ale.
physicalDesc: bubbly
color: "#2E6671" color: "#2E6671"
spritePath: irishcarbomb.rsi spritePath: irishcarbomb.rsi
@@ -71,6 +95,7 @@
id: chem.IrishCoffee id: chem.IrishCoffee
name: irish coffee name: irish coffee
desc: Coffee served with irish cream. Regular cream just isn't the same! desc: Coffee served with irish cream. Regular cream just isn't the same!
physicalDesc: cloudy
color: "#664300" color: "#664300"
spritePath: irishcoffeeglass.rsi spritePath: irishcoffeeglass.rsi
@@ -78,6 +103,7 @@
id: chem.IrishCream id: chem.IrishCream
name: irish cream name: irish cream
desc: Whiskey-imbued cream. What else could you expect from the Irish. desc: Whiskey-imbued cream. What else could you expect from the Irish.
physicalDesc: creamy
color: "#664300" color: "#664300"
spritePath: irishcreamglass.rsi spritePath: irishcreamglass.rsi
@@ -85,6 +111,7 @@
id: chem.B52 id: chem.B52
name: b-52 name: b-52
desc: Coffee, irish cream, and cognac. You will get bombed. desc: Coffee, irish cream, and cognac. You will get bombed.
physicalDesc: bubbly
color: "#664300" color: "#664300"
spritePath: b52glass.rsi spritePath: b52glass.rsi
@@ -92,6 +119,7 @@
id: chem.AtomicBomb id: chem.AtomicBomb
name: atomic bomb name: atomic bomb
desc: Nuclear proliferation never tasted so good. desc: Nuclear proliferation never tasted so good.
physicalDesc: cloudy
color: "#666300" color: "#666300"
spritePath: atomicbombglass.rsi spritePath: atomicbombglass.rsi
@@ -99,6 +127,7 @@
id: chem.WhiskeyCola id: chem.WhiskeyCola
name: whiskey cola name: whiskey cola
desc: An innocent-looking mixture of cola and whiskey. Delicious. desc: An innocent-looking mixture of cola and whiskey. Delicious.
physicalDesc: bubbly
color: "#3E1B00" color: "#3E1B00"
spritePath: whiskeycolaglass.rsi spritePath: whiskeycolaglass.rsi
@@ -106,22 +135,24 @@
id: chem.SyndicateBomb id: chem.SyndicateBomb
name: syndicate bomb name: syndicate bomb
desc: Somebody set us up the bomb! desc: Somebody set us up the bomb!
color: "#2E6671" physicalDesc: opaque
color: "#2E6660"
spritePath: syndicatebomb.rsi spritePath: syndicatebomb.rsi
- type: reagent - type: reagent
id: chem.Antifreeze id: chem.Antifreeze
name: antifreeze name: antifreeze
desc: The ultimate refreshment. desc: The ultimate refreshment.
color: "#664300" physicalDesc: translucent
color: "#ff7d63"
spritePath: antifreeze.rsi spritePath: antifreeze.rsi
- type: reagent - type: reagent
id: chem.Cola id: chem.Cola
name: cola name: cola
desc: A sweet, carbonated soft drink. Caffeine free. desc: A sweet, carbonated soft drink. Caffeine free.
color: "#100800" physicalDesc: fizzy
color: "#422912"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
rate: 1 rate: 1
@@ -130,6 +161,7 @@
id: chem.Coffee id: chem.Coffee
name: coffee name: coffee
desc: A drink made from brewed coffee beans. Contains a moderate amount of caffeine. desc: A drink made from brewed coffee beans. Contains a moderate amount of caffeine.
physicalDesc: aromatic
color: "#664300" color: "#664300"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
@@ -139,7 +171,8 @@
id: chem.Tea id: chem.Tea
name: tea name: tea
desc: A made by boiling leaves of the tea tree, Camellia sinensis. desc: A made by boiling leaves of the tea tree, Camellia sinensis.
color: "#101000" physicalDesc: aromatic
color: "#8a5a3a"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
rate: 1 rate: 1
@@ -148,6 +181,7 @@
id: chem.Cream id: chem.Cream
name: cream name: cream
desc: The fatty, still liquid part of milk. Why don't you mix this with sum scotch, eh? desc: The fatty, still liquid part of milk. Why don't you mix this with sum scotch, eh?
physicalDesc: creamy
color: "#DFD7AF" color: "#DFD7AF"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
@@ -157,16 +191,48 @@
id: chem.Milk id: chem.Milk
name: milk name: milk
desc: An opaque white liquid produced by the mammary glands of mammals. desc: An opaque white liquid produced by the mammary glands of mammals.
physicalDesc: opaque
color: "#DFDFDF" color: "#DFDFDF"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
rate: 1 rate: 1
- type: reagent
id: chem.SpoiledMilk
name: spoiled milk
desc: This milk has gone rancid.
physicalDesc: putrid
color: "#faffba"
metabolism:
- !type:DefaultDrink
rate: 1
- type: reagent
id: chem.CreamyDelight
name: creamy delight
desc: A combination of cream, wine and moonshine. Why would you do this?
physicalDesc: foul
color: "#a6969a"
metabolism:
- !type:DefaultDrink
rate: 1
- type: reagent - type: reagent
id: chem.Lean id: chem.Lean
name: lean name: lean
desc: Turn up for days desc: Turn up for days.
physicalDesc: bubbly
color: "#9400D3" color: "#9400D3"
metabolism: metabolism:
- !type:DefaultDrink - !type:DefaultDrink
rate: 1 rate: 1
- type: reagent
id: chem.LeanShine
name: leanshine
desc: Lean mixed with moonshine. Turn up for months.
physicalDesc: bubbly
color: "#9d5fb8"
metabolism:
- !type:DefaultDrink
rate: 1

View File

@@ -2,6 +2,7 @@
id: chem.H id: chem.H
name: hydrogen name: hydrogen
desc: A light, flammable gas. desc: A light, flammable gas.
physicalDesc: gaseous
color: "#808080" color: "#808080"
boilingPoint: -253.0 boilingPoint: -253.0
meltingPoint: -259.2 meltingPoint: -259.2
@@ -10,6 +11,7 @@
id: chem.O id: chem.O
name: oxygen name: oxygen
desc: An oxidizing, colorless gas. desc: An oxidizing, colorless gas.
physicalDesc: gaseous
color: "#808080" color: "#808080"
boilingPoint: -183.0 boilingPoint: -183.0
meltingPoint: -218.4 meltingPoint: -218.4
@@ -19,7 +21,8 @@
id: chem.S id: chem.S
name: sulfur name: sulfur
desc: A yellow, crystalline solid. desc: A yellow, crystalline solid.
color: "#FFFACD" physicalDesc: powdery
color: "#fff385"
boilingPoint: 445.0 boilingPoint: 445.0
meltingPoint: 120.0 meltingPoint: 120.0
@@ -27,6 +30,7 @@
id: chem.C id: chem.C
name: carbon name: carbon
desc: A black, crystalline solid. desc: A black, crystalline solid.
physicalDesc: crystalline
color: "#22282b" color: "#22282b"
boilingPoint: 4200.0 boilingPoint: 4200.0
meltingPoint: 3550.0 meltingPoint: 3550.0
@@ -34,7 +38,8 @@
- type: reagent - type: reagent
id: chem.Al id: chem.Al
name: aluminum name: aluminum
desc: A silvery-white, soft, non-magnetic, and ductile metal. desc: A silver, soft, non-magnetic, and ductile metal.
physicalDesc: metallic
color: "#848789" color: "#848789"
boilingPoint: 2327.0 boilingPoint: 2327.0
meltingPoint: 660.0 meltingPoint: 660.0
@@ -43,6 +48,7 @@
id: chem.Cu id: chem.Cu
name: copper name: copper
desc: A soft, malleable, and ductile metal with very high thermal and electrical conductivity. desc: A soft, malleable, and ductile metal with very high thermal and electrical conductivity.
physicalDesc: metallic
color: "#b05b3c" color: "#b05b3c"
boilingPoint: 2595.0 boilingPoint: 2595.0
meltingPoint: 1083.0 meltingPoint: 1083.0
@@ -51,6 +57,7 @@
id: chem.N id: chem.N
name: nitrogen name: nitrogen
desc: A colorless, odorless unreactive gas. Highly stable. desc: A colorless, odorless unreactive gas. Highly stable.
physicalDesc: gaseous
color: "#808080" color: "#808080"
boilingPoint: -195.8 boilingPoint: -195.8
meltingPoint: -210.0 meltingPoint: -210.0
@@ -59,6 +66,7 @@
id: chem.Fe id: chem.Fe
name: iron name: iron
desc: A silvery-grey metal which forms iron oxides (rust) with contact with air. Commonly alloyed with other elements to create alloys such as steel. desc: A silvery-grey metal which forms iron oxides (rust) with contact with air. Commonly alloyed with other elements to create alloys such as steel.
physicalDesc: metallic
color: "#434b4d" color: "#434b4d"
boilingPoint: 2862.0 boilingPoint: 2862.0
meltingPoint: 1538.0 meltingPoint: 1538.0
@@ -67,6 +75,7 @@
id: chem.F id: chem.F
name: fluorine name: fluorine
desc: A highly toxic pale yellow gas. Extremely reactive. desc: A highly toxic pale yellow gas. Extremely reactive.
physicalDesc: gaseous
color: "#808080" color: "#808080"
boilingPoint: -188.11 boilingPoint: -188.11
meltingPoint: -219.67 meltingPoint: -219.67
@@ -75,6 +84,7 @@
id: chem.Si id: chem.Si
name: silicon name: silicon
desc: A hard and brittle crystalline solid with a blue-grey color. desc: A hard and brittle crystalline solid with a blue-grey color.
physicalDesc: crystalline
color: "#364266" color: "#364266"
boilingPoint: 3265.0 boilingPoint: 3265.0
meltingPoint: 1414.0 meltingPoint: 1414.0
@@ -83,6 +93,7 @@
id: chem.Cl id: chem.Cl
name: chlorine name: chlorine
desc: A yellow-green gas which is toxic to humans. desc: A yellow-green gas which is toxic to humans.
physicalDesc: gaseous
color: "#a2ff00" color: "#a2ff00"
meltingPoint: -101.5 meltingPoint: -101.5
boilingPoint: -34.04 boilingPoint: -34.04
@@ -91,6 +102,7 @@
id: chem.Li id: chem.Li
name: lithium name: lithium
desc: A soft, silvery-white alkali metal. It is highly reactive, and ignites if it makes contact with water. desc: A soft, silvery-white alkali metal. It is highly reactive, and ignites if it makes contact with water.
physicalDesc: shiny
color: "#c6c8cc" color: "#c6c8cc"
meltingPoint: 180.5 meltingPoint: 180.5
boilingPoint: 1330.0 boilingPoint: 1330.0
@@ -99,6 +111,7 @@
id: chem.Hg id: chem.Hg
name: mercury name: mercury
desc: A silver metal which is liquid at room temperature. It is highly toxic to humans. desc: A silver metal which is liquid at room temperature. It is highly toxic to humans.
physicalDesc: shiny
color: "#929296" color: "#929296"
meltingPoint: -38.83 meltingPoint: -38.83
boilingPoint: 356.73 boilingPoint: 356.73
@@ -107,14 +120,16 @@
id: chem.P id: chem.P
name: phosphorus name: phosphorus
desc: A reactive metal used in pyrotechnics and weapons. desc: A reactive metal used in pyrotechnics and weapons.
color: "#803330" physicalDesc: powdery
color: "#ede4e4"
meltingPoint: 44.2 meltingPoint: 44.2
boilingPoint: 280.5 boilingPoint: 280.5
- type: reagent - type: reagent
id: chem.K id: chem.K
name: potassium name: potassium
desc: A soft, silvery-white metal. Even more reactive than lithium. desc: A soft, shiny grey metal. Even more reactive than lithium.
physicalDesc: shiny
color: "#c6c8cc" color: "#c6c8cc"
meltingPoint: 65.5 meltingPoint: 65.5
boilingPoint: 759.0 boilingPoint: 759.0
@@ -123,6 +138,7 @@
id: chem.Ra id: chem.Ra
name: radium name: radium
desc: A radioactive metal, silvery-white in it's pure form. It glows due to it's radioactivity and is highly toxic. desc: A radioactive metal, silvery-white in it's pure form. It glows due to it's radioactivity and is highly toxic.
physicalDesc: glowing
color: "#00ff04" color: "#00ff04"
meltingPoint: 700.0 meltingPoint: 700.0
boilingPoint: 1737.0 boilingPoint: 1737.0
@@ -131,6 +147,7 @@
id: chem.Na id: chem.Na
name: sodium name: sodium
desc: A silvery-white alkali metal. Highly reactive in it's pure form. desc: A silvery-white alkali metal. Highly reactive in it's pure form.
physicalDesc: metallic
color: "#c6c8cc" color: "#c6c8cc"
meltingPoint: 97.8 meltingPoint: 97.8
boilingPoint: 883.0 boilingPoint: 883.0
@@ -138,7 +155,8 @@
- type: reagent - type: reagent
id: chem.U id: chem.U
name: uranium name: uranium
desc: A silvery-white metallic chemical element in the actinide series, weakly radioactive. desc: A grey metallic chemical element in the actinide series, weakly radioactive.
color: "#00ff06" physicalDesc: metallic
color: "#8fa191"
meltingPoint: 1133.0 meltingPoint: 1133.0
boilingPoint: 4131.0 boilingPoint: 4131.0

View File

@@ -2,6 +2,7 @@
id: chem.Flour id: chem.Flour
name: flour name: flour
desc: Used for baking. desc: Used for baking.
physicalDesc: powdery
color: "#FFFFFF" color: "#FFFFFF"
metabolism: metabolism:
- !type:DefaultFood - !type:DefaultFood

View File

@@ -2,245 +2,285 @@
id: chem.Alkycosine id: chem.Alkycosine
name: alkycosine name: alkycosine
desc: Lessens the damage to neurological tissue. More effective at treating brain damage than alkysine and also a fairly effective painkiller as well. Caution is needed in its creation to avoid mixing bleach and the chlorine needed to make alkysine. desc: Lessens the damage to neurological tissue. More effective at treating brain damage than alkysine and also a fairly effective painkiller as well. Caution is needed in its creation to avoid mixing bleach and the chlorine needed to make alkysine.
physicalDesc: strong-smelling
color: "#9e232b" color: "#9e232b"
- type: reagent - type: reagent
id: chem.Alkysine id: chem.Alkysine
name: alkysine name: alkysine
desc: Lessens the damage to neurological tissue, effective even after catastrophic injury. Used for treating brain damage and also a fairly effective painkiller. desc: Lessens the damage to neurological tissue, effective even after catastrophic injury. Used for treating brain damage and also a fairly effective painkiller.
color: "#a1000b" physicalDesc: oily
color: "#ff8c00"
- type: reagent - type: reagent
id: chem.Dylovene id: chem.Dylovene
name: dylovene name: dylovene
desc: A broad-spectrum anti-toxin, which treats toxin damage in the blood stream. Overdosing will cause vomiting, dizzyness and pain. desc: A broad-spectrum anti-toxin, which treats toxin damage in the blood stream. Overdosing will cause vomiting, dizzyness and pain.
physicalDesc: translucent
color: "#3a1d8a" color: "#3a1d8a"
- type: reagent - type: reagent
id: chem.Arithrazine id: chem.Arithrazine
name: arithrazine name: arithrazine
desc: A slightly unstable medication used for the most extreme any serious case of radiation poisoning. Lowers radiation level at over twice the rate Hyronalin does and will heal toxin damage at the same time. Deals very minor brute damage to the patient over time, but the patient's body will typically out-regenerate it easily. desc: A slightly unstable medication used for the most extreme any serious case of radiation poisoning. Lowers radiation level at over twice the rate Hyronalin does and will heal toxin damage at the same time. Deals very minor brute damage to the patient over time, but the patient's body will typically out-regenerate it easily.
physicalDesc: cloudy
color: "#bd5902" color: "#bd5902"
- type: reagent - type: reagent
id: chem.Bicaridine id: chem.Bicaridine
name: bicaridine name: bicaridine
desc: An analgesic which is highly effective at treating brute damage. It is useful for stabilizing people who have been severely beaten, as well as treating less life-threatening injuries. In the case of bleeding (internal or external), bicaridine will slow down the bleeding heavily. If the dosage exceeds the overdose limit, it'll stop it outright. desc: An analgesic which is highly effective at treating brute damage. It is useful for stabilizing people who have been severely beaten, as well as treating less life-threatening injuries. In the case of bleeding (internal or external), bicaridine will slow down the bleeding heavily. If the dosage exceeds the overdose limit, it'll stop it outright.
physicalDesc: opaque
color: "#ffaa00" color: "#ffaa00"
- type: reagent - type: reagent
id: chem.Cryoxadone id: chem.Cryoxadone
name: cryoxadone name: cryoxadone
desc: Required for the proper function of cryogenics. Heals all standard types of damage very swiftly, but only works in temperatures under 170K (usually this means cryo cells). Can also slowly heal clone damage, such as caused by cloning or Slimes. desc: Required for the proper function of cryogenics. Heals all standard types of damage very swiftly, but only works in temperatures under 170K (usually this means cryo cells). Can also slowly heal clone damage, such as caused by cloning or Slimes.
physicalDesc: fizzy
color: "#0091ff" color: "#0091ff"
- type: reagent - type: reagent
id: chem.Clonexadone id: chem.Clonexadone
name: clonexadone name: clonexadone
desc: Heals standard damage in the same as Cryoxadone, with the same temperature requirement. Significantly more effective than the former at treating clone damage, although both can be used simultaneously. Best used in cryo cells. desc: Heals standard damage in the same as Cryoxadone, with the same temperature requirement. Significantly more effective than the former at treating cellular damage, although both can be used simultaneously. Best used in cryo cells.
color: "#0091ff" physicalDesc: bubbly
color: "#0666ff"
- type: reagent - type: reagent
id: chem.Citalopram id: chem.Citalopram
name: citalopram name: citalopram
desc: Prevents hallucination slightly. desc: Prevents hallucination slightly.
physicalDesc: cloudy
color: "#21693c" color: "#21693c"
- type: reagent - type: reagent
id: chem.Dermaline id: chem.Dermaline
name: dermaline name: dermaline
desc: An advanced chemical that is more effective at treating burns damage than Kelotane. desc: An advanced chemical that is more effective at treating burn damage than Kelotane.
physicalDesc: translucent
color: "#215263" color: "#215263"
- type: reagent - type: reagent
id: chem.Dexalin id: chem.Dexalin
name: dexalin name: dexalin
desc: Used for treating oxygen deprivation. In most cases where it is likely to be needed, the strength of Dexalin Plus will probably be more useful (Results in 1 unit instead of 2). desc: Used for treating oxygen deprivation. In most cases where it is likely to be needed, the strength of Dexalin Plus will probably be more useful (Results in 1 unit instead of 2).
physicalDesc: opaque
color: "#0041a8" color: "#0041a8"
- type: reagent - type: reagent
id: chem.DexalinPlus id: chem.DexalinPlus
name: dexalin plus name: dexalin plus
desc: Used in treatment of extreme cases of oxygen deprivation. Even a single unit immediately counters all oxygen loss, which is hugely useful in many circumstances. Any dose beyond this will continue to counter oxygen loss until it is metabolized, essentially removing the need to breathe. desc: Used in treatment of extreme cases of oxygen deprivation. Even a single unit immediately counters all oxygen loss, which is hugely useful in many circumstances. Any dose beyond this will continue to counter oxygen loss until it is metabolized, essentially removing the need to breathe.
color: "#297691" physicalDesc: cloudy
color: "#4da0bd"
- type: reagent - type: reagent
id: chem.Ethylredoxrazine id: chem.Ethylredoxrazine
name: ethylredoxrazine name: ethylredoxrazine
desc: Neutralises the effects of alcohol in the blood stream. Though it is commonly needed, it is rarely requested. desc: Neutralises the effects of alcohol in the blood stream. Though it is commonly needed, it is rarely requested.
physicalDesc: opaque
color: "#2d5708" color: "#2d5708"
- type: reagent - type: reagent
id: chem.Hyperzine id: chem.Hyperzine
name: hyperzine name: hyperzine
desc: A highly effective, long lasting muscle stimulant. It allows greater freedom of movement in bulky clothing although it has the side effect of causing some twitching. Dangerous in higher doses. desc: A highly effective, long lasting muscle stimulant. It allows greater freedom of movement in bulky clothing although it has the side effect of causing some twitching. Dangerous in higher doses.
physicalDesc: translucent
color: "#17bd61" color: "#17bd61"
- type: reagent - type: reagent
id: chem.Hyronalin id: chem.Hyronalin
name: hyronalin name: hyronalin
desc: A weak treatment for radiation damage. Considered to be useful mainly for genetic modification, where it reduces radiation levels, and thus the chance of genetic mutations. Largely outclassed by Arithrazine. desc: A weak treatment for radiation damage. Considered to be useful mainly for genetic modification, where it reduces radiation levels, and thus the chance of genetic mutations. Largely outclassed by Arithrazine.
color: "#17ac61" physicalDesc: cloudy
color: "#4cb580"
- type: reagent - type: reagent
id: chem.Imidazoline id: chem.Imidazoline
name: imidazoline name: imidazoline
desc: Effective in treating eye trauma. It heals damage caused by physical or chemical trauma, though it is ineffective in treating genetic defects in the eyes. desc: Effective in treating eye trauma. It heals damage caused by physical or chemical trauma, though it is ineffective in treating genetic defects in the eyes.
physicalDesc: pungent
color: "#f7ef00" color: "#f7ef00"
- type: reagent - type: reagent
id: chem.Inacusiate id: chem.Inacusiate
name: inacusiate name: inacusiate
desc: You only need 1u for Inacusiate work. Cures deafness instantly. Useful after an explosion. desc: You only need 1u for Inacusiate to be effective. Cures deafness instantly. Useful after an explosion.
color: "#f7ef00" physicalDesc: pungent
color: "#c4c04b"
- type: reagent - type: reagent
id: chem.Inaprovaline id: chem.Inaprovaline
name: inaprovaline name: inaprovaline
desc: Inaprovaline is a synaptic stimulant and cardiostimulant. Commonly used to stabilize patients- it stops oxygen loss when the patient is in critical health. It'll also slow down bleeding (internal or external) by half while in the body. Acts as a decent painkiller. desc: Inaprovaline is a synaptic stimulant and cardiostimulant. Commonly used to stabilize patients- it stops oxygen loss when the patient is in critical health. It'll also slow down bleeding (internal or external) by half while in the body. Acts as a decent painkiller.
color: "#73103b" physicalDesc: opaque
color: "#731024"
- type: reagent - type: reagent
id: chem.Kelotane id: chem.Kelotane
name: kelotane name: kelotane
desc: Treats burn damage and prevents infection. desc: Treats burn damage and prevents infection.
physicalDesc: strong-smelling
color: "#bf3d19" color: "#bf3d19"
- type: reagent - type: reagent
id: chem.Leporazine id: chem.Leporazine
name: leporazine name: leporazine
desc: This keeps a patient's body temperature stable. High doses can allow short periods of unprotected EVA, but prevents use of the cryogenics tubes. desc: This keeps a patient's body temperature stable. High doses can allow short periods of unprotected EVA, but prevents use of the cryogenics tubes.
physicalDesc: pungent
color: "#ff7db5" color: "#ff7db5"
- type: reagent - type: reagent
id: chem.Methylin id: chem.Methylin
name: methylin name: methylin
desc: An intelligence enhancer, also used in the treatment of attention deficit hyperactivity disorder. Also known as Ritalin. Allows monkeys (not diona nymphs) to understand human speech and improves their dexterity as long as they have some in their system. Causes toxin and brain damage in higher doses. desc: An intelligence enhancer, also used in the treatment of attention deficit hyperactivity disorder. Also known as Ritalin. Allows monkeys (not diona nymphs) to understand human speech and improves their dexterity as long as they have some in their system. Causes toxin and brain damage in higher doses.
physicalDesc: acrid
color: "#a700c4" color: "#a700c4"
- type: reagent - type: reagent
id: chem.Oxycodone id: chem.Oxycodone
name: oxycodone name: oxycodone
desc: A very effective painkiller, about 250% as strong as Tramadol. desc: A very effective painkiller, about 250% as strong as Tramadol.
physicalDesc: acrid
color: "#c4a300" color: "#c4a300"
- type: reagent - type: reagent
id: chem.Phalanximine id: chem.Phalanximine
name: phalanximine name: phalanximine
desc: Used in the treatment of cancer, is as effective as Anti-Toxin. Causes moderate radiation and hair loss. desc: Used in the treatment of cancer, is as effective as Anti-Toxin. Causes moderate radiation and hair loss.
physicalDesc: acrid
color: "#c8ff75" color: "#c8ff75"
- type: reagent - type: reagent
id: chem.Paroxetine id: chem.Paroxetine
name: paroxetine name: paroxetine
desc: Prevents hallucination, but has a 10% chance of causing intense hallucinations. desc: Prevents hallucination, but has a 10% chance of causing intense hallucinations.
color: "#c8ff75" physicalDesc: acrid
color: "#fffbad"
- type: reagent - type: reagent
id: chem.Ryetalyn id: chem.Ryetalyn
name: ryetalyn name: ryetalyn
desc: You only need 1u for Ryetalin to work. Deactivates genetic defects and powers, restoring a patient to an ideal state. May be useful if genetics is unable to function properly. Deactivated effects return if the patient's genes are modified again. desc: You only need 1u for Ryetalin to work. Deactivates genetic defects and powers, restoring a patient to an ideal state. May be useful if genetics is unable to function properly. Deactivated effects return if the patient's genes are modified again.
physicalDesc: cloudy
color: "#532fd4" color: "#532fd4"
- type: reagent - type: reagent
id: chem.Spaceacillin id: chem.Spaceacillin
name: spaceacillin name: spaceacillin
desc: A theta-lactam antibiotic. A common and very useful medicine, effective against many diseases likely to be encountered in space. Slows progression of diseases. desc: A theta-lactam antibiotic. A common and very useful medicine, effective against many diseases likely to be encountered in space. Slows progression of diseases.
color: "#7f2fd4" physicalDesc: opaque
color: "#9942f5"
- type: reagent - type: reagent
id: chem.Synaptizine id: chem.Synaptizine
name: synaptizine name: synaptizine
desc: Toxic, but treats hallucinations, drowsiness & halves the duration of paralysis, stuns and knockdowns. It is metabolized very slowly. One unit is enough to treat hallucinations; two units is deadly. desc: Toxic, but treats hallucinations, drowsiness & halves the duration of paralysis, stuns and knockdowns. It is metabolized very slowly. One unit is enough to treat hallucinations; two units is deadly.
physicalDesc: pungent
color: "#d49a2f" color: "#d49a2f"
- type: reagent - type: reagent
id: chem.Tramadol id: chem.Tramadol
name: tramadol name: tramadol
desc: A simple, yet effective painkiller. Very effective for patients in shock. desc: A simple, yet effective painkiller. Very effective for patients in shock.
physicalDesc: strong-smelling
color: "#2f6ed4" color: "#2f6ed4"
- type: reagent - type: reagent
id: chem.Tricordrazine id: chem.Tricordrazine
name: tricordrazine name: tricordrazine
desc: A wide-spectrum stimulant, originally derived from Cordrazine. Is capable of healing all four main damage types simultaneously, however it only heals at half the rate of conventional healing chemicals. Because of its low potency, it's best used as a supplement to other medicines. desc: A wide-spectrum stimulant, originally derived from Cordrazine. Is capable of healing all four main damage types simultaneously, however it only heals at half the rate of conventional healing chemicals. Because of its low potency, it's best used as a supplement to other medicines.
physicalDesc: opaque
color: "#00e5ff" color: "#00e5ff"
- type: reagent - type: reagent
id: chem.Vaccine id: chem.Vaccine
name: vaccine name: vaccine
desc: Introduces antigens to the body, allowing the immune system to produce enough antibodies to combat present or future infections. Is blank by default, vaccine carrying antigen is produced at a centrifuge. Each unit raises the associated antibody concentration by 20% so at most 5 units are needed to cure the strongest diseases. desc: Introduces antigens to the body, allowing the immune system to produce enough antibodies to combat present or future infections. Is blank by default, vaccine carrying antigen is produced at a centrifuge. Each unit raises the associated antibody concentration by 20% so at most 5 units are needed to cure the strongest diseases.
color: "#ba0b60" physicalDesc: translucent
color: "#ffc9f6"
- type: reagent - type: reagent
id: chem.Albuterol id: chem.Albuterol
name: albuterol name: albuterol
desc: A bronchodilator that relaxes muscles in the airways and increases air flow to the lungs. It'll remove mucus from your system as long as it's inside your body. Only useful to people with the Asthma disability. desc: A bronchodilator that relaxes muscles in the airways and increases air flow to the lungs. It'll remove mucus from your system as long as it's inside your body. Only useful to people with the Asthma disability.
color: "#00e5ff" physicalDesc: cloudy
color: "#00b89f"
- type: reagent - type: reagent
id: chem.ChloralHydrate id: chem.ChloralHydrate
name: chloral hydrate name: chloral hydrate
desc: A powerful sedative which causes death in doses upwards of 16.2 units. Sends the patient to sleep almost instantly. desc: A powerful sedative which causes death in doses upwards of 16.2 units. Sends the patient to sleep almost instantly.
color: "#00e5ff" physicalDesc: acrid
color: "#18c9b1"
- type: reagent - type: reagent
id: chem.Creatine id: chem.Creatine
name: creatine name: creatine
desc: A muscle-building drug that grants the user enormous strength, before their muscles seize and tear their own body to shreds. In practical terms, 1-25 units just causes toxin damage, and 26 units turns you into a hulk with all its associated benefits with the side effect of taking a little toxin damage over time. You'll remain as a hulk until it's all metabolized, at which point you'll take 200 brute damage and gib. With the correct administration, it can be the most potent drug there is, but even at the best of times it is best considered a double-edged sword. desc: A muscle-building drug that grants the user enormous strength, before their muscles seize and tear their own body to shreds. In practical terms, 1-25 units just causes toxin damage, and 26 units turns you into a hulk with all its associated benefits with the side effect of taking a little toxin damage over time. You'll remain as a hulk until it's all metabolized, at which point you'll take 200 brute damage and gib. With the correct administration, it can be the most potent drug there is, but even at the best of times it is best considered a double-edged sword.
physicalDesc: cloudy
color: "#a1000b" color: "#a1000b"
- type: reagent - type: reagent
id: chem.Cryptobiolin id: chem.Cryptobiolin
name: cryptobiolin name: cryptobiolin
desc: Causes confusion and dizziness. This is essential to make Spaceacillin. desc: Causes confusion and dizziness. This is essential to make Spaceacillin.
color: "#00e5ff" physicalDesc: fizzy
color: "#081a80"
- type: reagent - type: reagent
id: chem.HeartbreakerToxin id: chem.HeartbreakerToxin
name: heartbreaker toxin name: heartbreaker toxin
desc: A hallucinogenic compound that is illegal under space law. A synthetic drug derived from Mindbreaker toxin, it blocks some neurological signals to the respiratory system which causes choking. desc: A hallucinogenic compound that is illegal under space law. A synthetic drug derived from Mindbreaker toxin, it blocks some neurological signals to the respiratory system which causes choking.
color: "#00e5ff" physicalDesc: strong-smelling
color: "#5f959c"
- type: reagent - type: reagent
id: chem.Impedrezene id: chem.Impedrezene
name: impedrezene name: impedrezene
desc: A narcotic that impedes one's ability by slowing down the higher brain cell functions. Causes massive brain damage. desc: A narcotic that impedes one's ability by slowing down the higher brain cell functions. Causes massive brain damage.
physicalDesc: acrid
color: "#215263" color: "#215263"
- type: reagent - type: reagent
id: chem.Lexorin id: chem.Lexorin
name: lexorin name: lexorin
desc: Temporarily stops respiration and causes tissue damage. Large doses are fatal, and will cause people to pass out very quickly. Dexalin and Dexalin Plus will both remove it, however. desc: Temporarily stops respiration and causes tissue damage. Large doses are fatal, and will cause people to pass out very quickly. Dexalin and Dexalin Plus will both remove it, however.
color: "#a1000b" physicalDesc: pungent
color: "#6b0007"
- type: reagent - type: reagent
id: chem.Lipozine id: chem.Lipozine
name: lipozine name: lipozine
desc: Causes weight loss upon consumption. desc: Causes weight loss upon consumption.
color: "#215263" physicalDesc: oily
color: "#2690b5"
- type: reagent - type: reagent
id: chem.MindbreakerToxin id: chem.MindbreakerToxin
name: mindbreaker toxin name: mindbreaker toxin
desc: A potent hallucinogenic compound that is illegal under space law. Formerly known as LSD. desc: A potent hallucinogenic compound that is illegal under space law. Formerly known as LSD.
physicalDesc: opaque
color: "#77b58e" color: "#77b58e"
- type: reagent - type: reagent
id: chem.Soporific id: chem.Soporific
name: soporific (sleep-toxin) name: soporific (sleep-toxin)
desc: A less powerful sedative that takes a while to work, intended to help insomniacs and patients that are too aggressive to be treated normally. Takes roughly 50 seconds to make the patient fall asleep. Is safe in large quantities. Can be counteracted with Anti-Toxin. desc: A less powerful sedative that takes a while to work, intended to help insomniacs and patients that are too aggressive to be treated normally. Takes roughly 50 seconds to make the patient fall asleep. Is safe in large quantities. Can be counteracted with Anti-Toxin.
physicalDesc: acrid
color: "#215263" color: "#215263"
- type: reagent - type: reagent
id: chem.Sterilizine id: chem.Sterilizine
name: sterilizine name: sterilizine
desc: Helps the patient when used during surgery, may also decontaminate objects and surfaces that bear pathogens. Is currently useless due to infections not being a thing. desc: Helps the patient when used during surgery, may also decontaminate objects and surfaces that bear pathogens. Is currently useless due to infections not being a thing.
color: "#215263" physicalDesc: strong-smelling
color: "#7cad37"
- type: reagent - type: reagent
id: chem.SpaceDrugs id: chem.SpaceDrugs
name: space drugs name: space drugs
desc: An illegal compound which induces a number of effects such as loss of balance and visual artefacts. desc: An illegal compound which induces a number of effects such as loss of balance and visual artefacts.
color: "#a1000b" physicalDesc: syrupy
color: "#63806e"

View File

@@ -100,4 +100,38 @@
chem.Ice: chem.Ice:
amount: 1 amount: 1
products: products:
chem.Antifreeze: 4 chem.Antifreeze: 4
- type: reaction
id: react.Moonshine
reactants:
chem.Vodka:
amount: 1
chem.Tequila:
amount: 1
chem.Whiskey:
amount: 1
products:
chem.Moonshine: 3
- type: reaction
id: react.CreamyDelight
reactants:
chem.Moonshine:
amount: 1
chem.Cream:
amount: 1
chem.Wine:
amount: 1
products:
chem.CreamyDelight: 3
- type: reaction
id: react.LeanShine
reactants:
chem.Lean:
amount: 1
chem.Moonshine:
amount: 1
products:
chem.LeanShine: 2