]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add Mortar and Handheld Juicer (#42019)
authorScarKy0 <106310278+ScarKy0@users.noreply.github.com>
Fri, 16 Jan 2026 00:19:42 +0000 (01:19 +0100)
committerGitHub <noreply@github.com>
Fri, 16 Jan 2026 00:19:42 +0000 (00:19 +0000)
* init

* API

* testing

* review

* return

* good enough, fix later

TODO:
Proper prototype
DoAfter
Sounds

* "proper" prototype

TODO
DoAfter
Sprite

* proper protos, mortar sprite

* juicer sprites

TODO:
Juicer sounds
Makeshift crafting recipes
Add regular to vendors

* sprite tweak

* juicing sound, cleanup, construction

* vendors

* line end

* attribution newline

* small balance tweak

* Let it be known id never webedit

* meta

* item size

* review

* handhelds

* partial review

* cache solution, looping

* graph

* review

* popup

---------

Co-authored-by: Janet Blackquill <uhhadd@gmail.com>
42 files changed:
Content.Client/Kitchen/EntitySystems/ReagentGrinderSystem.cs
Content.Shared/Kitchen/Components/EntitySystems/HandheldGrinderSystem.cs [new file with mode: 0644]
Content.Shared/Kitchen/Components/HandheldGrinderComponent.cs [new file with mode: 0644]
Content.Shared/Kitchen/Components/ReagentGrinderComponent.cs
Content.Shared/Kitchen/EntitySystems/SharedReagentGrinderSystem.cs
Resources/Audio/Items/Culinary/attributions.yml [new file with mode: 0644]
Resources/Audio/Items/Culinary/juicer_juicing.ogg [new file with mode: 0644]
Resources/Audio/Items/Culinary/mortar_grinding.ogg [new file with mode: 0644]
Resources/Locale/en-US/kitchen/components/handheld-grinder.ftl [new file with mode: 0644]
Resources/Prototypes/Catalog/VendingMachines/Inventories/dinnerware.yml
Resources/Prototypes/Catalog/VendingMachines/Inventories/nutri.yml
Resources/Prototypes/Entities/Objects/Specific/Kitchen/equipment.yml [new file with mode: 0644]
Resources/Prototypes/Recipes/Construction/tools.yml
Resources/Prototypes/Recipes/Crafting/Graphs/improvised/handheld_grinders.yml [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/cap.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-1.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-2.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-3.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-4.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/juicer_base.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_base.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_icon.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-1.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-2.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-3.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-4.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/icon.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-left.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-right.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_base.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_icon.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/meta.json [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/mortar_base.png [new file with mode: 0644]
Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/pestle.png [new file with mode: 0644]

index 5eebd4a0fba4c0400450c190c12bde7516cb0097..0aaa8ba8d8eb8de8849774c290075b5c6b2c4b7d 100644 (file)
@@ -5,4 +5,3 @@ namespace Content.Client.Kitchen.EntitySystems;
 
 [UsedImplicitly]
 public sealed class ReagentGrinderSystem : SharedReagentGrinderSystem;
-
diff --git a/Content.Shared/Kitchen/Components/EntitySystems/HandheldGrinderSystem.cs b/Content.Shared/Kitchen/Components/EntitySystems/HandheldGrinderSystem.cs
new file mode 100644 (file)
index 0000000..30e61c8
--- /dev/null
@@ -0,0 +1,151 @@
+using System.Diagnostics.CodeAnalysis;
+using Content.Shared.Chemistry.EntitySystems;
+using Content.Shared.Destructible;
+using Content.Shared.DoAfter;
+using Content.Shared.Fluids;
+using Content.Shared.Interaction;
+using Content.Shared.Kitchen.Components;
+using Content.Shared.Popups;
+using Content.Shared.Stacks;
+using Robust.Shared.Audio.Systems;
+using Robust.Shared.Containers;
+using Robust.Shared.Network;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.Kitchen.EntitySystems;
+
+internal sealed class HandheldGrinderSystem : EntitySystem
+{
+    [Dependency] private readonly SharedReagentGrinderSystem _reagentGrinder = default!;
+    [Dependency] private readonly SharedSolutionContainerSystem _solution = default!;
+    [Dependency] private readonly SharedStackSystem _stackSystem = default!;
+    [Dependency] private readonly SharedDestructibleSystem _destructibleSystem = default!;
+    [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+    [Dependency] private readonly SharedAudioSystem _audio = default!;
+    [Dependency] private readonly INetManager _net = default!;
+    [Dependency] private readonly SharedPuddleSystem _puddle = default!;
+    [Dependency] private readonly SharedPopupSystem _popup = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<HandheldGrinderComponent, EntRemovedFromContainerMessage>(OnGrinderRemoved);
+        SubscribeLocalEvent<HandheldGrinderComponent, InteractUsingEvent>(OnInteractUsing);
+        SubscribeLocalEvent<HandheldGrinderComponent, HandheldGrinderDoAfterEvent>(OnHandheldDoAfter);
+    }
+
+    // prevent the infamous UdderSystem debug assert, see https://github.com/space-wizards/space-station-14/pull/35314
+    // TODO: find a better solution than copy pasting this into every shared system that caches solution entities
+    private void OnGrinderRemoved(Entity<HandheldGrinderComponent> entity, ref EntRemovedFromContainerMessage args)
+    {
+        // Make sure the removed entity was our contained solution and set it to null
+        if (args.Entity != entity.Comp.GrinderSolution?.Owner)
+            return;
+
+        entity.Comp.GrinderSolution = null;
+    }
+
+    private void OnInteractUsing(Entity<HandheldGrinderComponent> ent, ref InteractUsingEvent args)
+    {
+        if (args.Handled)
+            return;
+
+        args.Handled = true;
+
+        var item = args.Used;
+
+        if (!CanGrinderBeUsed(ent, item, out var reason))
+        {
+            _popup.PopupClient(reason, ent, args.User);
+            return;
+        }
+
+        if (_reagentGrinder.GetGrinderSolution(item, ent.Comp.Program) is null)
+            return;
+
+        if (!_solution.ResolveSolution(ent.Owner, ent.Comp.SolutionName, ref ent.Comp.GrinderSolution))
+            return;
+
+        if (_net.IsServer) // Cannot cancel predicted audio.
+            ent.Comp.AudioStream = _audio.PlayPvs(ent.Comp.Sound, ent)?.Entity;
+
+        var doAfter = new DoAfterArgs(EntityManager, args.User, ent.Comp.DoAfterDuration, new HandheldGrinderDoAfterEvent(), ent, ent, item)
+        {
+            NeedHand = true,
+            BreakOnDamage = true,
+            BreakOnDropItem = true,
+            BreakOnHandChange = true,
+            BreakOnMove = true
+        };
+
+        _doAfter.TryStartDoAfter(doAfter);
+    }
+
+    private void OnHandheldDoAfter(Entity<HandheldGrinderComponent> ent, ref HandheldGrinderDoAfterEvent args)
+    {
+        ent.Comp.AudioStream = _audio.Stop(ent.Comp.AudioStream);
+
+        if (args.Cancelled)
+            return;
+
+        if (args.Used is not { } item)
+            return;
+
+        if (!CanGrinderBeUsed(ent, item, out var reason))
+        {
+            _popup.PopupClient(reason, ent, args.User);
+            return;
+        }
+
+        if (_reagentGrinder.GetGrinderSolution(item, ent.Comp.Program) is not { } obtainedSolution)
+            return;
+
+        if (!_solution.ResolveSolution(ent.Owner, ent.Comp.SolutionName, ref ent.Comp.GrinderSolution, out var solution))
+            return;
+
+        _solution.TryMixAndOverflow(ent.Comp.GrinderSolution.Value, obtainedSolution, solution.MaxVolume, out var overflow);
+
+        if (overflow != null)
+            _puddle.TrySpillAt(ent, overflow, out _);
+
+        if (TryComp<StackComponent>(item, out var stack))
+            _stackSystem.ReduceCount((item, stack), 1);
+        else
+            _destructibleSystem.DestroyEntity(item);
+
+        _popup.PopupClient(Loc.GetString(ent.Comp.FinishedPopup, ("item", item)), ent, args.User);
+    }
+
+    /// <summary>
+    /// Checks whether the respective handheld grinder can currently be used.
+    /// </summary>
+    /// <param name="ent">The grinder entity.</param>
+    /// <param name="item">The item it is being used on.</param>
+    /// <param name="reason">Reason the grinder cannot be used. Null if the function returns true.</param>
+    /// <returns>True if the grinder can be used, otherwise false.</returns>
+    public bool CanGrinderBeUsed(Entity<HandheldGrinderComponent> ent, EntityUid item, [NotNullWhen(false)] out string? reason)
+    {
+        reason = null;
+        if (ent.Comp.Program == GrinderProgram.Grind && !_reagentGrinder.CanGrind(item))
+        {
+            reason = Loc.GetString("handheld-grinder-cannot-grind", ("item", item));
+            return false;
+        }
+
+        if (ent.Comp.Program == GrinderProgram.Juice && !_reagentGrinder.CanJuice(item))
+        {
+            reason = Loc.GetString("handheld-grinder-cannot-juice", ("item", item));
+            return false;
+        }
+
+        return true;
+    }
+}
+
+/// <summary>
+/// DoAfter used to indicate the handheld grinder is in use.
+/// After it ends, the GrinderProgram from <see cref="HandheldGrinderComponent"/> is used on the contents.
+/// </summary>
+[Serializable, NetSerializable]
+public sealed partial class HandheldGrinderDoAfterEvent : SimpleDoAfterEvent;
diff --git a/Content.Shared/Kitchen/Components/HandheldGrinderComponent.cs b/Content.Shared/Kitchen/Components/HandheldGrinderComponent.cs
new file mode 100644 (file)
index 0000000..c32d11d
--- /dev/null
@@ -0,0 +1,54 @@
+using Content.Shared.Chemistry.Components;
+using Robust.Shared.Audio;
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Kitchen.Components;
+
+/// <summary>
+/// Indicates this entity is a handheld grinder.
+/// Entities with <see cref="ExtractableComponent"/> can be used on handheld grinders to extract their solutions.
+/// </summary>
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class HandheldGrinderComponent : Component
+{
+    /// <summary>
+    /// The length of the doAfter.
+    /// After it ends, the respective GrinderProgram is used on the contents.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public TimeSpan DoAfterDuration = TimeSpan.FromSeconds(4f);
+
+    /// <summary>
+    /// Popup to use after the current item is done processing.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public LocId FinishedPopup = "handheld-grinder-default";
+
+    /// <summary>
+    /// The sound to play when the doAfter starts.
+    /// </summary>
+    [DataField]
+    public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/Items/Culinary/mortar_grinding.ogg", AudioParams.Default.WithLoop(true));
+
+    /// <summary>
+    /// The grinder program to use.
+    /// Decides whether this one will Juice or Grind the objects.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public GrinderProgram Program = GrinderProgram.Grind;
+
+    /// <summary>
+    /// The solution into which the output reagents will go.
+    /// </summary>
+    [DataField, AutoNetworkedField]
+    public string SolutionName = "grinderOutput";
+
+    /// <summary>
+    /// Cached solution from the grinder.
+    /// </summary>
+    [ViewVariables]
+    public Entity<SolutionComponent>? GrinderSolution;
+
+    // Used to cancel the sound.
+    public EntityUid? AudioStream;
+}
index 6b8eb6f4ac103294fb5368cbe4fdf469a449265f..d884198a4cc6bf509fc2636173d0fe0fef8138ec 100644 (file)
@@ -51,4 +51,3 @@ public sealed partial class ActiveReagentGrinderComponent : Component
     [ViewVariables]
     public GrinderProgram Program;
 }
-
index b54fd1d49e9c0221de51e47b65b32a0e219f75a0..524a7a19eab46a5dceb4aa4f7aed371917d468f5 100644 (file)
@@ -65,4 +65,3 @@ public abstract class SharedReagentGrinderSystem : EntitySystem
         return ent.Comp.JuiceSolution is not null;
     }
 }
