diff --git a/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderBoundUserInterface.cs b/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderBoundUserInterface.cs new file mode 100644 index 0000000000..41ae8e015e --- /dev/null +++ b/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderBoundUserInterface.cs @@ -0,0 +1,292 @@ +using System.Collections.Generic; +using Robust.Client.GameObjects.Components.UserInterface; +using Robust.Client.UserInterface; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Content.Shared.Kitchen; +using Robust.Shared.GameObjects; +using Content.Shared.Chemistry; +using Robust.Shared.IoC; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Prototypes; +using Robust.Client.GameObjects; + +namespace Content.Client.GameObjects.Components.Kitchen +{ + public class ReagentGrinderBoundUserInterface : BoundUserInterface + { + [Dependency] private readonly IEntityManager _entityManager = default!; + [Dependency] private readonly IPrototypeManager _prototypeManager = default!; + + private GrinderMenu _menu; + private Dictionary _chamberVisualContents = new Dictionary(); + private Dictionary _beakerVisualContents = new Dictionary(); + public ReagentGrinderBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) { } + + protected override void Open() + { + base.Open(); + _menu = new GrinderMenu(this); + _menu.OpenCentered(); + _menu.OnClose += Close; + _menu.GrindButton.OnPressed += args => SendMessage(new SharedReagentGrinderComponent.ReagentGrinderGrindStartMessage()); + _menu.JuiceButton.OnPressed += args => SendMessage(new SharedReagentGrinderComponent.ReagentGrinderJuiceStartMessage()); + _menu.ChamberContentBox.EjectButton.OnPressed += args => SendMessage(new SharedReagentGrinderComponent.ReagentGrinderEjectChamberAllMessage()); + _menu.BeakerContentBox.EjectButton.OnPressed += args => SendMessage(new SharedReagentGrinderComponent.ReagentGrinderEjectBeakerMessage()); + _menu.ChamberContentBox.BoxContents.OnItemSelected += args => + { + SendMessage(new SharedReagentGrinderComponent.ReagentGrinderEjectChamberContentMessage(_chamberVisualContents[args.ItemIndex])); + }; + + _menu.BeakerContentBox.BoxContents.OnItemSelected += args => + { + SendMessage(new SharedReagentGrinderComponent.ReagentGrinderVaporizeReagentIndexedMessage(_beakerVisualContents[args.ItemIndex])); + }; + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + if (!disposing) + { + return; + } + + _chamberVisualContents?.Clear(); + _beakerVisualContents?.Clear(); + _menu?.Dispose(); + } + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + if (!(state is ReagentGrinderInterfaceState cState)) + { + return; + } + _menu.BeakerContentBox.EjectButton.Disabled = !cState.HasBeakerIn; + _menu.ChamberContentBox.EjectButton.Disabled = cState.ChamberContents.Length <= 0; + _menu.GrindButton.Disabled = !cState.CanGrind || !cState.Powered; + _menu.JuiceButton.Disabled = !cState.CanJuice || !cState.Powered; + RefreshContentsDisplay(cState.ReagentQuantities, cState.ChamberContents, cState.HasBeakerIn); + } + + protected override void ReceiveMessage(BoundUserInterfaceMessage message) + { + base.ReceiveMessage(message); + switch (message) + { + case SharedReagentGrinderComponent.ReagentGrinderWorkStartedMessage workStarted: + _menu.GrindButton.Disabled = true; + _menu.GrindButton.Modulate = workStarted.GrinderProgram == SharedReagentGrinderComponent.GrinderProgram.Grind ? Color.Green : Color.White; + _menu.JuiceButton.Disabled = true; + _menu.JuiceButton.Modulate = workStarted.GrinderProgram == SharedReagentGrinderComponent.GrinderProgram.Juice ? Color.Green : Color.White; + _menu.BeakerContentBox.EjectButton.Disabled = true; + _menu.ChamberContentBox.EjectButton.Disabled = true; + break; + case SharedReagentGrinderComponent.ReagentGrinderWorkCompleteMessage doneMessage: + _menu.GrindButton.Disabled = false; + _menu.JuiceButton.Disabled = false; + _menu.GrindButton.Modulate = Color.White; + _menu.JuiceButton.Modulate = Color.White; + _menu.BeakerContentBox.EjectButton.Disabled = false; + _menu.ChamberContentBox.EjectButton.Disabled = false; + break; + } + } + + private void RefreshContentsDisplay(IList reagents, IReadOnlyList containedSolids, bool isBeakerAttached) + { + //Refresh chamber contents + _chamberVisualContents.Clear(); + _menu.ChamberContentBox.BoxContents.Clear(); + foreach (var uid in containedSolids) + { + if (!_entityManager.TryGetEntity(uid, out var entity)) + { + return; + } + var texture = entity.GetComponent().Icon?.Default; + + var solidItem = _menu.ChamberContentBox.BoxContents.AddItem(entity.Name, texture); + var solidIndex = _menu.ChamberContentBox.BoxContents.IndexOf(solidItem); + _chamberVisualContents.Add(solidIndex, uid); + } + + //Refresh beaker contents + _beakerVisualContents.Clear(); + _menu.BeakerContentBox.BoxContents.Clear(); + //if no beaker is attached use this guard to prevent hitting a null reference. + if (!isBeakerAttached || reagents == null) + { + return; + } + + //Looks like we have a beaker attached. + if (reagents.Count <= 0) + { + _menu.BeakerContentBox.BoxContents.AddItem(Loc.GetString("Empty")); + } + else + { + for (var i = 0; i < reagents.Count; i++) + { + var goodIndex = _prototypeManager.TryIndex(reagents[i].ReagentId, out ReagentPrototype proto); + var reagentName = goodIndex ? Loc.GetString($"{reagents[i].Quantity} {proto.Name}") : Loc.GetString("???"); + var reagentAdded = _menu.BeakerContentBox.BoxContents.AddItem(reagentName); + var reagentIndex = _menu.BeakerContentBox.BoxContents.IndexOf(reagentAdded); + _beakerVisualContents.Add(reagentIndex, reagents[i]); + } + } + } + + public class GrinderMenu : SS14Window + { + /*The contents of the chamber and beaker will both be vertical scroll rectangles. + * Will have a vsplit to split the g/j buttons from the contents menu. + * |--------------------------------\ + * | | Chamber [E] Beaker [E] | + * | [G] | | | | | | + * | | | | | | | + * | | | | | | | + * | [J] | |-----| |-----| | + * | | | + * \---------------------------------/ + * + */ + + private ReagentGrinderBoundUserInterface Owner { get; set; } + protected override Vector2? CustomSize => (512, 256); + + //We'll need 4 buttons, grind, juice, eject beaker, eject the chamber contents. + //The other 2 are referenced in the Open function. + public Button GrindButton { get; } + public Button JuiceButton { get; } + + public LabelledContentBox ChamberContentBox { get; } + public LabelledContentBox BeakerContentBox { get; } + + public sealed class LabelledContentBox : VBoxContainer + { + public string LabelText { get; set; } + public ItemList BoxContents { get; set; } + + public Button EjectButton { get; set; } + + private Label _label; + + public LabelledContentBox(string labelText, string buttonText) + { + + _label = new Label + { + Text = labelText, + Align = Label.AlignMode.Center, + }; + + EjectButton = new Button + { + Text = buttonText, + TextAlign = Label.AlignMode.Center, + }; + + var vSplit = new HSplitContainer + { + Children = + { + _label, + EjectButton + } + }; + + AddChild(vSplit); + BoxContents = new ItemList + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SelectMode = ItemList.ItemListSelectMode.Button, + SizeFlagsStretchRatio = 2, + CustomMinimumSize = (100, 128) + }; + AddChild(BoxContents); + } + } + + public GrinderMenu(ReagentGrinderBoundUserInterface owner = null) + { + Owner = owner; + Title = Loc.GetString("All-In-One Grinder 3000"); + + var hSplit = new HBoxContainer + { + SizeFlagsHorizontal = SizeFlags.Fill, + SizeFlagsVertical = SizeFlags.Fill + }; + + var vBoxGrindJuiceButtonPanel = new VBoxContainer + { + SizeFlagsVertical = SizeFlags.ShrinkCenter + }; + + GrindButton = new Button + { + Text = Loc.GetString("Grind"), + TextAlign = Label.AlignMode.Center, + CustomMinimumSize = (64, 64) + }; + + JuiceButton = new Button + { + Text = Loc.GetString("Juice"), + TextAlign = Label.AlignMode.Center, + CustomMinimumSize = (64, 64) + }; + + vBoxGrindJuiceButtonPanel.AddChild(GrindButton); + //inner button padding + vBoxGrindJuiceButtonPanel.AddChild(new Control + { + CustomMinimumSize = (0, 16), + }); + vBoxGrindJuiceButtonPanel.AddChild(JuiceButton); + + ChamberContentBox = new LabelledContentBox(Loc.GetString("Chamber"), Loc.GetString("Eject Contents")) + { + //Modulate = Color.Red, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 2, + + }; + + BeakerContentBox = new LabelledContentBox(Loc.GetString("Beaker"), Loc.GetString("Eject Beaker")) + { + //Modulate = Color.Blue, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 2, + }; + + hSplit.AddChild(vBoxGrindJuiceButtonPanel); + + //Padding between the g/j buttons panel and the itemlist boxes panel. + hSplit.AddChild(new Control + { + CustomMinimumSize = (16, 0), + }); + hSplit.AddChild(ChamberContentBox); + + //Padding between the two itemlists. + hSplit.AddChild(new Control + { + CustomMinimumSize = (8, 0), + }); + hSplit.AddChild(BeakerContentBox); + Contents.AddChild(hSplit); + } + } + } +} diff --git a/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderVisualizer.cs b/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderVisualizer.cs new file mode 100644 index 0000000000..aed64cad27 --- /dev/null +++ b/Content.Client/GameObjects/Components/Kitchen/ReagentGrinderVisualizer.cs @@ -0,0 +1,17 @@ +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.GameObjects.Components; +using static Content.Shared.Kitchen.SharedReagentGrinderComponent; + +namespace Content.Client.GameObjects.Components.Kitchen +{ + public class ReagentGrinderVisualizer : AppearanceVisualizer + { + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + var sprite = component.Owner.GetComponent(); + component.TryGetData(ReagentGrinderVisualState.BeakerAttached, out bool hasBeaker); + sprite.LayerSetState(0, $"juicer{(hasBeaker ? "1" : "0")}"); + } + } +} diff --git a/Content.Client/IgnoredComponents.cs b/Content.Client/IgnoredComponents.cs index 9833230e94..816f88f7d3 100644 --- a/Content.Client/IgnoredComponents.cs +++ b/Content.Client/IgnoredComponents.cs @@ -209,6 +209,9 @@ "CrematoriumEntityStorage", "RandomArcade", "RandomSpriteState", + "ReagentGrinder", + "Grindable", + "Juiceable", "WelderRefinable", "ConveyorAssembly", "TwoWayLever", diff --git a/Content.Server/GameObjects/Components/Kitchen/GrindableComponent.cs b/Content.Server/GameObjects/Components/Kitchen/GrindableComponent.cs new file mode 100644 index 0000000000..a0d484260d --- /dev/null +++ b/Content.Server/GameObjects/Components/Kitchen/GrindableComponent.cs @@ -0,0 +1,13 @@ +using Robust.Shared.GameObjects; + +namespace Content.Server.GameObjects.Components.Kitchen +{ + /// + /// Tag component that denotes an entity as Grindable by the reagentgrinder. + /// + [RegisterComponent] + public class GrindableComponent : Component + { + public override string Name => "Grindable"; + } +} diff --git a/Content.Server/GameObjects/Components/Kitchen/JuiceableComponent.cs b/Content.Server/GameObjects/Components/Kitchen/JuiceableComponent.cs new file mode 100644 index 0000000000..bb4ae5a6a7 --- /dev/null +++ b/Content.Server/GameObjects/Components/Kitchen/JuiceableComponent.cs @@ -0,0 +1,23 @@ +using Content.Shared.Chemistry; +using Robust.Shared.GameObjects; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Kitchen +{ + /// + /// Tag component that denotes an entity as Juiceable + /// + [RegisterComponent] + public class JuiceableComponent : Component + { + public override string Name => "Juiceable"; + [ViewVariables] public Solution JuiceResultSolution; + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(this, x => x.JuiceResultSolution, "result", new Solution()); + + } + } +} diff --git a/Content.Server/GameObjects/Components/Kitchen/ReagentGrinderComponent.cs b/Content.Server/GameObjects/Components/Kitchen/ReagentGrinderComponent.cs new file mode 100644 index 0000000000..c0b9cd6fc1 --- /dev/null +++ b/Content.Server/GameObjects/Components/Kitchen/ReagentGrinderComponent.cs @@ -0,0 +1,375 @@ +#nullable enable +using System; +using System.Linq; +using System.Threading.Tasks; +using Content.Server.GameObjects.Components.Chemistry; +using Content.Server.GameObjects.Components.GUI; +using Content.Server.GameObjects.Components.Items.Storage; +using Content.Server.GameObjects.Components.Power.ApcNetComponents; +using Content.Server.Interfaces.GameObjects.Components.Items; +using Content.Server.Utility; +using Content.Shared.Chemistry; +using Content.Shared.Interfaces; +using Content.Shared.Interfaces.GameObjects.Components; +using Content.Shared.Kitchen; +using Content.Shared.Utility; +using Robust.Server.GameObjects; +using Robust.Server.GameObjects.Components.Container; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.GameObjects.EntitySystems; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.Audio; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.Timers; +using Robust.Shared.GameObjects.Systems; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Localization; +using Robust.Shared.Serialization; +using Robust.Shared.ViewVariables; + +namespace Content.Server.GameObjects.Components.Kitchen +{ + + /// + /// The combo reagent grinder/juicer. The reason why grinding and juicing are seperate is simple, + /// think of grinding as a utility to break an object down into its reagents. Think of juicing as + /// converting something into its single juice form. E.g, grind an apple and get the nutriment and sugar + /// it contained, juice an apple and get "apple juice". + /// + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + public class ReagentGrinderComponent : SharedReagentGrinderComponent, IActivate, IInteractUsing + { + private AudioSystem _audioSystem = default!; + [ViewVariables] private ContainerSlot _beakerContainer = default!; + + /// + /// Can be null since we won't always have a beaker in the grinder. + /// + [ViewVariables] private SolutionContainerComponent? _heldBeaker = default!; + + /// + /// Contains the things that are going to be ground or juiced. + /// + [ViewVariables] private Container _chamber = default!; + + [ViewVariables] private bool ChamberEmpty => _chamber.ContainedEntities.Count <= 0; + [ViewVariables] private bool HasBeaker => _beakerContainer.ContainedEntity != null; + [ViewVariables] private BoundUserInterface? UserInterface => Owner.GetUIOrNull(ReagentGrinderUiKey.Key); + + private bool Powered => !Owner.TryGetComponent(out PowerReceiverComponent? receiver) || receiver.Powered; + + /// + /// Should the BoundUI be told to update? + /// + private bool _uiDirty = true; + /// + /// Is the machine actively doing something and can't be used right now? + /// + private bool _busy = false; + + //YAML serialization vars + [ViewVariables(VVAccess.ReadWrite)] private int _storageCap = 16; + [ViewVariables(VVAccess.ReadWrite)] private int _workTime = 3500; //3.5 seconds, completely arbitrary for now. + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref _storageCap, "chamberCapacity", 16); + serializer.DataField(ref _workTime, "workTime", 3500); + } + + public override void Initialize() + { + base.Initialize(); + //A slot for the beaker where the grounds/juices will go. + _beakerContainer = + ContainerManagerComponent.Ensure($"{Name}-reagentContainerContainer", Owner); + + //A container for the things that WILL be ground/juiced. Useful for ejecting them instead of deleting them from the hands of the user. + _chamber = + ContainerManagerComponent.Ensure($"{Name}-entityContainerContainer", Owner); + + if (UserInterface != null) + { + UserInterface.OnReceiveMessage += UserInterfaceOnReceiveMessage; + } + + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged += OnPowerStateChanged; + } + + _audioSystem = EntitySystem.Get(); + } + + public override void OnRemove() + { + base.OnRemove(); + if (UserInterface != null) + { + UserInterface.OnReceiveMessage -= UserInterfaceOnReceiveMessage; + } + + if (Owner.TryGetComponent(out PowerReceiverComponent? receiver)) + { + receiver.OnPowerStateChanged -= OnPowerStateChanged; + } + } + + private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message) + { + if(_busy) + { + return; + } + + switch(message.Message) + { + case ReagentGrinderGrindStartMessage msg: + if (!Powered) break; + ClickSound(); + DoWork(message.Session.AttachedEntity!, GrinderProgram.Grind); + break; + + case ReagentGrinderJuiceStartMessage msg: + if (!Powered) break; + ClickSound(); + DoWork(message.Session.AttachedEntity!, GrinderProgram.Juice); + break; + + case ReagentGrinderEjectChamberAllMessage msg: + if(!ChamberEmpty) + { + ClickSound(); + for (var i = _chamber.ContainedEntities.Count - 1; i >= 0; i--) + { + EjectSolid(_chamber.ContainedEntities.ElementAt(i).Uid); + } + } + break; + + case ReagentGrinderEjectChamberContentMessage msg: + if (!ChamberEmpty) + { + EjectSolid(msg.EntityID); + ClickSound(); + _uiDirty = true; + } + break; + + case ReagentGrinderEjectBeakerMessage msg: + ClickSound(); + EjectBeaker(message.Session.AttachedEntity); + //EjectBeaker will dirty the UI for us, we don't have to do it explicitly here. + break; + } + } + + private void OnPowerStateChanged(object? sender, PowerStateEventArgs e) + { + _uiDirty = true; + } + + private void ClickSound() + { + _audioSystem.PlayFromEntity("/Audio/Machines/machine_switch.ogg", Owner, AudioParams.Default.WithVolume(-2f)); + } + + private void SetAppearance() + { + if (Owner.TryGetComponent(out AppearanceComponent? appearance)) + { + appearance.SetData(ReagentGrinderVisualState.BeakerAttached, HasBeaker); + } + } + + public void OnUpdate() + { + if(_uiDirty) + { + UpdateInterface(); + _uiDirty = false; + } + } + + // This doesn't check for UI dirtiness so handle that when calling this. + private void UpdateInterface() + { + bool canJuice = false; + bool canGrind = false; + if (HasBeaker) + { + foreach (var entity in _chamber.ContainedEntities) + { + if (!canJuice && entity.HasComponent()) canJuice = true; + if (!canGrind && entity.HasComponent()) canGrind = true; + if (canJuice && canGrind) break; + } + } + + UserInterface?.SetState(new ReagentGrinderInterfaceState + ( + _busy, + HasBeaker, + Powered, + canJuice, + canGrind, + _chamber.ContainedEntities.Select(item => item.Uid).ToArray(), + //Remember the beaker can be null! + _heldBeaker?.Solution.Contents.ToArray() + )); + _uiDirty = false; + } + + private void EjectSolid(EntityUid entityID) + { + if (_busy) + return; + + if (Owner.EntityManager.TryGetEntity(entityID, out var entity)) + { + _chamber.Remove(entity); + + //Give the ejected entity a tiny bit of offset so each one is apparent in case of a big stack, + //but (hopefully) not enough to clip it through a solid (wall). + entity.RandomOffset(0.4f); + } + _uiDirty = true; + } + + /// + /// Tries to eject whatever is in the beaker slot. Puts the item in the user's hands or failing that on top + /// of the grinder. + /// + private void EjectBeaker(IEntity? user) + { + if (!HasBeaker || _heldBeaker == null || _busy) + return; + + _beakerContainer.Remove(_beakerContainer.ContainedEntity); + + if (user == null || !user.TryGetComponent(out var hands) || !_heldBeaker.Owner.TryGetComponent(out var item)) + return; + hands.PutInHandOrDrop(item); + + _heldBeaker = null; + _uiDirty = true; + SetAppearance(); + } + + void IActivate.Activate(ActivateEventArgs eventArgs) + { + if (!eventArgs.User.TryGetComponent(out IActorComponent? actor)) + { + return; + } + _uiDirty = true; + UserInterface?.Toggle(actor.playerSession); + } + + public async Task InteractUsing(InteractUsingEventArgs eventArgs) + { + if (!eventArgs.User.TryGetComponent(out IHandsComponent? hands)) + { + Owner.PopupMessage(eventArgs.User, Loc.GetString("You have no hands.")); + return true; + } + + IEntity heldEnt = eventArgs.Using; + + //First, check if user is trying to insert a beaker. + //No promise it will be a beaker right now, but whatever. + //Maybe this should whitelist "beaker" in the prototype id of heldEnt? + if(heldEnt.TryGetComponent(out SolutionContainerComponent? beaker) && beaker.Capabilities.HasFlag(SolutionContainerCaps.FitsInDispenser)) + { + _beakerContainer.Insert(heldEnt); + _heldBeaker = beaker; + _uiDirty = true; + //We are done, return. Insert the beaker and exit! + SetAppearance(); + ClickSound(); + return true; + } + + //Next, see if the user is trying to insert something they want to be ground/juiced. + if(!heldEnt.TryGetComponent(out GrindableComponent? grind) && !heldEnt.TryGetComponent(out JuiceableComponent? juice)) + { + //Entity did NOT pass the whitelist for grind/juice. + //Wouldn't want the clown grinding up the Captain's ID card now would you? + //Why am I asking you? You're biased. + return false; + } + + //Cap the chamber. Don't want someone putting in 500 entities and ejecting them all at once. + //Maybe I should have done that for the microwave too? + if (_chamber.ContainedEntities.Count >= _storageCap) + { + return false; + } + + if (!_chamber.Insert(heldEnt)) + return false; + + _uiDirty = true; + return true; + } + + /// + /// The wzhzhzh of the grinder. Processes the contents of the grinder and puts the output in the beaker. + /// + /// true for wanting to juice, false for wanting to grind. + private async void DoWork(IEntity user, GrinderProgram program) + { + //Have power, are we busy, chamber has anything to grind, a beaker for the grounds to go? + if(!Powered || _busy || ChamberEmpty || !HasBeaker || _heldBeaker == null) + { + return; + } + + _busy = true; + + UserInterface?.SendMessage(new ReagentGrinderWorkStartedMessage(program)); + switch (program) + { + case GrinderProgram.Grind: + _audioSystem.PlayFromEntity("/Audio/Machines/blender.ogg", Owner, AudioParams.Default); + //Get each item inside the chamber and get the reagents it contains. Transfer those reagents to the beaker, given we have one in. + Owner.SpawnTimer(_workTime, (Action) (() => + { + foreach (var item in _chamber.ContainedEntities.ToList()) + { + if (!item.HasComponent()) continue; + if (!item.TryGetComponent(out var solution)) continue; + if (_heldBeaker.CurrentVolume + solution.CurrentVolume > _heldBeaker.MaxVolume) continue; + _heldBeaker.TryAddSolution(solution.Solution); + solution.RemoveAllSolution(); + item.Delete(); + } + + _busy = false; + _uiDirty = true; + UserInterface?.SendMessage(new ReagentGrinderWorkCompleteMessage()); + })); + break; + + case GrinderProgram.Juice: + _audioSystem.PlayFromEntity("/Audio/Machines/juicer.ogg", Owner, AudioParams.Default); + Owner.SpawnTimer(_workTime, (Action) (() => + { + foreach (var item in _chamber.ContainedEntities.ToList()) + { + if (!item.TryGetComponent(out var juiceMe)) continue; + if (_heldBeaker.CurrentVolume + juiceMe.JuiceResultSolution.TotalVolume > _heldBeaker.MaxVolume) continue; + _heldBeaker.TryAddSolution(juiceMe.JuiceResultSolution); + item.Delete(); + } + UserInterface?.SendMessage(new ReagentGrinderWorkCompleteMessage()); + _busy = false; + _uiDirty = true; + })); + break; + } + } + } +} diff --git a/Content.Server/GameObjects/EntitySystems/ReagentGrinderSystem.cs b/Content.Server/GameObjects/EntitySystems/ReagentGrinderSystem.cs new file mode 100644 index 0000000000..85a4682d4b --- /dev/null +++ b/Content.Server/GameObjects/EntitySystems/ReagentGrinderSystem.cs @@ -0,0 +1,19 @@ +using Content.Server.GameObjects.Components.Kitchen; +using JetBrains.Annotations; +using Robust.Shared.GameObjects.Systems; + +namespace Content.Server.GameObjects.EntitySystems +{ + [UsedImplicitly] + internal sealed class ReagentGrinderSystem : EntitySystem + { + public override void Update(float frameTime) + { + base.Update(frameTime); + foreach (var comp in ComponentManager.EntityQuery()) + { + comp.OnUpdate(); + } + } + } +} diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index 8e1c89dd5e..7d4905c7f0 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -85,6 +85,7 @@ public const uint GAS_TANK = 1079; public const uint SINGULARITY = 1080; public const uint CHARACTERINFO = 1081; + public const uint REAGENT_GRINDER = 1082; // Net IDs for integration tests. public const uint PREDICTION_TEST = 10001; diff --git a/Content.Shared/Kitchen/SharedReagentGrinderComponent.cs b/Content.Shared/Kitchen/SharedReagentGrinderComponent.cs new file mode 100644 index 0000000000..6aa00b33ea --- /dev/null +++ b/Content.Shared/Kitchen/SharedReagentGrinderComponent.cs @@ -0,0 +1,126 @@ +using System; +using Content.Shared.Chemistry; +using Content.Shared.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Serialization; + +namespace Content.Shared.Kitchen +{ + public abstract class SharedReagentGrinderComponent : Component + { + public override string Name => "ReagentGrinder"; + public override uint? NetID => ContentNetIDs.REAGENT_GRINDER; + + [Serializable, NetSerializable] + public class ReagentGrinderGrindStartMessage : BoundUserInterfaceMessage + { + public ReagentGrinderGrindStartMessage() + { + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderJuiceStartMessage : BoundUserInterfaceMessage + { + public ReagentGrinderJuiceStartMessage() + { + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderEjectChamberAllMessage : BoundUserInterfaceMessage + { + public ReagentGrinderEjectChamberAllMessage() + { + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderEjectBeakerMessage : BoundUserInterfaceMessage + { + public ReagentGrinderEjectBeakerMessage() + { + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderEjectChamberContentMessage : BoundUserInterfaceMessage + { + public EntityUid EntityID; + public ReagentGrinderEjectChamberContentMessage(EntityUid entityID) + { + EntityID = entityID; + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderVaporizeReagentIndexedMessage : BoundUserInterfaceMessage + { + public Solution.ReagentQuantity ReagentQuantity; + public ReagentGrinderVaporizeReagentIndexedMessage(Solution.ReagentQuantity reagentQuantity) + { + ReagentQuantity = reagentQuantity; + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderWorkStartedMessage : BoundUserInterfaceMessage + { + public GrinderProgram GrinderProgram; + public ReagentGrinderWorkStartedMessage(GrinderProgram grinderProgram) + { + GrinderProgram = grinderProgram; + } + } + + [Serializable, NetSerializable] + public class ReagentGrinderWorkCompleteMessage : BoundUserInterfaceMessage + { + public ReagentGrinderWorkCompleteMessage() + { + } + } + + [Serializable, NetSerializable] + public enum ReagentGrinderVisualState : byte + { + BeakerAttached + } + + [NetSerializable, Serializable] + public enum ReagentGrinderUiKey : byte + { + Key + } + + [Serializable, NetSerializable] + public enum GrinderProgram : byte + { + Grind, + Juice + } + } + + [NetSerializable, Serializable] + public sealed class ReagentGrinderInterfaceState : BoundUserInterfaceState + { + public bool IsBusy; + public bool HasBeakerIn; + public bool Powered; + public bool CanJuice; + public bool CanGrind; + public EntityUid[] ChamberContents; + public Solution.ReagentQuantity[] ReagentQuantities; + public ReagentGrinderInterfaceState(bool isBusy, bool hasBeaker, bool powered, bool canJuice, bool canGrind, EntityUid[] chamberContents, Solution.ReagentQuantity[] heldBeakerContents) + { + IsBusy = isBusy; + HasBeakerIn = hasBeaker; + Powered = powered; + CanJuice = canJuice; + CanGrind = canGrind; + ChamberContents = chamberContents; + ReagentQuantities = heldBeakerContents; + } + } +} diff --git a/Resources/Audio/Machines/blender.ogg b/Resources/Audio/Machines/blender.ogg new file mode 100644 index 0000000000..72dd92af3b Binary files /dev/null and b/Resources/Audio/Machines/blender.ogg differ diff --git a/Resources/Audio/Machines/juicer.ogg b/Resources/Audio/Machines/juicer.ogg new file mode 100644 index 0000000000..4d6877e7a8 Binary files /dev/null and b/Resources/Audio/Machines/juicer.ogg differ diff --git a/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml new file mode 100644 index 0000000000..1ae18690ce --- /dev/null +++ b/Resources/Prototypes/Entities/Constructible/Specific/Cooking/reagent_grinder.yml @@ -0,0 +1,35 @@ +- type: entity + id: KitchenReagentGrinder + name: reagent grinder + suffix: grinder/juicer + placement: + mode: SnapgridCenter + components: + - type: SnapGrid + offset: Center + - type: ReagentGrinder + - type: UserInterface + interfaces: + - key: enum.ReagentGrinderUiKey.Key + type: ReagentGrinderBoundUserInterface + - type: Appearance + visuals: + - type: ReagentGrinderVisualizer + - type: Clickable + - type: InteractionOutline + - type: PowerReceiver + - type: LoopingSound + - type: Physics + shapes: + - !type:PhysShapeAabb + bounds: "-0.35,-0.08,0.25,0.15" + layer: + - Opaque + - Impassable + - MobImpassable + - VaultImpassable + - type: Sprite + netsync: false + sprite: Constructible/Power/juicer.rsi + state: juicer0 + drawdepth: Items diff --git a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml index 64905e33a4..def7c602af 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/botany.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/botany.yml @@ -27,6 +27,7 @@ Quantity: 5 - type: Produce seed: wheat + - type: Grindable - type: entity name: sugarcane @@ -46,6 +47,7 @@ Quantity: 5 - type: Produce seed: sugarcane + - type: Grindable - type: entity name: tower-cap log @@ -79,6 +81,12 @@ sprite: Objects/Specific/Hydroponics/banana.rsi - type: Produce seed: banana + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.BananaJuice + Quantity: 10 - type: entity name: carrot @@ -96,6 +104,12 @@ sprite: Objects/Specific/Hydroponics/carrot.rsi - type: Produce seed: carrots + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.CarrotJuice + Quantity: 10 - type: entity name: lemon @@ -113,6 +127,12 @@ sprite: Objects/Specific/Hydroponics/lemon.rsi - type: Produce seed: lemon + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.LimeJuice + Quantity: 10 - type: entity name: potato @@ -130,6 +150,12 @@ sprite: Objects/Specific/Hydroponics/potato.rsi - type: Produce seed: potato + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.PotatoJuice + Quantity: 10 - type: entity name: tomato @@ -147,6 +173,12 @@ sprite: Objects/Specific/Hydroponics/tomato.rsi - type: Produce seed: tomato + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.TomatoJuice + Quantity: 10 - type: entity name: eggplant @@ -164,6 +196,7 @@ sprite: Objects/Specific/Hydroponics/eggplant.rsi - type: Produce seed: eggplant + - type: Grindable - type: entity name: apple @@ -181,6 +214,12 @@ sprite: Objects/Specific/Hydroponics/apple.rsi - type: Produce seed: apple + - type: Grindable + - type: Juiceable + result: + reagents: + - ReagentId: chem.AppleJuice + Quantity: 10 - type: entity name: ear of corn @@ -199,6 +238,7 @@ sprite: Objects/Specific/Hydroponics/corn.rsi - type: Produce seed: corn + - type: Grindable - type: entity name: chanterelle cluster @@ -216,3 +256,4 @@ sprite: Objects/Specific/Hydroponics/chanterelle.rsi - type: Produce seed: chanterelle + - type: Grindable diff --git a/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml b/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml index d8255085c6..15a843e3c8 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/drinks.yml @@ -165,11 +165,17 @@ - type: entity parent: DrinkGlassBase - id: DrinkBerryjJice + id: DrinkBerryJuice name: berry juice description: A delicious blend of several different kinds of berries. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.BerryJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/berryjuice.rsi @@ -252,6 +258,12 @@ description: Has a uniquely sweet flavour of concentrated carrots. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.CarrotJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/carrotjuice.rsi @@ -564,6 +576,12 @@ description: The sweet-sour juice of limes. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.LimeJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/glass_green.rsi @@ -575,9 +593,31 @@ description: Liquid extract of the orange tree fruit, produced by squeezing or reaming oranges. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.OrangeJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/glass_orange.rsi +- type: entity + parent: DrinkGlassBase + id: DrinkGlassYellow + name: lemon juice + description: Used to make lemonade, soft drinks, and cocktails. + components: + - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.LemonJuice + Quantity: 20 + - type: Sprite + sprite: Objects/Consumable/Drinks/glass_yellow.rsi + - type: entity parent: DrinkGlassBase @@ -586,6 +626,12 @@ description: Juice made from tomatoes, usually used as a beverage, either plain or in cocktails components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.TomatoJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/glass_red.rsi @@ -605,18 +651,6 @@ - type: Sprite sprite: Objects/Consumable/Drinks/glass_white.rsi - -- type: entity - parent: DrinkGlassBase - id: DrinkGlassYellow - name: lemon juice - description: '' - components: - - type: Drink - - type: Sprite - sprite: Objects/Consumable/Drinks/glass_yellow.rsi - - - type: entity parent: DrinkGlassBase id: DrinkGoldschlagerGlass @@ -635,6 +669,12 @@ description: The juice is often sold in stores or fermented and made into wine, brandy, or vinegar. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.GrapeJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/grapejuice.rsi @@ -903,6 +943,12 @@ description: Used to make lemonade, soft drinks, and cocktails. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.LemonJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/lemonjuice.rsi @@ -914,6 +960,14 @@ description: A tangy substance made of lime and lemon. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.LemonJuice + Quantity: 10 + - ReagentId: chem.LimeJuice + Quantity: 10 - type: Sprite sprite: Objects/Consumable/Drinks/lemonlime.rsi @@ -925,6 +979,12 @@ description: The sweet-sour juice of limes. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.LimeJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/limejuice.rsi @@ -1100,6 +1160,12 @@ description: Liquid extract of the orange tree fruit, produced by squeezing or reaming oranges. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.OrangeJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/orangejuice.rsi @@ -1122,6 +1188,12 @@ description: A tasty juice blended from various kinds of very deadly and toxic berries. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.PoisonBerryJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/poisonberryjuice.rsi @@ -1521,9 +1593,15 @@ parent: DrinkGlassBase id: DrinkTomatoJuice name: tomato juice - description: Juice made from tomatoes, usually used as a beverage, either plain or in cocktails + description: Juice made from tomatoes, usually used as a beverage, either plain or in cocktails. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.TomatoJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/tomatojuice.rsi @@ -1612,6 +1690,12 @@ description: Delicious juice made from watermelon. components: - type: Drink + - type: SolutionContainer + maxVol: 20 + contents: + reagents: + - ReagentId: chem.WatermelonJuice + Quantity: 20 - type: Sprite sprite: Objects/Consumable/Drinks/watermelon.rsi diff --git a/Resources/Prototypes/Entities/Objects/Consumable/food.yml b/Resources/Prototypes/Entities/Objects/Consumable/food.yml index 0467526a1e..84197458e6 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/food.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/food.yml @@ -35,7 +35,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/4no_raisins.rsi - + - type: Grindable - type: Item sprite: Objects/Consumable/Food/4no_raisins.rsi @@ -53,6 +53,7 @@ trash: TrashSnackBowl - type: Sprite sprite: Objects/Consumable/Food/aesirsalad.rsi + - type: Grindable - type: entity @@ -68,6 +69,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/amanita_pie.rsi + - type: Grindable - type: entity @@ -85,6 +87,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/amanitajelly.rsi + - type: Grindable #- type: entity @@ -115,6 +118,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/apple_cake_slice.rsi + - type: Grindable - type: entity @@ -130,6 +134,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/apple_pie.rsi + - type: Grindable # TODO: BREADSLICE? @@ -159,6 +164,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/badrecipe.rsi + - type: Grindable - type: entity @@ -174,6 +180,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/baguette.rsi + - type: Grindable - type: entity @@ -191,6 +198,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/breadslice.rsi + - type: Grindable - type: entity @@ -208,6 +216,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/bananabreadslice.rsi + - type: Grindable - type: entity @@ -226,6 +235,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/pie.rsi + - type: Grindable #- type: entity @@ -256,6 +266,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/beetsoup.rsi + - type: Grindable - type: entity @@ -273,6 +284,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/berryclafoutis.rsi + - type: Grindable - type: entity @@ -290,6 +302,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/birthday_cake_slice.rsi + - type: Grindable - type: entity @@ -307,6 +320,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/spaghettiboiled.rsi + - type: Grindable - type: entity @@ -324,6 +338,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/brain_cake_slice.rsi + - type: Grindable - type: entity @@ -341,9 +356,9 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/candy.rsi - - type: Item sprite: Objects/Consumable/Food/candy.rsi + - type: Grindable - type: entity name: candy corn @@ -358,6 +373,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/candy_corn.rsi + - type: Grindable - type: entity @@ -375,6 +391,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/carrotcake_slice.rsi + - type: Grindable - type: entity @@ -392,6 +409,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/carrotfries.rsi + - type: Grindable - type: entity @@ -409,6 +427,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/chawanmushi.rsi + - type: Grindable - type: entity @@ -424,9 +443,9 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/cheeseburger.rsi - - type: Item sprite: Objects/Consumable/Food/cheeseburger.rsi + - type: Grindable - type: entity name: cheesecake (slice) @@ -443,6 +462,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/cheesecake_slice.rsi + - type: Grindable - type: entity @@ -458,6 +478,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/cheesewedge.rsi + - type: Grindable - type: entity @@ -475,6 +496,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/cheesie_honkers.rsi + - type: Grindable - type: entity @@ -492,6 +514,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/cheesyfries.rsi + - type: Grindable - type: entity @@ -507,6 +530,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/cherrypie.rsi + - type: Grindable - type: entity @@ -524,9 +548,9 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/chips.rsi - - type: Item sprite: Objects/Consumable/Food/chips.rsi + - type: Grindable - type: entity name: chocolate bar @@ -543,6 +567,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/chocolatebar.rsi + - type: Grindable - type: entity @@ -560,6 +585,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/chocolatecake_slice.rsi + - type: Grindable - type: entity @@ -575,6 +601,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/chocolateegg.rsi + - type: Grindable - type: entity @@ -590,9 +617,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/clownburger.rsi - - type: Item sprite: Objects/Consumable/Food/clownburger.rsi + - type: Grindable - type: entity name: clown's tears @@ -607,6 +634,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/clownstears.rsi + - type: Grindable #- type: entity @@ -638,6 +666,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/coldchili.rsi + - type: Grindable #- type: entity @@ -667,6 +696,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/cookie!!!.rsi + - type: Grindable - type: entity @@ -682,6 +712,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/cracker.rsi + - type: Grindable - type: entity @@ -699,6 +730,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/creamcheesebreadslice.rsi + - type: Grindable - type: entity @@ -716,6 +748,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/cubancarp.rsi + - type: Grindable #- type: entity @@ -745,6 +778,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/donkpocket.rsi + - type: Grindable - type: entity @@ -760,9 +794,9 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/donut1.rsi - - type: Item sprite: Objects/Consumable/Food/donut1.rsi + - type: Grindable - type: entity parent: FoodBase @@ -777,9 +811,9 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/donut2.rsi - - type: Item sprite: Objects/Consumable/Food/donut2.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -794,9 +828,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-blue.rsi - - type: Item sprite: Objects/Consumable/Food/egg-blue.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -811,9 +845,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-green.rsi - - type: Item sprite: Objects/Consumable/Food/egg-green.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -828,9 +862,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-mime.rsi - - type: Item sprite: Objects/Consumable/Food/egg-mime.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -845,9 +879,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-orange.rsi - - type: Item sprite: Objects/Consumable/Food/egg-orange.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -862,9 +896,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-purple.rsi - - type: Item sprite: Objects/Consumable/Food/egg-purple.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -879,9 +913,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-rainbow.rsi - - type: Item sprite: Objects/Consumable/Food/egg-rainbow.rsi.rsi + - type: Grindable - type: entity parent: FoodBase @@ -896,9 +930,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-red.rsi - - type: Item sprite: Objects/Consumable/Food/egg-red.rsi.rsi + - type: Grindable - type: entity @@ -914,9 +948,9 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/egg-yellow.rsi - - type: Item sprite: Objects/Consumable/Food/egg-yellow.rsi + - type: Grindable - type: entity parent: FoodBase @@ -935,11 +969,12 @@ seed: eggy - type: Item sprite: Objects/Consumable/Food/egg.rsi + - type: Grindable - type: entity parent: FoodBase id: FoodEggplantparm - name: eggplant parmigiana # parma or parmi + name: eggplant parmigiana description: The only good recipe for eggplant. components: - type: Food @@ -951,6 +986,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/eggplantparm.rsi + - type: Grindable #- type: entity @@ -982,6 +1018,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/enchiladas.rsi + - type: Grindable #- type: entity @@ -1025,6 +1062,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/fishandchips.rsi + - type: Grindable - type: entity @@ -1040,9 +1078,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/fishburger.rsi - - type: Item sprite: Objects/Consumable/Food/fishburger.rsi + - type: Grindable #- type: entity # parent: FoodBase @@ -1071,6 +1109,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/fishfingers.rsi + - type: Grindable #- type: entity @@ -1100,6 +1139,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/fortune_cookie.rsi + - type: Grindable - type: entity @@ -1115,6 +1155,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/friedegg.rsi + - type: Grindable - type: entity @@ -1132,6 +1173,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/fries.rsi + - type: Grindable - type: entity @@ -1149,6 +1191,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/gappletart.rsi + - type: Grindable - type: entity @@ -1166,6 +1209,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/toastedsandwich.rsi + - type: Grindable - type: entity @@ -1181,9 +1225,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/hburger.rsi - - type: Item sprite: Objects/Consumable/Food/hburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -1200,6 +1244,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/herbsalad.rsi + - type: Grindable #- type: entity @@ -1231,6 +1276,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/hotchili.rsi + - type: Grindable - type: entity @@ -1246,6 +1292,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/hotdog.rsi + - type: Grindable #- type: entity @@ -1275,6 +1322,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/hugemushroomslice.rsi + - type: Grindable - type: entity @@ -1292,6 +1340,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/kabob.rsi + - type: Grindable - type: entity @@ -1307,6 +1356,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/jdonut1.rsi + - type: Grindable - type: entity @@ -1322,6 +1372,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/jdonut2.rsi + - type: Grindable - type: entity @@ -1337,9 +1388,9 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/jellyburger.rsi - - type: Item sprite: Objects/Consumable/Food/jellyburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -1356,6 +1407,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/jellysandwich.rsi + - type: Grindable - type: entity @@ -1373,6 +1425,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/jellytoast.rsi + - type: Grindable # TODO: Add more pies. Anything that shares a sprite @@ -1391,6 +1444,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/kabob.rsi + - type: Grindable #- type: entity @@ -1436,6 +1490,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/lemoncake_slice.rsi + - type: Grindable - type: entity @@ -1453,6 +1508,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/limecake_slice.rsi + - type: Grindable - type: entity @@ -1468,6 +1524,7 @@ Quantity: 40 - type: Sprite sprite: Objects/Consumable/Food/liquidfood.rsi + - type: Grindable - type: entity @@ -1483,6 +1540,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/loadedbakedpotato.rsi + - type: Grindable - type: entity @@ -1498,6 +1556,7 @@ Quantity: 5 - type: Sprite sprite: Objects/Consumable/Food/meat.rsi + - type: Grindable - type: entity @@ -1513,9 +1572,9 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/meatball.rsi - - type: Item sprite: Objects/Consumable/Food/meatball.rsi + - type: Grindable - type: entity parent: FoodBase @@ -1532,6 +1591,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/meatballsoup.rsi + - type: Grindable - type: entity @@ -1549,6 +1609,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/meatballspaghetti.rsi + - type: Grindable - type: entity @@ -1566,6 +1627,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/meatbreadslice.rsi + - type: Grindable - type: entity @@ -1583,6 +1645,7 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/meatpie.rsi + - type: Grindable - type: entity @@ -1598,6 +1661,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/meatpizzaslice.rsi + - type: Grindable - type: entity @@ -1615,6 +1679,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/meatsteak.rsi + - type: Grindable - type: entity @@ -1632,6 +1697,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/milosoup.rsi + - type: Grindable - type: entity @@ -1647,6 +1713,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/mimeburger.rsi + - type: Grindable - type: entity @@ -1657,11 +1724,12 @@ components: - type: SolutionContainer contents: - reagents: + reagents: # TODO: mint toxin - ReagentId: chem.Nutriment Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/mint.rsi + - type: Grindable #- type: entity @@ -1691,9 +1759,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/hburger.rsi - - type: Item sprite: Objects/Consumable/Food/hburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -1712,6 +1780,7 @@ sprite: Objects/Consumable/Food/monkeycube.rsi - type: Rehydratable target: MonkeyMob_Content + - type: Grindable - type: entity parent: FoodBase @@ -1728,6 +1797,7 @@ Quantity: 30 - type: Sprite sprite: Objects/Consumable/Food/monkeysdelight.rsi + - type: Grindable #- type: entity @@ -1771,6 +1841,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/mushroompizzaslice.rsi + - type: Grindable - type: entity @@ -1788,6 +1859,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/mushroomsoup.rsi + - type: Grindable # TODO: More in this one @@ -1806,6 +1878,7 @@ Quantity: 1 - type: Sprite sprite: Objects/Consumable/Food/mysterysoup.rsi + - type: Grindable - type: entity @@ -1823,6 +1896,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/nettlesoup.rsi + - type: Grindable #- type: entity @@ -1854,6 +1928,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/omelette.rsi + - type: Grindable - type: entity @@ -1871,6 +1946,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/orangecake_slice.rsi + - type: Grindable - type: entity @@ -1888,6 +1964,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/pastatomato.rsi + - type: Grindable #- type: entity @@ -1917,6 +1994,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/phelmbiscuit.rsi + - type: Grindable - type: entity @@ -1932,6 +2010,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/pizzamargheritaslice.rsi + - type: Grindable - type: entity @@ -1949,6 +2028,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/plaincake_slice.rsi + - type: Grindable - type: entity @@ -1964,6 +2044,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/plump_pie.rsi + - type: Grindable - type: entity @@ -1982,6 +2063,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/popcorn.rsi + - type: Grindable - type: entity @@ -1997,6 +2079,7 @@ Quantity: 10 - type: Sprite sprite: Objects/Consumable/Food/poppypretzel.rsi + - type: Grindable - type: entity @@ -2014,6 +2097,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/pumpkinpieslice.rsi + - type: Grindable # TODO: Boiled rice? @@ -2044,6 +2128,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/roburger.rsi + - type: Grindable - type: entity @@ -2061,6 +2146,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/rofflewaffles.rsi + - type: Grindable #- type: entity @@ -2106,6 +2192,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/rpudding.rsi + - type: Grindable - type: entity @@ -2123,6 +2210,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/sandwich.rsi + - type: Grindable #- type: entity @@ -2166,6 +2254,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/sausage.rsi + - type: Grindable #- type: entity @@ -2210,9 +2299,9 @@ trash: TrashSOSJerky - type: Sprite sprite: Objects/Consumable/Food/sosjerky.rsi - - type: Item sprite: Objects/Consumable/Food/sosjerky.rsi + - type: Grindable - type: entity parent: FoodBase @@ -2229,6 +2318,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/soydope.rsi + - type: Grindable - type: entity @@ -2246,13 +2336,14 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/soylent_green.rsi + - type: Grindable # why these were named different i have no idea - type: entity parent: FoodBase id: FoodSoylentYellow - name: soylen virdians + name: soylen viridians description: Not made of people. Honest. components: - type: Food @@ -2264,6 +2355,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/soylent_yellow.rsi + - type: Grindable #- type: entity @@ -2293,6 +2385,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/space_twinkie.rsi + - type: Grindable - type: entity @@ -2310,6 +2403,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/spacylibertyduff.rsi + - type: Grindable - type: entity @@ -2325,6 +2419,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/spaghetti.rsi + - type: Grindable - type: entity @@ -2340,9 +2435,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/spellburger.rsi - - type: Item sprite: Objects/Consumable/Food/spellburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -2357,6 +2452,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/spesslaw.rsi + - type: Grindable - type: entity @@ -2372,6 +2468,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/stew.rsi + - type: Grindable - type: entity @@ -2389,6 +2486,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/stewedsoymeat.rsi + - type: Grindable - type: entity @@ -2404,6 +2502,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/stuffing.rsi + - type: Grindable #- type: entity @@ -2447,6 +2546,7 @@ Quantity: 40 - type: Sprite sprite: Objects/Consumable/Food/superbiteburger.rsi + - type: Grindable - type: entity @@ -2464,6 +2564,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/syndi_cakes.rsi + - type: Grindable - type: entity @@ -2479,6 +2580,7 @@ Quantity: 8 - type: Sprite sprite: Objects/Consumable/Food/taco.rsi + - type: Grindable - type: entity @@ -2496,6 +2598,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/tastybread.rsi + - type: Grindable - type: entity @@ -2513,6 +2616,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/toastedsandwich.rsi + - type: Grindable - type: entity @@ -2528,6 +2632,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/tofu.rsi + - type: Grindable - type: entity @@ -2545,6 +2650,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/tofubreadslice.rsi + - type: Grindable - type: entity @@ -2560,9 +2666,9 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/tofuburger.rsi - - type: Item sprite: Objects/Consumable/Food/tofuburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -2579,6 +2685,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/kabob.rsi + - type: Grindable - type: entity @@ -2594,6 +2701,7 @@ Quantity: 24 - type: Sprite sprite: Objects/Consumable/Food/tofurkey.rsi + - type: Grindable - type: entity @@ -2609,6 +2717,7 @@ Quantity: 6 - type: Sprite sprite: Objects/Consumable/Food/tomatomeat.rsi + - type: Grindable - type: entity @@ -2626,6 +2735,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/tomatosoup.rsi + - type: Grindable - type: entity @@ -2641,6 +2751,7 @@ Quantity: 4 - type: Sprite sprite: Objects/Consumable/Food/twobread.rsi + - type: Grindable - type: entity @@ -2658,6 +2769,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/validsalad.rsi + - type: Grindable - type: entity @@ -2673,6 +2785,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/vegetablepizzaslice.rsi + - type: Grindable - type: entity @@ -2690,6 +2803,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/vegetablesoup.rsi + - type: Grindable - type: entity @@ -2707,6 +2821,7 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/waffles.rsi + - type: Grindable - type: entity @@ -2722,6 +2837,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/watermelonslice.rsi + - type: Grindable - type: entity @@ -2739,6 +2855,7 @@ Quantity: 12 - type: Sprite sprite: Objects/Consumable/Food/wingfangchu.rsi + - type: Grindable - type: entity @@ -2756,6 +2873,7 @@ Quantity: 2 - type: Sprite sprite: Objects/Consumable/Food/wishsoup.rsi + - type: Grindable - type: entity @@ -2771,9 +2889,9 @@ Quantity: 16 - type: Sprite sprite: Objects/Consumable/Food/xburger.rsi - - type: Item sprite: Objects/Consumable/Food/xburger.rsi + - type: Grindable - type: entity parent: FoodBase @@ -2790,6 +2908,7 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/xenobreadslice.rsi + - type: Grindable - type: entity @@ -2805,6 +2924,7 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/xenomeat.rsi + - type: Grindable - type: entity @@ -2822,6 +2942,7 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/xenomeatpie.rsi + - type: Grindable - type: entity @@ -2839,6 +2960,7 @@ Quantity: 15 - type: Sprite sprite: Objects/Consumable/Food/stew.rsi + - type: Grindable - type: entity @@ -2857,6 +2979,7 @@ Quantity: 20 - type: Sprite sprite: Objects/Consumable/Food/milkape.rsi + - type: Grindable - type: entity name: memory leek @@ -2873,4 +2996,5 @@ - type: Sprite sprite: Objects/Consumable/Food/memoryleek.rsi state: memoryLeek + - type: Grindable diff --git a/Resources/Prototypes/Reagents/drinks.yml b/Resources/Prototypes/Reagents/drinks.yml index bce9438f42..1173cb83d6 100644 --- a/Resources/Prototypes/Reagents/drinks.yml +++ b/Resources/Prototypes/Reagents/drinks.yml @@ -182,7 +182,7 @@ - type: reagent id: chem.Tea name: tea - desc: A made by boiling leaves of the tea tree, Camellia sinensis. + desc: A drink made by boiling leaves of the tea tree, Camellia sinensis. physicalDesc: aromatic color: "#8a5a3a" metabolism: @@ -253,3 +253,152 @@ metabolism: - !type:DefaultDrink rate: 1 + + +#Juices +- type: reagent + id: chem.AppleJuice + name: apple juice + desc: It's a little piece of Eden. + physicalDesc: crisp + color: "#FDAD01" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.BerryJuice + name: berry juice + desc: A delicious blend of several different kinds of berries. + physicalDesc: sweet + color: "#660099" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.BananaJuice + name: banana juice + desc: The raw essence of a banana. HONK. + physicalDesc: crisp + color: "#FFE777" + metabolism: + - !type:DefaultDrink + rate: 1 + +#TODO: port on_mob_life: restore eyesight +#if(..()) +#return 1 +# M.eye_blurry = max(M.eye_blurry - 1 , 0) +# M.eye_blind = max(M.eye_blind - 1 , 0) +# switch(data) +# if(21 to INFINITY) +# if(prob(data - 10)) +# M.disabilities &= ~NEARSIGHTED +# data++ + +- type: reagent + id: chem.CarrotJuice + name: carrot juice + desc: It's like a carrot, but less crunchy. + physicalDesc: crisp + color: "#FF8820" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.LimeJuice + name: lime juice + desc: The sweet-sour juice of limes. + physicalDesc: citric + color: "#99bb43" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.LemonJuice + name: lemon juice + desc: This juice is VERY sour. + physicalDesc: citric + color: "#fff690" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.GrapeJuice + name: grape juice + desc: Freshly squeezed juice from red grapes. Quite sweet. + physicalDesc: crisp + color: "#512284" + metabolism: + - !type:DefaultDrink + rate: 1 + + +# /datum/reagent/drink/orangejuice/on_mob_life(var/mob/living/M) + +# if(..()) +# return 1 + +# if(M.getToxLoss() && prob(20)) +# M.adjustToxLoss(-REM) + +- type: reagent + id: chem.OrangeJuice + name: orange juice + desc: Both delicious AND rich in Vitamin C. What more do you need? + physicalDesc: citric + color: "#E78108" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.TomatoJuice + name: tomato juice + desc: Tomatoes made into juice. What a waste of good tomatoes, huh? + physicalDesc: saucey + color: "#731008" + metabolism: + - !type:DefaultDrink + rate: 1 + +# /datum/reagent/drink/poisonberryjuice/on_mob_life(var/mob/living/M) + +# if(..()) +# return 1 + +# M.adjustToxLoss(1) + +- type: reagent + id: chem.PoisonBerryJuice + name: poison berry juice + desc: A surprisingly tasty juice blended from various kinds of very deadly and toxic berries. + physicalDesc: aromatic #maybe should be 'sickly'? + color: "#6600CC" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.WatermelonJuice + name: water melon juice + desc: The delicious juice of a watermelon. + physicalDesc: sweet + color: "#EF3520" + metabolism: + - !type:DefaultDrink + rate: 1 + +- type: reagent + id: chem.PotatoJuice + name: potato juice + desc: Juice of the potato. Bleh. + physicalDesc: starchy + color: "#302000" + metabolism: + - !type:DefaultDrink + rate: 1 diff --git a/Resources/Textures/Constructible/Power/juicer.rsi/juicer0.png b/Resources/Textures/Constructible/Power/juicer.rsi/juicer0.png new file mode 100644 index 0000000000..ea33f75660 Binary files /dev/null and b/Resources/Textures/Constructible/Power/juicer.rsi/juicer0.png differ diff --git a/Resources/Textures/Constructible/Power/juicer.rsi/juicer1.png b/Resources/Textures/Constructible/Power/juicer.rsi/juicer1.png new file mode 100644 index 0000000000..e588271229 Binary files /dev/null and b/Resources/Textures/Constructible/Power/juicer.rsi/juicer1.png differ diff --git a/Resources/Textures/Constructible/Power/juicer.rsi/meta.json b/Resources/Textures/Constructible/Power/juicer.rsi/meta.json new file mode 100644 index 0000000000..95a4d470ed --- /dev/null +++ b/Resources/Textures/Constructible/Power/juicer.rsi/meta.json @@ -0,0 +1 @@ +{"license": "CC-BY-SA 3.0", "copyright": "https://github.com/tgstation/tgstation/commit/59f2a4e10e5ba36033c9734ddebfbbdc6157472d","version": 1, "size": {"x": 32, "y": 32}, "states": [{"name": "juicer0", "directions": 1, "delays": [[1.0]]}, {"name": "juicer1", "directions": 1, "delays": [[1.0]]}]} diff --git a/SpaceStation14.sln.DotSettings b/SpaceStation14.sln.DotSettings index 5d7e8fdb10..eb8d57346e 100644 --- a/SpaceStation14.sln.DotSettings +++ b/SpaceStation14.sln.DotSettings @@ -104,9 +104,11 @@ True True True + True True True True + True True True True