--- /dev/null
+namespace Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent
+{
+ /// <summary>
+ /// Component that removes an item when a specific solution in it becomes empty.
+ /// </summary>
+ [RegisterComponent]
+ public sealed partial class DeleteOnSolutionEmptyComponent : Component
+ {
+ /// <summary>
+ /// The name of the solution of which to check emptiness
+ /// </summary>
+ [DataField("solution")]
+ public string Solution = string.Empty;
+ }
+}
--- /dev/null
+using Content.Server.Chemistry.Components.DeleteOnSolutionEmptyComponent;
+using Content.Shared.Chemistry.Components.SolutionManager;
+using Content.Shared.Chemistry.EntitySystems;
+
+namespace Content.Server.Chemistry.EntitySystems.DeleteOnSolutionEmptySystem
+{
+ public sealed class DeleteOnSolutionEmptySystem : EntitySystem
+ {
+ [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, ComponentStartup>(OnStartup);
+ SubscribeLocalEvent<DeleteOnSolutionEmptyComponent, SolutionChangedEvent>(OnSolutionChange);
+ }
+
+ public void OnStartup(EntityUid uid, DeleteOnSolutionEmptyComponent component, ComponentStartup args)
+ {
+ CheckSolutions(uid, component);
+ }
+
+ public void OnSolutionChange(EntityUid uid, DeleteOnSolutionEmptyComponent component, SolutionChangedEvent args)
+ {
+ CheckSolutions(uid, component);
+ }
+
+ public void CheckSolutions(EntityUid uid, DeleteOnSolutionEmptyComponent component)
+ {
+ if (!EntityManager.HasComponent<SolutionContainerManagerComponent>(uid))
+ return;
+
+ if (_solutionContainerSystem.TryGetSolution(uid, component.Solution, out var solution))
+ if (solution.Volume <= 0)
+ EntityManager.QueueDeleteEntity(uid);
+ }
+ }
+}
if (!decal.Decal.Cleanable)
continue;
+ if (amount + CleanCost > reactVolume)
+ break;
+
decalSystem.RemoveDecal(tile.GridUid, decal.Index, decalGrid);
amount += CleanCost;
-
- if (amount > reactVolume)
- break;
}
return amount;
using Content.Server.Popups;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
-using Content.Shared.Chemistry.Reagent;
using Content.Shared.FixedPoint;
using Content.Shared.Fluids;
using Content.Shared.Fluids.Components;
using Content.Shared.Timing;
using Content.Shared.Weapons.Melee;
using Robust.Server.GameObjects;
+using Robust.Shared.Map;
using Robust.Shared.Prototypes;
using Robust.Shared.Utility;
/// <inheritdoc/>
public sealed class AbsorbentSystem : SharedAbsorbentSystem
{
+ [Dependency] private readonly IMapManager _mapManager = default!;
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly AudioSystem _audio = default!;
[Dependency] private readonly PopupSystem _popups = default!;
var oldProgress = component.Progress.ShallowClone();
component.Progress.Clear();
- var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagent);
+ var water = solution.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents);
if (water > FixedPoint2.Zero)
{
- component.Progress[_prototype.Index<ReagentPrototype>(PuddleSystem.EvaporationReagent).SubstanceColor] = water.Float();
+ component.Progress[solution.GetColorWithOnly(_prototype, PuddleSystem.EvaporationReagents)] = water.Float();
}
- var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagent);
+ var otherColor = solution.GetColorWithout(_prototype, PuddleSystem.EvaporationReagents);
var other = (solution.Volume - water).Float();
if (other > 0f)
// Remove the non-water reagents.
// Remove water on target
// Then do the transfer.
- var nonWater = absorberSoln.SplitSolutionWithout(component.PickupAmount, PuddleSystem.EvaporationReagent);
+ var nonWater = absorberSoln.SplitSolutionWithout(component.PickupAmount, PuddleSystem.EvaporationReagents);
_solutionContainerSystem.UpdateChemicals(used, absorberSoln, true);
if (nonWater.Volume == FixedPoint2.Zero && absorberSoln.AvailableVolume == FixedPoint2.Zero)
component.PickupAmount :
absorberSoln.AvailableVolume;
- var water = refillableSolution.RemoveReagent(PuddleSystem.EvaporationReagent, transferAmount);
+ var water = refillableSolution.SplitSolutionWithOnly(transferAmount, PuddleSystem.EvaporationReagents);
_solutionContainerSystem.UpdateChemicals(target, refillableSolution);
- if (water == FixedPoint2.Zero && nonWater.Volume == FixedPoint2.Zero)
+ if (water.Volume == FixedPoint2.Zero && nonWater.Volume == FixedPoint2.Zero)
{
_popups.PopupEntity(Loc.GetString("mopping-system-target-container-empty-water", ("target", target)), user, user);
return false;
}
-
-
- if (water > 0 && !_solutionContainerSystem.TryAddReagent(used, absorberSoln, PuddleSystem.EvaporationReagent, water,
- out _))
+
+ if (water.Volume > 0 && !_solutionContainerSystem.TryAddSolution(used, absorberSoln, water))
{
_popups.PopupEntity(Loc.GetString("mopping-system-full", ("used", used)), used, user);
}
if (!TryComp(target, out PuddleComponent? puddle))
return false;
- if (!_solutionSystem.TryGetSolution(target, puddle.SolutionName, out var puddleSolution) || puddleSolution.Volume <= 0)
+ if (!_solutionSystem.TryGetSolution(target, puddle.SolutionName, out var puddleSoln) || puddleSoln.Volume <= 0)
return false;
// Check if the puddle has any non-evaporative reagents
- if (_puddleSystem.CanFullyEvaporate(puddleSolution))
+ if (_puddleSystem.CanFullyEvaporate(puddleSoln))
{
_popups.PopupEntity(Loc.GetString("mopping-system-puddle-evaporate", ("target", target)), user, user);
return true;
}
// Check if we have any evaporative reagents on our absorber to transfer
- var available = absorberSoln.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagent);
+ var available = absorberSoln.GetTotalPrototypeQuantity(PuddleSystem.EvaporationReagents);
// No material
if (available == FixedPoint2.Zero)
var transferMax = absorber.PickupAmount;
var transferAmount = available > transferMax ? transferMax : available;
- var split = puddleSolution.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagent);
+ var puddleSplit = puddleSoln.SplitSolutionWithout(transferAmount, PuddleSystem.EvaporationReagents);
+ var absorberSplit = absorberSoln.SplitSolutionWithOnly(puddleSplit.Volume, PuddleSystem.EvaporationReagents);
+
+ // Do tile reactions first
+ var coordinates = Transform(target).Coordinates;
+ if (_mapManager.TryGetGrid(coordinates.GetGridUid(EntityManager), out var mapGrid))
+ {
+ _puddleSystem.DoTileReactions(mapGrid.GetTileRef(coordinates), absorberSplit);
+ }
- absorberSoln.RemoveReagent(PuddleSystem.EvaporationReagent, split.Volume);
- puddleSolution.AddReagent(PuddleSystem.EvaporationReagent, split.Volume);
- absorberSoln.AddSolution(split, _prototype);
+ puddleSoln.AddSolution(absorberSplit, _prototype);
+ absorberSoln.AddSolution(puddleSplit, _prototype);
_solutionSystem.UpdateChemicals(used, absorberSoln);
- _solutionSystem.UpdateChemicals(target, puddleSolution);
+ _solutionSystem.UpdateChemicals(target, puddleSoln);
_audio.PlayPvs(absorber.PickupSound, target);
_useDelay.BeginDelay(used);
private static readonly TimeSpan EvaporationCooldown = TimeSpan.FromSeconds(1);
[ValidatePrototypeId<ReagentPrototype>]
- public const string EvaporationReagent = "Water";
+ private const string Water = "Water";
+
+ [ValidatePrototypeId<ReagentPrototype>]
+ private const string SoapyWater = "SoapyWater";
+
+ public static string[] EvaporationReagents = new[] { Water, SoapyWater };
private void OnEvaporationMapInit(EntityUid uid, EvaporationComponent component, MapInitEvent args)
{
return;
}
- if (solution.ContainsPrototype(EvaporationReagent))
+ if (solution.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero)
{
var evaporation = AddComp<EvaporationComponent>(uid);
evaporation.NextTick = _timing.CurTime + EvaporationCooldown;
continue;
var reagentTick = evaporation.EvaporationAmount * EvaporationCooldown.TotalSeconds;
- _solutionContainerSystem.RemoveReagent(uid, puddleSolution, EvaporationReagent, reagentTick);
+ puddleSolution.SplitSolutionWithOnly(reagentTick, EvaporationReagents);
// Despawn if we're done
if (puddleSolution.Volume == FixedPoint2.Zero)
public bool CanFullyEvaporate(Solution solution)
{
- return solution.Contents.Count == 1 && solution.ContainsPrototype(EvaporationReagent);
+ return solution.GetTotalPrototypeQuantity(EvaporationReagents) == solution.Volume;
}
}
{
args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating"));
}
- else if (solution?.ContainsPrototype(EvaporationReagent) == true)
+ else if (solution?.GetTotalPrototypeQuantity(EvaporationReagents) > FixedPoint2.Zero)
{
args.PushMarkup(Loc.GetString("puddle-component-examine-evaporating-partial"));
}
if (tileReact)
{
// First, do all tile reactions
- for (var i = solution.Contents.Count - 1; i >= 0; i--)
- {
- var (reagent, quantity) = solution.Contents[i];
- var proto = _prototypeManager.Index<ReagentPrototype>(reagent.Prototype);
- var removed = proto.ReactionTile(tileRef, quantity);
- if (removed <= FixedPoint2.Zero)
- continue;
-
- solution.RemoveReagent(reagent, removed);
- }
+ DoTileReactions(tileRef, solution);
}
// Tile reactions used up everything.
#endregion
+ public void DoTileReactions(TileRef tileRef, Solution solution)
+ {
+ for (var i = solution.Contents.Count - 1; i >= 0; i--)
+ {
+
+ var (reagent, quantity) = solution.Contents[i];
+ var proto = _prototypeManager.Index<ReagentPrototype>(reagent.Prototype);
+ var removed = proto.ReactionTile(tileRef, quantity);
+ if (removed <= FixedPoint2.Zero)
+ continue;
+
+ solution.RemoveReagent(reagent, removed);
+ }
+ }
+
/// <summary>
/// Tries to get the relevant puddle entity for a tile.
/// </summary>
/// Used for things like used ketchup packets or used syringes.
/// </summary>
[RegisterComponent]
- public sealed partial class TrashOnEmptyComponent : Component
+ public sealed partial class TrashOnSolutionEmptyComponent : Component
{
/// <summary>
/// The name of the solution of which to check emptiness
-using Content.Server.Chemistry.EntitySystems;
using Content.Server.Nutrition.Components;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.Components.SolutionManager;
namespace Content.Server.Nutrition.EntitySystems
{
- public sealed class TrashOnEmptySystem : EntitySystem
+ public sealed class TrashOnSolutionEmptySystem : EntitySystem
{
[Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
public override void Initialize()
{
base.Initialize();
- SubscribeLocalEvent<TrashOnEmptyComponent, ComponentStartup>(OnStartup);
- SubscribeLocalEvent<TrashOnEmptyComponent, SolutionChangedEvent>(OnSolutionChange);
+ SubscribeLocalEvent<TrashOnSolutionEmptyComponent, ComponentStartup>(OnStartup);
+ SubscribeLocalEvent<TrashOnSolutionEmptyComponent, SolutionChangedEvent>(OnSolutionChange);
}
- public void OnStartup(EntityUid uid, TrashOnEmptyComponent component, ComponentStartup args)
+ public void OnStartup(EntityUid uid, TrashOnSolutionEmptyComponent component, ComponentStartup args)
{
CheckSolutions(component);
}
- public void OnSolutionChange(EntityUid uid, TrashOnEmptyComponent component, SolutionChangedEvent args)
+ public void OnSolutionChange(EntityUid uid, TrashOnSolutionEmptyComponent component, SolutionChangedEvent args)
{
CheckSolutions(component);
}
- public void CheckSolutions(TrashOnEmptyComponent component)
+ public void CheckSolutions(TrashOnSolutionEmptyComponent component)
{
if (!EntityManager.HasComponent<SolutionContainerManagerComponent>((component).Owner))
return;
UpdateTags(component, solution);
}
- public void UpdateTags(TrashOnEmptyComponent component, Solution solution)
+ public void UpdateTags(TrashOnSolutionEmptyComponent component, Solution solution)
{
if (solution.Volume <= 0)
{
/// If you only want the volume of a single reagent, use <see cref="GetReagentQuantity"/>
/// </summary>
[Pure]
- public FixedPoint2 GetTotalPrototypeQuantity(string prototype)
+ public FixedPoint2 GetTotalPrototypeQuantity(params string[] prototypes)
{
var total = FixedPoint2.Zero;
foreach (var (reagent, quantity) in Contents)
{
- if (reagent.Prototype == prototype)
+ if (prototypes.Contains(reagent.Prototype))
total += quantity;
}
return sol;
}
+ /// <summary>
+ /// Splits a solution without the specified reagent prototypes.
+ /// </summary>
+ public Solution SplitSolutionWithOnly(FixedPoint2 toTake, params string[] includedPrototypes)
+ {
+ // First remove the non-included prototypes
+ List<ReagentQuantity> excluded = new();
+ for (var i = Contents.Count - 1; i >= 0; i--)
+ {
+ if (includedPrototypes.Contains(Contents[i].Reagent.Prototype))
+ continue;
+
+ excluded.Add(Contents[i]);
+ RemoveReagent(Contents[i]);
+ }
+
+ // Then split the solution
+ var sol = SplitSolution(toTake);
+
+ // Then re-add the excluded reagents to the original solution.
+ foreach (var reagent in excluded)
+ {
+ AddReagent(reagent);
+ }
+
+ return sol;
+ }
+
public Solution SplitSolution(FixedPoint2 toTake)
{
if (toTake <= FixedPoint2.Zero)
return GetColorWithout(protoMan);
}
+ public Color GetColorWithOnly(IPrototypeManager? protoMan, params string[] included)
+ {
+ if (Volume == FixedPoint2.Zero)
+ {
+ return Color.Transparent;
+ }
+
+ IoCManager.Resolve(ref protoMan);
+
+ Color mixColor = default;
+ var runningTotalQuantity = FixedPoint2.New(0);
+ bool first = true;
+
+ foreach (var (reagent, quantity) in Contents)
+ {
+ if (!included.Contains(reagent.Prototype))
+ continue;
+
+ runningTotalQuantity += quantity;
+
+ if (!protoMan.TryIndex(reagent.Prototype, out ReagentPrototype? proto))
+ {
+ continue;
+ }
+
+ if (first)
+ {
+ first = false;
+ mixColor = proto.SubstanceColor;
+ continue;
+ }
+
+ var interpolateValue = quantity.Float() / runningTotalQuantity.Float();
+ mixColor = Color.InterpolateBetween(mixColor, proto.SubstanceColor, interpolateValue);
+ }
+ return mixColor;
+ }
+
#region Enumeration
public IEnumerator<ReagentQuantity> GetEnumerator()
flavor-base-sharp = sharp
flavor-base-syrupy = syrupy
flavor-base-spaceshroom = mysterious
+flavor-base-clean = clean
# lmao
flavor-base-terrible = terrible
flavor-complex-bee = unbeelievable
flavor-complex-sax = like jazz
flavor-complex-bottledlightning = like lightning in a bottle
+flavor-complex-punishment = like punishment
reagent-name-space-cleaner = space cleaner
reagent-desc-space-cleaner = This is able to clean almost all surfaces of almost anything that may dirty them. The janitor is likely to appreciate refills.
+reagent-name-soap = soap
+reagent-desc-soap = Soap can be used to make soapy water.
+
+reagent-name-soapy-water = soapy water
+reagent-desc-soapy-water = It's just soap and water. Good for cleaning gunk off of surfaces and also slippier than regular water.
+
reagent-name-space-lube = space lube
reagent-desc-space-lube = Space Lube is a high performance lubricant intended for maintenance of extremely complex mechanical equipment (and certainly not used to make people slip).
reagent-physical-desc-bubbly = bubbly
reagent-physical-desc-rocky = rocky
reagent-physical-desc-lemony-fresh = lemony fresh
+reagent-physical-desc-soapy = soapy
reagent-physical-desc-crisp = crisp
reagent-physical-desc-citric = citric
reagent-physical-desc-acidic = acidic
layers:
- state: red
- sprite: Objects/Specific/Janitorial/soap.rsi
- state: soap
+ state: soap-4
- type: RandomSpawner
prototypes:
- Soap
qualities:
- Rolling
speed: 0.75 # not as good as a rolling pin but does the job
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
speed: 0.25 # its small so takes longer to roll the entire dough flat
- type: ItemCooldown
- type: SpaceGarbage
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: PhysicalComposition
materialComposition:
- type: SolutionContainerVisuals
maxFillLevels: 4
fillBaseName: icon-
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
- type: Sprite
sprite: Objects/Consumable/Drinks/cafe_latte.rsi
- type: Appearance
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
- type: SolutionContainerVisuals
maxFillLevels: 4
fillBaseName: icon-
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
- type: SolutionContainerVisuals
maxFillLevels: 4
fillBaseName: icon-
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
state: icon
- type: Item
sprite: Objects/Consumable/Drinks/lean.rsi
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
- type: SolutionContainerVisuals
maxFillLevels: 1
fillBaseName: icon-
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
reagents:
- ReagentId: Water
Quantity: 50
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: entity
sprite: Objects/Consumable/Food/condiments.rsi
- type: Icon
sprite: Objects/Consumable/Food/condiments.rsi
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: food
- type: SpaceGarbage
- type: StaticPrice
damageContainer: Inorganic
- type: Spillable
solution: food
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: food
- type: entity
- Soap
- type: Sprite
sprite: Objects/Specific/Janitorial/soap.rsi
- state: soap
+ layers:
+ - state: soap-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ maxFillLevels: 4
+ fillBaseName: soap-
+ changeColor: false
+ - type: Appearance
- type: Item
sprite: Objects/Specific/Janitorial/soap.rsi
- type: Slippery
density: 10
mask:
- ItemMask
+ - type: SolutionContainerManager
+ solutions:
+ soap:
+ maxVol: 50
+ reagents:
+ - ReagentId: SoapReagent
+ Quantity: 50
+ - type: SolutionTransfer
+ transferAmount: 10
+ minTransferAmount: 1
+ maxTransferAmount: 25
+ canReceive: false
+ canChangeTransferAmount: true
+ - type: DrainableSolution
+ solution: soap
+ - type: DeleteOnSolutionEmpty
+ solution: soap
+ - type: FlavorProfile
+ flavors:
+ - clean
+ - type: Food
+ solution: soap
+
- type: entity
name: soap
description: A Nanotrasen brand bar of soap. Smells of plasma.
components:
- type: Sprite
- state: nt
+ layers:
+ - state: nt-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ fillBaseName: nt-
- type: Item
heldPrefix: nt
+ - type: SolutionContainerManager
+ solutions:
+ soap:
+ maxVol: 100
+ reagents:
+ - ReagentId: SoapReagent
+ Quantity: 100
- type: entity
name: soap
description: A deluxe Waffle Co. brand bar of soap. Smells of condoms.
components:
- type: Sprite
- state: deluxe
+ layers:
+ - state: deluxe-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ fillBaseName: deluxe-
- type: Item
heldPrefix: deluxe
description: An untrustworthy bar of soap. Smells of fear.
components:
- type: Sprite
- state: syndie
+ layers:
+ - state: syndie-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ fillBaseName: syndie-
- type: Slippery
paralyzeTime: 5
launchForwardsMultiplier: 2.5
- type: Item
heldPrefix: syndie
+ - type: FlavorProfile
+ flavors:
+ - clean
+ - punishment
- type: entity
name: soap
description: A homemade bar of soap. Smells of... well....
components:
- type: Sprite
- state: gibs
+ layers:
+ - state: gibs-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ fillBaseName: gibs-
+ - type: Slippery
+ paralyzeTime: 2
+ - type: StepTrigger
- type: Item
heldPrefix: gibs
+ - type: FlavorProfile
+ flavors:
+ - clean
+ - meaty
- type: entity
name: omega soap
description: The most advanced soap known to mankind. Smells of bluespace.
components:
- type: Sprite
- state: omega
+ layers:
+ - state: omega-4
+ map: ["enum.SolutionContainerLayers.Fill"]
+ - type: SolutionContainerVisuals
+ fillBaseName: omega-
- type: Slippery
paralyzeTime: 7
launchForwardsMultiplier: 3
- type: Item
heldPrefix: omega
+ - type: SolutionContainerManager
+ solutions:
+ soap:
+ maxVol: 240 #In the Greek alphabet, Omega is the 24th letter
+ reagents:
+ - ReagentId: SoapReagent
+ Quantity: 240
sprayVelocity: 2
spraySound:
path: /Audio/Effects/spray2.ogg
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: spray
- type: entity
- type: SpaceGarbage
- type: StaticPrice
price: 75 # These are limited supply items.
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: pen
- type: entity
damage:
types:
Blunt: 0
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: drink
- type: StaticPrice
price: 0
solution: injector
- type: Spillable
solution: injector
- - type: TrashOnEmpty
+ - type: TrashOnSolutionEmpty
solution: injector
- type: Appearance
- type: SolutionContainerVisuals
flavorType: Base
description: flavor-base-syrupy
+- type: flavor
+ id: clean
+ flavorType: Base
+ description: flavor-base-clean
+
- type: flavor
id: nothing
flavorType: Complex
id: spaceshroomcooked
flavorType: Complex
description: flavor-complex-spaceshroom-cooked
-
+
- type: flavor
id: lostfriendship
flavorType: Complex
- type: flavor
id: pumpkin
flavorType: Complex
- description: flavor-complex-pumpkin
\ No newline at end of file
+ description: flavor-complex-pumpkin
+
+- type: flavor
+ id: punishment
+ flavorType: Complex
+ description: flavor-complex-punishment
- !type:CleanTileReaction {}
- !type:CleanDecalsReaction {}
+- type: reagent
+ id: SoapReagent
+ name: reagent-name-soap
+ desc: reagent-desc-soap
+ physicalDesc: reagent-physical-desc-soapy
+ flavor: clean
+ color: "#c8dfc9"
+ recognizable: true
+ boilingPoint: 100.0
+ meltingPoint: 60.0
+ metabolisms:
+ Food:
+ effects:
+ - !type:ChemVomit
+ Drink:
+ effects:
+ - !type:ChemVomit
+
+- type: reagent
+ id: SoapyWater
+ parent: Water
+ name: reagent-name-soapy-water
+ desc: reagent-desc-soapy-water
+ physicalDesc: reagent-physical-desc-soapy
+ flavor: clean
+ color: "#9ec8dc"
+ recognizable: true
+ metabolisms:
+ Drink:
+ effects:
+ - !type:SatiateThirst
+ factor: 3
+ - !type:ChemVomit
+ thirstAmount: -10.0
+ hungerAmount: -10.0
+ plantMetabolism:
+ - !type:PlantAdjustWater
+ amount: .8
+ tileReactions:
+ - !type:CleanDecalsReaction
+ cleanCost: 5
+ - !type:ExtinguishTileReaction { }
+ - !type:SpillIfPuddlePresentTileReaction { }
+
- type: reagent
id: SpaceLube
name: reagent-name-space-lube
products:
SpaceCleaner: 2
+- type: reaction
+ id: SoapyWater
+ reactants:
+ Water:
+ amount: 3
+ SoapReagent:
+ amount: 1
+ products:
+ SoapyWater: 4
+
- type: reaction
id: SpaceLube
impact: Medium
},
"states": [
{
- "name": "soap"
+ "name": "soap-1"
},
{
- "name": "deluxe"
+ "name": "soap-2"
},
{
- "name": "gibs"
+ "name": "soap-3"
},
{
- "name": "nt"
+ "name": "soap-4"
},
{
- "name": "omega"
+ "name": "deluxe-1"
},
{
- "name": "syndie"
+ "name": "deluxe-2"
+ },
+ {
+ "name": "deluxe-3"
+ },
+ {
+ "name": "deluxe-4"
+ },
+ {
+ "name": "gibs-1"
+ },
+ {
+ "name": "gibs-2"
+ },
+ {
+ "name": "gibs-3"
+ },
+ {
+ "name": "gibs-4"
+ },
+ {
+ "name": "nt-1"
+ },
+ {
+ "name": "nt-2"
+ },
+ {
+ "name": "nt-3"
+ },
+ {
+ "name": "nt-4"
+ },
+ {
+ "name": "omega-1"
+ },
+ {
+ "name": "omega-2"
+ },
+ {
+ "name": "omega-3"
+ },
+ {
+ "name": "omega-4"
+ },
+ {
+ "name": "syndie-1"
+ },
+ {
+ "name": "syndie-2"
+ },
+ {
+ "name": "syndie-3"
+ },
+ {
+ "name": "syndie-4"
},
{
"name": "inhand-left",