-
diff --git a/Resources/Audio/Items/Culinary/attributions.yml b/Resources/Audio/Items/Culinary/attributions.yml
new file mode 100644 (file)
index 0000000..c5c1c72
--- /dev/null
@@ -0,0 +1,9 @@
+- files: ["mortar_grinding.ogg"]
+  license: "CC0-1.0"
+  copyright: "Taken from freesound, cleaned up and sped up. Coverted to .ogg"
+  source: "https://freesound.org/people/OlyveBone/sounds/486995/"
+
+- files: ["juicer_juicing.ogg"]
+  license: "CC-BY-3.0"
+  copyright: "Taken from freesound. Converted to .ogg"
+  source: "https://freesound.org/people/Edo333/sounds/272208/"
diff --git a/Resources/Audio/Items/Culinary/juicer_juicing.ogg b/Resources/Audio/Items/Culinary/juicer_juicing.ogg
new file mode 100644 (file)
index 0000000..82a9cd3
Binary files /dev/null and b/Resources/Audio/Items/Culinary/juicer_juicing.ogg differ
diff --git a/Resources/Audio/Items/Culinary/mortar_grinding.ogg b/Resources/Audio/Items/Culinary/mortar_grinding.ogg
new file mode 100644 (file)
index 0000000..b6b3a1e
Binary files /dev/null and b/Resources/Audio/Items/Culinary/mortar_grinding.ogg differ
diff --git a/Resources/Locale/en-US/kitchen/components/handheld-grinder.ftl b/Resources/Locale/en-US/kitchen/components/handheld-grinder.ftl
new file mode 100644 (file)
index 0000000..6ab76c2
--- /dev/null
@@ -0,0 +1,6 @@
+handheld-grinder-cannot-juice = You cannot juice {THE($item)}!
+handheld-grinder-cannot-grind = You cannot grind {THE($item)}!
+
+handheld-grinder-default = You finished processing {THE($item)}.
+handheld-grinder-juiced = You finished juicing {THE($item)}.
+handheld-grinder-grinded = You finished grinding {THE($item)}.
index a6446a2cc16431f92a62a79c1fdfd210972e5804..22dba1bccfa0df218f4f23baaa32410fda440e96 100644 (file)
@@ -27,6 +27,8 @@
     DrinkMugOne: 1
     DrinkMugRainbow: 2
     DrinkMugRed: 2
