Alchemy tools: pestle and mortar (#144)
* add mortar & pestle mechanic * setup prototypes * Update mixing_types.yml * add bubble sound collection, fix errors
88
Content.Server/_CP14/Alchemy/CP14AlchemyExtractionSystem.cs
Normal file
@@ -0,0 +1,88 @@
|
||||
using Content.Shared.Chemistry.Components;
|
||||
using Content.Shared.Chemistry.Components.SolutionManager;
|
||||
using Content.Shared.Chemistry.EntitySystems;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Interaction;
|
||||
using Content.Shared.Kitchen.Components;
|
||||
using Content.Shared.Stacks;
|
||||
using Robust.Shared.Audio.Systems;
|
||||
using Robust.Shared.Containers;
|
||||
using Robust.Shared.Random;
|
||||
|
||||
namespace Content.Server._CP14.Alchemy;
|
||||
|
||||
public sealed partial class CP14AlchemyExtractionSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedSolutionContainerSystem _solutionContainer = default!;
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedStackSystem _stackSystem = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<CP14MortarComponent, InteractUsingEvent>(OnInteractUsing);
|
||||
}
|
||||
|
||||
private void OnInteractUsing(Entity<CP14MortarComponent> mortar, ref InteractUsingEvent args)
|
||||
{
|
||||
if (!TryComp<CP14PestleComponent>(args.Used, out var pestle))
|
||||
return;
|
||||
|
||||
_audio.PlayPvs(pestle.HitSound, mortar);
|
||||
|
||||
if (!_random.Prob(pestle.Probability))
|
||||
return;
|
||||
|
||||
if (!TryComp<SolutionContainerManagerComponent>(mortar, out var solutionManagerComp))
|
||||
return;
|
||||
var solutionManager = new Entity<SolutionContainerManagerComponent?>(mortar, solutionManagerComp);
|
||||
|
||||
if (!_solutionContainer.TryGetSolution(solutionManager, mortar.Comp.Solution, out var solutionEnt, out var solution))
|
||||
return;
|
||||
|
||||
if (!_container.TryGetContainer(mortar, mortar.Comp.ContainerId, out var container))
|
||||
return;
|
||||
|
||||
if (container.ContainedEntities.Count == 0)
|
||||
return;
|
||||
|
||||
var ent = _random.Pick(container.ContainedEntities);
|
||||
|
||||
var juiceSolution = CompOrNull<ExtractableComponent>(ent)?.JuiceSolution;
|
||||
if (juiceSolution is null)
|
||||
return;
|
||||
|
||||
if (TryComp<StackComponent>(ent, out var stack))
|
||||
{
|
||||
var totalVolume = juiceSolution.Volume * stack.Count;
|
||||
if (totalVolume <= 0)
|
||||
return;
|
||||
|
||||
// Maximum number of items we can process in the stack without going over AvailableVolume
|
||||
// We add a small tolerance, because floats are inaccurate.
|
||||
var fitsCount = (int) (stack.Count * FixedPoint2.Min(solution.AvailableVolume / totalVolume + 0.01, 1));
|
||||
if (fitsCount <= 0)
|
||||
return;
|
||||
|
||||
// Make a copy of the solution to scale
|
||||
// Otherwise we'll actually change the volume of the remaining stack too
|
||||
var scaledSolution = new Solution(juiceSolution);
|
||||
scaledSolution.ScaleSolution(fitsCount);
|
||||
juiceSolution = scaledSolution;
|
||||
|
||||
_stackSystem.SetCount(ent, stack.Count - fitsCount); // Setting to 0 will QueueDel
|
||||
}
|
||||
else
|
||||
{
|
||||
if (juiceSolution.Volume > solution.AvailableVolume)
|
||||
return;
|
||||
|
||||
QueueDel(ent);
|
||||
}
|
||||
|
||||
_solutionContainer.TryAddSolution(solutionEnt.Value, juiceSolution);
|
||||
}
|
||||
}
|
||||
13
Content.Server/_CP14/Alchemy/CP14MortarComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
namespace Content.Server._CP14.Alchemy;
|
||||
|
||||
[RegisterComponent, Access(typeof(CP14AlchemyExtractionSystem))]
|
||||
public sealed partial class CP14MortarComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public string Solution = string.Empty;
|
||||
|
||||
[DataField(required: true)]
|
||||
public string ContainerId = string.Empty;
|
||||
}
|
||||
|
||||
13
Content.Server/_CP14/Alchemy/CP14PestleComponent.cs
Normal file
@@ -0,0 +1,13 @@
|
||||
using Robust.Shared.Audio;
|
||||
|
||||
namespace Content.Server._CP14.Alchemy;
|
||||
|
||||
[RegisterComponent, Access(typeof(CP14AlchemyExtractionSystem))]
|
||||
public sealed partial class CP14PestleComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public float Probability = 0.1f;
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier HitSound = new SoundCollectionSpecifier("CP14Pestle", AudioParams.Default.WithVariation(0.2f));
|
||||
}
|
||||
@@ -68,7 +68,7 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
[DataField("impact", serverOnly: true)] public LogImpact Impact = LogImpact.Low;
|
||||
|
||||
// TODO SERV3: Empty on the client, (de)serialize on the server with module manager is server module
|
||||
[DataField("sound", serverOnly: true)] public SoundSpecifier Sound { get; private set; } = new SoundPathSpecifier("/Audio/Effects/Chemistry/bubbles.ogg");
|
||||
[DataField("sound", serverOnly: true)] public SoundSpecifier Sound { get; private set; } = new SoundCollectionSpecifier("CP14Bubbles", AudioParams.Default.WithVariation(0.2f));
|
||||
|
||||
/// <summary>
|
||||
/// If true, this reaction will only consume only integer multiples of the reactant amounts. If there are not
|
||||
|
||||
4
Resources/Audio/_CP14/Effects/attributions.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
- files: ["bubbles.ogg"]
|
||||
license: "CC0-1.0"
|
||||
copyright: 'magnuswaker of Freesound.org. Mixed from stereo to mono.'
|
||||
source: "https://freesound.org/people/magnuswaker/sounds/540074/"
|
||||
BIN
Resources/Audio/_CP14/Effects/bubbles.ogg
Normal file
4
Resources/Audio/_CP14/Items/Pestle/attributions.yml
Normal file
@@ -0,0 +1,4 @@
|
||||
- files: ["pestle1.ogg", "pestle2.ogg", "pestle3.ogg", "pestle4.ogg", "pestle5.ogg"]
|
||||
license: "CC-BY-4.0"
|
||||
copyright: 'Australopithecusman of Freesound.org. Cropped and Mixed from stereo to mono.'
|
||||
source: "https://freesound.org/people/Australopithecusman/sounds/388900/"
|
||||
BIN
Resources/Audio/_CP14/Items/Pestle/pestle1.ogg
Normal file
BIN
Resources/Audio/_CP14/Items/Pestle/pestle2.ogg
Normal file
BIN
Resources/Audio/_CP14/Items/Pestle/pestle3.ogg
Normal file
BIN
Resources/Audio/_CP14/Items/Pestle/pestle4.ogg
Normal file
BIN
Resources/Audio/_CP14/Items/Pestle/pestle5.ogg
Normal file
@@ -19,15 +19,15 @@
|
||||
id: DummyJuice
|
||||
verbText: mixing-verb-default-juice
|
||||
icon:
|
||||
sprite: Structures/Machines/juicer.rsi
|
||||
state: juicer0
|
||||
sprite: _CP14/Objects/Specific/Alchemy/mortar_pestle.rsi
|
||||
state: full
|
||||
|
||||
- type: mixingCategory
|
||||
id: DummyCondense
|
||||
verbText: mixing-verb-default-condense
|
||||
icon:
|
||||
sprite: Structures/Piping/Atmospherics/condenser.rsi
|
||||
state: display
|
||||
sprite: _CP14/Objects/Specific/Alchemy/mortar_pestle.rsi
|
||||
state: full
|
||||
|
||||
# Alternative Mixing Methods
|
||||
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: CP14Cauldron
|
||||
name: cauldron
|
||||
description: A heavy cauldron. It is not as bulky as a vat, but can be carried in your hands.
|
||||
components:
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
- type: MultiHandedItem
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 0.6
|
||||
sprintModifier: 0.6
|
||||
- type: HeldSpeedModifier
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/Specific/Alchemy/cauldron.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
- state: liq-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
vat:
|
||||
maxVol: 100
|
||||
- type: Spillable
|
||||
solution: vat
|
||||
- type: DrainableSolution
|
||||
solution: vat
|
||||
- type: ExaminableSolution
|
||||
solution: vat
|
||||
- type: MixableSolution
|
||||
solution: vat
|
||||
- type: RefillableSolution
|
||||
solution: vat
|
||||
- type: DrawableSolution
|
||||
solution: vat
|
||||
- type: DumpableSolution
|
||||
solution: vat
|
||||
- type: SolutionItemStatus
|
||||
solution: vat
|
||||
- type: Drink
|
||||
solution: vat
|
||||
- type: Injector
|
||||
solutionName: vat
|
||||
injectOnly: false
|
||||
ignoreMobs: true
|
||||
minTransferAmount: 10
|
||||
maxTransferAmount: 100
|
||||
transferAmount: 50
|
||||
toggleState: 1 # draw
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.TransferAmountUiKey.Key:
|
||||
type: TransferAmountBoundUserInterface
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 5
|
||||
fillBaseName: liq-
|
||||
inHandsMaxFillLevels: 5
|
||||
inHandsFillBaseName: -fill
|
||||
- type: DamageOtherOnHit
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
- type: DamageOnHighSpeedImpact
|
||||
minimumSpeed: 2
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
|
||||
@@ -0,0 +1,146 @@
|
||||
- type: entity
|
||||
parent: BaseItem
|
||||
id: CP14Cauldron
|
||||
name: cauldron
|
||||
description: A heavy cauldron. It is not as bulky as a vat, but can be carried in your hands.
|
||||
components:
|
||||
- type: Item
|
||||
size: Ginormous
|
||||
- type: MultiHandedItem
|
||||
- type: ClothingSpeedModifier
|
||||
walkModifier: 0.6
|
||||
sprintModifier: 0.6
|
||||
- type: HeldSpeedModifier
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/Specific/Alchemy/cauldron.rsi
|
||||
layers:
|
||||
- state: icon
|
||||
- state: liq-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
vat:
|
||||
maxVol: 100
|
||||
- type: Spillable
|
||||
solution: vat
|
||||
- type: DrainableSolution
|
||||
solution: vat
|
||||
- type: ExaminableSolution
|
||||
solution: vat
|
||||
- type: MixableSolution
|
||||
solution: vat
|
||||
- type: RefillableSolution
|
||||
solution: vat
|
||||
- type: DrawableSolution
|
||||
solution: vat
|
||||
- type: DumpableSolution
|
||||
solution: vat
|
||||
- type: SolutionItemStatus
|
||||
solution: vat
|
||||
- type: Drink
|
||||
solution: vat
|
||||
- type: Injector
|
||||
solutionName: vat
|
||||
injectOnly: false
|
||||
ignoreMobs: true
|
||||
minTransferAmount: 10
|
||||
maxTransferAmount: 100
|
||||
transferAmount: 50
|
||||
toggleState: 1 # draw
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.TransferAmountUiKey.Key:
|
||||
type: TransferAmountBoundUserInterface
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 5
|
||||
fillBaseName: liq-
|
||||
inHandsMaxFillLevels: 5
|
||||
inHandsFillBaseName: -fill
|
||||
- type: DamageOtherOnHit
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
- type: DamageOnHighSpeedImpact
|
||||
minimumSpeed: 2
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
|
||||
- type: entity
|
||||
id: CP14Pestle
|
||||
name: pestle
|
||||
description: A device for conveniently grinding various materials in liquids
|
||||
parent: BaseItem
|
||||
components:
|
||||
- type: Item
|
||||
size: Tiny
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/Specific/Alchemy/mortar_pestle.rsi
|
||||
state: pestle
|
||||
- type: CP14Pestle
|
||||
|
||||
- type: entity
|
||||
id: CP14Mortar
|
||||
name: mortar
|
||||
description: Alchemical sturdy plate for grinding reagents
|
||||
parent: BaseStorageItem
|
||||
components:
|
||||
- type: Item
|
||||
size: Normal
|
||||
- type: Sprite
|
||||
sprite: _CP14/Objects/Specific/Alchemy/mortar_pestle.rsi
|
||||
layers:
|
||||
- state: mortar_base
|
||||
- state: liq-1
|
||||
map: ["enum.SolutionContainerLayers.Fill"]
|
||||
visible: false
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
mortar:
|
||||
maxVol: 30
|
||||
- type: Spillable
|
||||
solution: mortar
|
||||
- type: DrainableSolution
|
||||
solution: mortar
|
||||
- type: ExaminableSolution
|
||||
solution: mortar
|
||||
- type: MixableSolution
|
||||
solution: mortar
|
||||
- type: RefillableSolution
|
||||
solution: mortar
|
||||
- type: DrawableSolution
|
||||
solution: mortar
|
||||
- type: DumpableSolution
|
||||
solution: mortar
|
||||
- type: SolutionItemStatus
|
||||
solution: mortar
|
||||
- type: Drink
|
||||
solution: mortar
|
||||
- type: Injector
|
||||
solutionName: mortar
|
||||
injectOnly: false
|
||||
ignoreMobs: true
|
||||
minTransferAmount: 1
|
||||
maxTransferAmount: 10
|
||||
transferAmount: 5
|
||||
toggleState: 1 # draw
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.TransferAmountUiKey.Key:
|
||||
type: TransferAmountBoundUserInterface
|
||||
enum.StorageUiKey.Key:
|
||||
type: StorageBoundUserInterface
|
||||
- type: Appearance
|
||||
- type: SolutionContainerVisuals
|
||||
maxFillLevels: 4
|
||||
fillBaseName: liq-
|
||||
- type: Storage
|
||||
maxItemSize: Normal
|
||||
cP14CanStorageSolutionManagers: false
|
||||
grid:
|
||||
- 0,0,1,1
|
||||
- type: CP14Mortar
|
||||
solution: mortar
|
||||
containerId: storagebase
|
||||
@@ -80,8 +80,7 @@
|
||||
containerId: storagebase
|
||||
- type: Storage
|
||||
cP14CanStorageSolutionManagers: false
|
||||
maxItemSize: Normal
|
||||
grid:
|
||||
- 0,0,4,3
|
||||
blacklist:
|
||||
components:
|
||||
- SolutionContainerManager
|
||||
- type: Anchorable
|
||||
14
Resources/Prototypes/_CP14/SoundCollections/alchemy.yml
Normal file
@@ -0,0 +1,14 @@
|
||||
- type: soundCollection
|
||||
id: CP14Pestle
|
||||
files:
|
||||
- /Audio/_CP14/Items/Pestle/pestle1.ogg
|
||||
- /Audio/_CP14/Items/Pestle/pestle2.ogg
|
||||
- /Audio/_CP14/Items/Pestle/pestle3.ogg
|
||||
- /Audio/_CP14/Items/Pestle/pestle4.ogg
|
||||
- /Audio/_CP14/Items/Pestle/pestle5.ogg
|
||||
|
||||
- type: soundCollection
|
||||
id: CP14Bubbles
|
||||
files:
|
||||
- /Audio/Effects/Chemistry/bubbles.ogg
|
||||
- /Audio/_CP14/Effects/bubbles.ogg
|
||||
|
After Width: | Height: | Size: 412 B |
|
After Width: | Height: | Size: 114 B |
|
After Width: | Height: | Size: 137 B |
|
After Width: | Height: | Size: 158 B |
|
After Width: | Height: | Size: 159 B |
@@ -0,0 +1,32 @@
|
||||
{
|
||||
"version": 1,
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Created by TheShuEd (Github) for CrystallPunk14",
|
||||
"states": [
|
||||
{
|
||||
"name": "full"
|
||||
},
|
||||
{
|
||||
"name": "liq-1"
|
||||
},
|
||||
{
|
||||
"name": "liq-2"
|
||||
},
|
||||
{
|
||||
"name": "liq-3"
|
||||
},
|
||||
{
|
||||
"name": "liq-4"
|
||||
},
|
||||
{
|
||||
"name": "mortar_base"
|
||||
},
|
||||
{
|
||||
"name": "pestle"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 363 B |
|
After Width: | Height: | Size: 251 B |