+    MortarAndPestle: 1
+    HandheldJuicer: 1
   contrabandInventory:
     CandyBowl: 1
     BarSpoon: 2
index 9b68de41e49260c6b81e1ab1a6e82e7a24e273c5..04f371e4253f5cfd819bbbf0b5697b85feaf5e67 100644 (file)
@@ -17,6 +17,8 @@
     Bucket: 3
     BoxMouthSwab: 1
     BoxAgrichem: 1
+    MortarAndPestle: 1
+    HandheldJuicer: 1
     #TO DO:
     #plant analyzer
   contrabandInventory:
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Kitchen/equipment.yml b/Resources/Prototypes/Entities/Objects/Specific/Kitchen/equipment.yml
new file mode 100644 (file)
index 0000000..fa1a96a
--- /dev/null
@@ -0,0 +1,170 @@
+- type: entity
+  abstract: true
+  parent: BaseItem
+  id: BaseHandheldGrinder
+  components:
+  - type: SolutionContainerManager
+    solutions:
+      grinderOutput:
+        maxVol: 20
+  - type: SolutionTransfer
+  - type: DrawableSolution
+    solution: grinderOutput
+  - type: RefillableSolution
+    solution: grinderOutput
+  - type: DrainableSolution
+    solution: grinderOutput
+  - type: Edible
+    edible: Drink
+    solution: grinderOutput
+    destroyOnEmpty: false
+    utensil: Spoon
+  - type: MixableSolution
+    solution: grinderOutput
+  - type: ExaminableSolution
+    solution: grinderOutput
+    exactVolume: true
+  - type: SolutionItemStatus
+    solution: grinderOutput
+  - type: SolutionContainerVisuals
+    maxFillLevels: 4
+    fillBaseName: fill-
+  - type: DnaSubstanceTrace
+  - type: Damageable
+    damageContainer: Inorganic
+  - type: Spillable
+    solution: grinderOutput
+  - type: Appearance
+  - type: HandheldGrinder
+
+# Mortars
+- type: entity
+  parent: BaseHandheldGrinder
+  id: MortarAndPestle
+  name: mortar and pestle
+  description: Used for grinding small amounts of objects.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/mortar_and_pestle.rsi
+    layers:
+    - state: icon
+    - map: ["enum.SolutionContainerLayers.Fill"]
+      state: fill-1
+      visible: false
+  - type: HandheldGrinder
+    finishedPopup: handheld-grinder-grinded
+
+- type: entity
+  parent: MortarAndPestle
+  id: MortarAndPestleMakeshift
+  name: makeshift mortar and pestle
+  description: Used for grinding small amounts of objects. Inferior version made out of wood.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/mortar_and_pestle.rsi
+    layers:
+    - state: makeshift_icon
+    - map: ["enum.SolutionContainerLayers.Fill"]
+      state: fill-1
+      visible: false
+  - type: Item
+    inhandVisuals:
+      left:
+      - state: makeshift-inhand-left
+      right:
+      - state: makeshift-inhand-right
+  - type: HandheldGrinder
+    doAfterDuration: 6
+  - type: Construction
+    graph: MakeshiftMortarAndPestle
+    node: mortarAndPestle
+
+# Juicers
+- type: entity
+  parent: BaseHandheldGrinder
+  id: HandheldJuicer
+  name: handheld juicer
+  description: Used for juicing small amounts of objects.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/handheld_juicer.rsi
+    layers:
+    - state: juicer_base
+    - map: ["enum.SolutionContainerLayers.Fill"]
+      state: fill-1
+      visible: false
+    - state: cap
+  - type: HandheldGrinder
+    finishedPopup: handheld-grinder-juiced
+    sound: !type:SoundPathSpecifier
+      path: /Audio/Items/Culinary/juicer_juicing.ogg # Pasta mixing sound. Close enough.
+      params:
+        loop: true
+    program: Juice
+
+- type: entity
+  parent: HandheldJuicer
+  id: HandheldJuicerMakeshift
+  name: makeshift juicer
+  description: Used for juicing small amounts of objects. Inferior version made out of wood.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/handheld_juicer.rsi
+    layers:
+    - state: makeshift_base
+    - map: ["enum.SolutionContainerLayers.Fill"]
+      state: fill-1
+      visible: false
+    - state: cap
+  - type: Item
+    inhandVisuals:
+      left:
+      - state: makeshift-inhand-left
+      right:
+      - state: makeshift-inhand-right
+  - type: HandheldGrinder
+    doAfterDuration: 6
+  - type: Construction
+    graph: MakeshiftJuicer
+    node: juicer
+
+# Construction
+- type: entity
+  name: incomplete mortar and pestle
+  parent: BaseItem
+  id: IncompleteMortarAndPestle
+  description: A few planks of wood stuck together.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/mortar_and_pestle.rsi
+    state: makeshift_base
+  - type: Item
+    size: Normal
+    inhandVisuals:
+      left:
+      - state: makeshift-inhand-left
+      right:
+      - state: makeshift-inhand-right
+  - type: Construction
+    graph: MakeshiftMortarAndPestle
+    node: incompleteMortarAndPestle
+
+- type: entity
+  name: incomplete handheld juicer
+  parent: BaseItem
+  id: IncompleteHandheldJuicer
+  description: A some wood and plastic stuck together.
+  components:
+  - type: Sprite
+    sprite: Objects/Specific/Kitchen/handheld_juicer.rsi
+    state: makeshift_base
+  - type: Item
+    size: Normal
+    inhandVisuals:
+      left:
+      - state: makeshift-inhand-left
+      right:
+      - state: makeshift-inhand-right
+  - type: Construction
+    graph: MakeshiftJuicer
+    node: incompleteJuicer
index 6b89f3687ab2a67763238c2a1f93d1d895567bbc..bff07cddf108c711ca0fa58899ce5936c03a8297 100644 (file)
   category: construction-category-tools
   objectType: Item
 
+- type: construction
+  id: MakeshiftMortarAndPestle
+  graph: MakeshiftMortarAndPestle
+  startNode: start
+  targetNode: mortarAndPestle
+  category: construction-category-tools
+  objectType: Item
+
+- type: construction
+  id: MakeshiftJuicer
+  graph: MakeshiftJuicer
+  startNode: start
+  targetNode: juicer
+
 - type: construction
   id: MakeshiftCentrifuge
   graph: MakeshiftCentrifuge
diff --git a/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/handheld_grinders.yml b/Resources/Prototypes/Recipes/Crafting/Graphs/improvised/handheld_grinders.yml
new file mode 100644 (file)
index 0000000..c4b3356
--- /dev/null
@@ -0,0 +1,80 @@
+
+# Mortar
+- type: constructionGraph
+  id: MakeshiftMortarAndPestle
+  start: start
+  graph:
+  - node: start
+    edges:
+    - to: incompleteMortarAndPestle
+      steps:
+        - material: WoodPlank
+          amount: 5
+          doAfter: 4
+
+  - node: incompleteMortarAndPestle
+    entity: IncompleteMortarAndPestle
+    edges:
+    - to: start
+      completed:
+      - !type:SpawnPrototype
+        prototype: MaterialWoodPlank1
+        amount: 5
+      - !type:DeleteEntity {}
+      steps:
+      - tool: Prying
+        doAfter: 1
+    - to: mortarAndPestle
+      completed:
+      - !type:AdminLog
+        message: "Construction"
+        impact: High
+      steps:
+      - tool: Slicing
+        doAfter: 4
+
+  - node: mortarAndPestle
+    entity: MortarAndPestleMakeshift
+
+# Juicer
+- type: constructionGraph
+  id: MakeshiftJuicer
+  start: start
+  graph:
+  - node: start
+    edges:
+    - to: incompleteJuicer
+      steps:
+      - material: WoodPlank
+        amount: 4
+        doAfter: 2
+      - material: Plastic
+        amount: 2
+        doAfter: 2
+
+  - node: incompleteJuicer
+    entity: IncompleteHandheldJuicer
+    edges:
+    - to: start
+      completed:
+      - !type:SpawnPrototype
+        prototype: MaterialWoodPlank1
+        amount: 4
+      - !type:SpawnPrototype
+        prototype: SheetPlastic1
+        amount: 2
+      - !type:DeleteEntity {}
+      steps:
+      - tool: Prying
+        doAfter: 1
+    - to: juicer
+      completed:
+      - !type:AdminLog
+        message: "Construction"
+        impact: High
+      steps:
+      - tool: Slicing
+        doAfter: 4
+
+  - node: juicer
+    entity: HandheldJuicerMakeshift
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/cap.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/cap.png
new file mode 100644 (file)
index 0000000..042021a
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/cap.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-1.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-1.png
new file mode 100644 (file)
index 0000000..2cd73cc
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-1.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-2.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-2.png
new file mode 100644 (file)
index 0000000..58e0287
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-2.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-3.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-3.png
new file mode 100644 (file)
index 0000000..6cca57f
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-3.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-4.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-4.png
new file mode 100644 (file)
index 0000000..7c3d1e4
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/fill-4.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/icon.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/icon.png
new file mode 100644 (file)
index 0000000..3d46d6e
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-left.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..6b4f036
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-right.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..0ef90e2
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/juicer_base.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/juicer_base.png
new file mode 100644 (file)
index 0000000..f9cf206
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/juicer_base.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-left.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-left.png
new file mode 100644 (file)
index 0000000..5f4e166
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-right.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-right.png
new file mode 100644 (file)
index 0000000..a6f479c
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_base.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_base.png
new file mode 100644 (file)
index 0000000..9096457
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_base.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_icon.png b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_icon.png
new file mode 100644 (file)
index 0000000..cba2377
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/makeshift_icon.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/meta.json b/Resources/Textures/Objects/Specific/Kitchen/handheld_juicer.rsi/meta.json
new file mode 100644 (file)
index 0000000..d02803a
--- /dev/null
@@ -0,0 +1,54 @@
+{
+    "version": 1,
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "license": "CC-BY-SA-4.0",
+    "copyright": "Created by TheShuEd (Github), edited into a juicer and inhands by ScarKy0(GitHub)",
+    "states": [
+        {
+            "name": "icon"
+        },
+        {
+            "name": "makeshift_icon"
+        },
+        {
+            "name": "fill-1"
+        },
+        {
+            "name": "fill-2"
+        },
+        {
+            "name": "fill-3"
+        },
+        {
+            "name": "fill-4"
+        },
+        {
+            "name": "juicer_base"
+        },
+        {
+            "name": "cap"
+        },
+        {
+            "name": "makeshift_base"
+        },
+        {
+            "name": "inhand-right",
+            "directions": 4
+        },
+        {
+            "name": "inhand-left",
+            "directions": 4
+        },
+        {
+            "name": "makeshift-inhand-right",
+            "directions": 4
+        },
+        {
+            "name": "makeshift-inhand-left",
+            "directions": 4
+        }
+    ]
+}
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-1.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-1.png
new file mode 100644 (file)
index 0000000..2cd73cc
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-1.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-2.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-2.png
new file mode 100644 (file)
index 0000000..58e0287
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-2.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-3.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-3.png
new file mode 100644 (file)
index 0000000..26332bc
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-3.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-4.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-4.png
new file mode 100644 (file)
index 0000000..9560456
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/fill-4.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/icon.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/icon.png
new file mode 100644 (file)
index 0000000..6040513
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/icon.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-left.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-left.png
new file mode 100644 (file)
index 0000000..0d288cb
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-right.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-right.png
new file mode 100644 (file)
index 0000000..7766c9c
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-left.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-left.png
new file mode 100644 (file)
index 0000000..7e61052
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-left.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-right.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-right.png
new file mode 100644 (file)
index 0000000..26ebdd0
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift-inhand-right.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_base.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_base.png
new file mode 100644 (file)
index 0000000..0d376b4
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_base.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_icon.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_icon.png
new file mode 100644 (file)
index 0000000..7ca2e26
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/makeshift_icon.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/meta.json b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/meta.json
new file mode 100644 (file)
index 0000000..0a9173c
--- /dev/null
@@ -0,0 +1,54 @@
+{
+    "version": 1,
+    "size": {
+        "x": 32,
+        "y": 32
+    },
+    "license": "CC-BY-SA-4.0",
+    "copyright": "Created by TheShuEd (Github) | Small tweaks to fill states, makeshift and inhands by ScarKy0 (Github)",
+    "states": [
+        {
+            "name": "icon"
+        },
+        {
+            "name": "makeshift_icon"
+        },
+        {
+            "name": "fill-1"
+        },
+        {
+            "name": "fill-2"
+        },
+        {
+            "name": "fill-3"
+        },
+        {
+            "name": "fill-4"
+        },
+        {
+            "name": "mortar_base"
+        },
+        {
+            "name": "makeshift_base"
+        },
+        {
+            "name": "pestle"
+        },
+        {
+            "name": "inhand-right",
+            "directions": 4
+        },
+        {
+            "name": "inhand-left",
+            "directions": 4
+        },
+        {
+            "name": "makeshift-inhand-right",
+            "directions": 4
+        },
+        {
+            "name": "makeshift-inhand-left",
+            "directions": 4
+        }
+    ]
+}
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/mortar_base.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/mortar_base.png
new file mode 100644 (file)
index 0000000..5c128df
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/mortar_base.png differ
diff --git a/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/pestle.png b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/pestle.png
new file mode 100644 (file)
index 0000000..96a7f16
Binary files /dev/null and b/Resources/Textures/Objects/Specific/Kitchen/mortar_and_pestle.rsi/pestle.png differ