Add cheese & dough reactions (#5547)
* git mv * rename CreateEntityReaction -> CreateEntityTileReaction * cheese * change microwave recipes * remove unnecessary test * TryGet->Get
This commit is contained in:
@@ -1,43 +0,0 @@
|
||||
using System.Threading.Tasks;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Content.Shared.Kitchen;
|
||||
using NUnit.Framework;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.IntegrationTests.Tests.Kitchen
|
||||
{
|
||||
[TestFixture]
|
||||
public class KitchenTest : ContentIntegrationTest
|
||||
{
|
||||
[Test]
|
||||
public async Task TestRecipesValid()
|
||||
{
|
||||
var server = StartServer();
|
||||
await server.WaitIdleAsync();
|
||||
|
||||
var protoManager = server.ResolveDependency<IPrototypeManager>();
|
||||
|
||||
await server.WaitAssertion(() =>
|
||||
{
|
||||
foreach (var recipe in protoManager.EnumeratePrototypes<FoodRecipePrototype>())
|
||||
{
|
||||
Assert.That(protoManager.HasIndex<EntityPrototype>(recipe.Result), $"Cannot find FoodRecipe result {recipe.Result} in {recipe.ID}");
|
||||
|
||||
foreach (var (solid, amount) in recipe.IngredientsSolids)
|
||||
{
|
||||
Assert.That(protoManager.HasIndex<EntityPrototype>(solid), $"Cannot find FoodRecipe solid {solid} in {recipe.ID}");
|
||||
Assert.That(amount > 0, $" FoodRecipe {recipe.ID} has invalid solid amount of {amount}");
|
||||
}
|
||||
|
||||
foreach (var (reagent, amount) in recipe.IngredientsReagents)
|
||||
{
|
||||
Assert.That(protoManager.HasIndex<ReagentPrototype>(reagent), $"Cannot find FoodRecipe reagent {reagent} in {recipe.ID}");
|
||||
Assert.That(amount > 0, $" FoodRecipe {recipe.ID} has invalid reagent amount of {amount}");
|
||||
}
|
||||
|
||||
Assert.That(recipe.CookTime > 0, $"Cook time of {recipe.CookTime} for FoodRecipe {recipe.ID} is invalid!");
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Chemistry.ReactionEffects;
|
||||
|
||||
[DataDefinition]
|
||||
public class CreateEntityReactionEffect : ReagentEffect
|
||||
{
|
||||
/// <summary>
|
||||
/// What entity to create.
|
||||
/// </summary>
|
||||
[DataField("entity", required: true, customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Entity = default!;
|
||||
|
||||
/// <summary>
|
||||
/// How many entities to create per unit reaction.
|
||||
/// </summary>
|
||||
[DataField("number")]
|
||||
public uint Number = 1;
|
||||
|
||||
public override void Effect(ReagentEffectArgs args)
|
||||
{
|
||||
var transform = args.EntityManager.GetComponent<TransformComponent>(args.SolutionEntity);
|
||||
var quantity = Number * args.Quantity.Int();
|
||||
|
||||
for (var i = 0; i < quantity; i++)
|
||||
{
|
||||
args.EntityManager.SpawnEntity(Entity, transform.MapPosition);
|
||||
|
||||
// TODO figure out how to spawn inside of containers
|
||||
// e.g. cheese:
|
||||
// if the user is holding a bowl milk & enzyme, should drop to floor, not attached to the user.
|
||||
// if reaction happens in a backpack, should insert cheese into backpack.
|
||||
// --> if it doesn't fit, iterate through parent storage until it attaches to the grid (again, DON'T attach to players).
|
||||
// if the reaction happens INSIDE a stomach? the bloodstream? I have no idea how to handle that.
|
||||
// presumably having cheese materialize inside of your blood would have "disadvantages".
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,7 +16,7 @@ using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototy
|
||||
namespace Content.Server.Chemistry.TileReactions;
|
||||
|
||||
[DataDefinition]
|
||||
public class CreateEntityReaction : ITileReaction
|
||||
public class CreateEntityTileReaction : ITileReaction
|
||||
{
|
||||
[DataField("entity", required: true, customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Entity = default!;
|
||||
@@ -45,6 +45,12 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
|
||||
// TODO SERV3: Empty on the client, (de)serialize on the server with module manager is server module
|
||||
[DataField("sound", serverOnly: true)] public SoundSpecifier Sound { get; private set; } = new SoundPathSpecifier("/Audio/Effects/Chemistry/bubbles.ogg");
|
||||
|
||||
/// <summary>
|
||||
/// If true, this reaction will only consume only integer multiples of the reactant amounts. If there are not
|
||||
/// enough reactants, the reaction does not occur. Useful for spawn-entity reactions (e.g. creating cheese).
|
||||
/// </summary>
|
||||
[DataField("quantized")] public bool Quantized = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -46,6 +46,17 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
if (!solution.ContainsReagent(reactantName, out var reactantQuantity))
|
||||
return false;
|
||||
|
||||
if (reactantData.Value.Catalyst)
|
||||
{
|
||||
// catalyst is not consumed, so will not limit the reaction. But it still needs to be present, and
|
||||
// for quantized reactions we need to have a minimum amount
|
||||
|
||||
if (reactantQuantity == FixedPoint2.Zero || reaction.Quantized && reactantQuantity < reactantCoefficient)
|
||||
return false;
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
var unitReactions = reactantQuantity / reactantCoefficient;
|
||||
|
||||
if (unitReactions < lowestUnitReactions)
|
||||
@@ -53,7 +64,11 @@ namespace Content.Shared.Chemistry.Reaction
|
||||
lowestUnitReactions = unitReactions;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
if (reaction.Quantized)
|
||||
lowestUnitReactions = (int) lowestUnitReactions;
|
||||
|
||||
return lowestUnitReactions > 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -1,7 +1,10 @@
|
||||
using System.Collections.Generic;
|
||||
using Content.Shared.Chemistry.Reagent;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Serialization.Manager.Attributes;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
|
||||
using Robust.Shared.ViewVariables;
|
||||
|
||||
namespace Content.Shared.Kitchen
|
||||
@@ -19,21 +22,21 @@ namespace Content.Shared.Kitchen
|
||||
[DataField("name")]
|
||||
private string _name = string.Empty;
|
||||
|
||||
[DataField("reagents")]
|
||||
private readonly Dictionary<string, int> _ingsReagents = new();
|
||||
[DataField("reagents", customTypeSerializer:typeof(PrototypeIdDictionarySerializer<uint, ReagentPrototype>))]
|
||||
private readonly Dictionary<string, uint> _ingsReagents = new();
|
||||
|
||||
[DataField("solids")]
|
||||
private readonly Dictionary<string, int> _ingsSolids = new ();
|
||||
[DataField("solids", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<uint, EntityPrototype>))]
|
||||
private readonly Dictionary<string, uint> _ingsSolids = new ();
|
||||
|
||||
[DataField("result")]
|
||||
[DataField("result", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||
public string Result { get; } = string.Empty;
|
||||
|
||||
[DataField("time")]
|
||||
public int CookTime { get; } = 5;
|
||||
public uint CookTime { get; } = 5;
|
||||
|
||||
public string Name => Loc.GetString(_name);
|
||||
|
||||
public IReadOnlyDictionary<string, int> IngredientsReagents => _ingsReagents;
|
||||
public IReadOnlyDictionary<string, int> IngredientsSolids => _ingsSolids;
|
||||
public IReadOnlyDictionary<string, uint> IngredientsReagents => _ingsReagents;
|
||||
public IReadOnlyDictionary<string, uint> IngredientsSolids => _ingsSolids;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,14 @@
|
||||
- id: MonkeyCubeBox
|
||||
- id: SprayBottleWater
|
||||
- id: ReagentContainerFlour
|
||||
amount: 2
|
||||
- id: ReagentContainerSugar
|
||||
- id: FoodCondimentBottleEnzyme
|
||||
# really, milk should go in the fridge. Unfortunately saltern only has freezers.
|
||||
# yes, I'm using this as an excuse to not have to do extra work.
|
||||
- id: ReagentContainerMilk
|
||||
amount: 2
|
||||
- id: ReagentContainerMilkSoy
|
||||
|
||||
- type: entity
|
||||
id: ClosetJanitorFilled
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
startingInventory:
|
||||
ButchCleaver: 1
|
||||
KitchenKnife: 5
|
||||
FoodBowlBig: 5
|
||||
DrinkGlass: 10
|
||||
DrinkMug: 5
|
||||
DrinkMugBlack: 2
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
|
||||
- type: entity
|
||||
name: bowl
|
||||
parent: BaseItem
|
||||
parent: ReagentContainerBase
|
||||
id: FoodBowlBig
|
||||
description: A simple bowl, used for soups and salads.
|
||||
components:
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
maxVol: 20
|
||||
maxVol: 50 # enough to make cheese in.
|
||||
- type: Sprite
|
||||
sprite: Objects/Consumable/Food/bowl.rsi
|
||||
state: bowl
|
||||
@@ -22,17 +22,11 @@
|
||||
damage:
|
||||
types:
|
||||
Blunt: 5
|
||||
- type: Spillable
|
||||
solution: food
|
||||
# I suspect this ought to be more of a transformable container kinda thing.
|
||||
# For now, these components make it usable.
|
||||
- type: Drink
|
||||
solution: food
|
||||
isOpen: true
|
||||
- type: DrawableSolution
|
||||
solution: food
|
||||
- type: RefillableSolution
|
||||
solution: food
|
||||
- type: Damageable
|
||||
damageContainer: Inorganic
|
||||
- type: Destructible
|
||||
|
||||
@@ -337,6 +337,7 @@
|
||||
description: A thin glass bottle used to store condiments.
|
||||
components:
|
||||
- type: Drink
|
||||
solution: food
|
||||
openSounds:
|
||||
collection: pop
|
||||
- type: SolutionContainerManager
|
||||
@@ -344,6 +345,8 @@
|
||||
food:
|
||||
maxVol: 30
|
||||
- type: SolutionTransfer
|
||||
canChangeTransferAmount: true
|
||||
minTransferAmount: 5
|
||||
maxTransferAmount: 30
|
||||
- type: Sprite
|
||||
netsync: false
|
||||
@@ -480,6 +483,7 @@
|
||||
description: A smaller glass bottle used to store condiments.
|
||||
components:
|
||||
- type: Drink
|
||||
solution: food
|
||||
openSounds:
|
||||
collection: pop
|
||||
- type: SolutionContainerManager
|
||||
|
||||
@@ -214,10 +214,10 @@
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
maxVol: 20
|
||||
maxVol: 50 # at least enough for one cheese
|
||||
reagents:
|
||||
- ReagentId: Milk
|
||||
Quantity: 20
|
||||
Quantity: 50
|
||||
|
||||
- type: entity
|
||||
parent: ReagentContainerBase
|
||||
@@ -230,10 +230,10 @@
|
||||
- type: SolutionContainerManager
|
||||
solutions:
|
||||
food:
|
||||
maxVol: 20
|
||||
maxVol: 50
|
||||
reagents:
|
||||
- ReagentId: MilkSoy
|
||||
Quantity: 20
|
||||
Quantity: 50
|
||||
|
||||
- type: entity
|
||||
parent: ReagentContainerBase
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
physicalDesc: fibrous
|
||||
color: "#800000"
|
||||
tileReactions:
|
||||
- !type:CreateEntityReaction
|
||||
- !type:CreateEntityTileReaction
|
||||
entity: Carpet
|
||||
maxOnTileWhitelist:
|
||||
tags: [ Carpet ]
|
||||
@@ -31,7 +31,7 @@
|
||||
physicalDesc: buzzy
|
||||
color: "#FFD35D"
|
||||
tileReactions:
|
||||
- !type:CreateEntityReaction
|
||||
- !type:CreateEntityTileReaction
|
||||
entity: MobBee
|
||||
usage: 2
|
||||
maxOnTile: 2
|
||||
|
||||
@@ -4,19 +4,18 @@
|
||||
name: cheeseburger recipe
|
||||
result: FoodBurgerCheese
|
||||
time: 5
|
||||
reagents:
|
||||
Flour: 5
|
||||
solids:
|
||||
FoodBreadPlainSlice: 2 # its not a burger bun, but its good enough
|
||||
FoodMeat: 1
|
||||
FoodCheeseSlice: 1
|
||||
|
||||
- type: microwaveMealRecipe
|
||||
id: RecipeClownBurger
|
||||
name: clownburger recipe
|
||||
result: FoodBurgerClown
|
||||
time: 5
|
||||
reagents:
|
||||
Flour: 5
|
||||
solids:
|
||||
FoodBreadPlainSlice: 2
|
||||
ClothingMaskClown: 1
|
||||
|
||||
# - type: microwaveMealRecipe
|
||||
@@ -34,9 +33,8 @@
|
||||
name: xenoburger recipe
|
||||
result: FoodBurgerXeno
|
||||
time: 5
|
||||
reagents:
|
||||
Flour: 5
|
||||
solids:
|
||||
FoodBreadPlainSlice: 2
|
||||
FoodMeatXeno: 1
|
||||
|
||||
#- type: microwaveMealRecipe
|
||||
@@ -60,8 +58,8 @@
|
||||
name: bread recipe
|
||||
result: FoodBreadPlain
|
||||
time: 15
|
||||
reagents:
|
||||
Flour: 15
|
||||
solids:
|
||||
FoodDough: 1
|
||||
|
||||
# - type: microwaveMealRecipe
|
||||
# id: RecipeSandwich
|
||||
@@ -105,9 +103,8 @@
|
||||
name: cream cheese bread recipe
|
||||
result: FoodBreadCreamcheese
|
||||
time: 20
|
||||
reagents:
|
||||
Flour: 15
|
||||
solids:
|
||||
FoodDough: 1
|
||||
FoodCheeseSlice: 2
|
||||
|
||||
- type: microwaveMealRecipe
|
||||
@@ -115,11 +112,8 @@
|
||||
name: banana bread recipe
|
||||
result: FoodBreadBanana
|
||||
time: 25
|
||||
reagents:
|
||||
Flour: 15
|
||||
Milk: 5
|
||||
solids:
|
||||
FoodEgg: 3
|
||||
FoodDough: 1
|
||||
FoodBanana: 1
|
||||
|
||||
#Pizzas
|
||||
@@ -128,9 +122,8 @@
|
||||
name: margherita pizza recipe
|
||||
result: FoodPizzaMargherita
|
||||
time: 30
|
||||
reagents:
|
||||
Flour: 10
|
||||
solids:
|
||||
FoodDough: 1
|
||||
FoodCheeseSlice: 4
|
||||
FoodTomato: 1
|
||||
|
||||
@@ -139,9 +132,8 @@
|
||||
name: mushroom pizza recipe
|
||||
result: FoodPizzaMushroom
|
||||
time: 25
|
||||
reagents:
|
||||
Flour: 10
|
||||
solids:
|
||||
FoodDough: 1
|
||||
FoodMushroom: 5
|
||||
|
||||
- type: microwaveMealRecipe
|
||||
@@ -149,9 +141,8 @@
|
||||
name: meat pizza recipe
|
||||
result: FoodPizzaMeat
|
||||
time: 30
|
||||
reagents:
|
||||
Flour: 10
|
||||
solids:
|
||||
FoodDough: 1
|
||||
FoodMeat: 3
|
||||
FoodCheeseSlice: 1
|
||||
FoodTomato: 1
|
||||
@@ -161,9 +152,8 @@
|
||||
name: vegetable pizza recipe
|
||||
result: FoodPizzaVegetable
|
||||
time: 30
|
||||
reagents:
|
||||
Flour: 10
|
||||
solids:
|
||||
FoodDough: 1
|
||||
FoodEggplant: 1
|
||||
FoodCarrot: 1
|
||||
FoodCorn: 1
|
||||
@@ -365,9 +355,8 @@
|
||||
name: banana cream pie
|
||||
result: FoodPieBananaCream
|
||||
time: 15
|
||||
reagents:
|
||||
Flour: 10
|
||||
solids:
|
||||
FoodCakeBatter: 1 # should really be pie pastry or whatever. Good enough.
|
||||
FoodBanana: 3
|
||||
|
||||
#Donks i guess
|
||||
|
||||
59
Resources/Prototypes/Recipes/Reactions/food.yml
Normal file
59
Resources/Prototypes/Recipes/Reactions/food.yml
Normal file
@@ -0,0 +1,59 @@
|
||||
- type: reaction
|
||||
id: Curdling
|
||||
impact: Low
|
||||
quantized: true
|
||||
reactants:
|
||||
Milk:
|
||||
amount: 40
|
||||
Enzyme:
|
||||
amount: 5
|
||||
catalyst: true
|
||||
effects:
|
||||
- !type:CreateEntityReactionEffect
|
||||
entity: FoodCheese
|
||||
|
||||
- type: reaction
|
||||
id: CreateDough
|
||||
impact: Low
|
||||
quantized: true
|
||||
reactants:
|
||||
Flour:
|
||||
amount: 15
|
||||
Water:
|
||||
amount: 10
|
||||
effects:
|
||||
- !type:CreateEntityReactionEffect
|
||||
entity: FoodDough
|
||||
|
||||
- type: reaction
|
||||
id: CreateCakeBatter
|
||||
impact: Low
|
||||
quantized: true
|
||||
reactants:
|
||||
Flour:
|
||||
amount: 15
|
||||
Egg:
|
||||
amount: 12
|
||||
Sugar:
|
||||
amount: 5
|
||||
effects:
|
||||
- !type:CreateEntityReactionEffect
|
||||
entity: FoodCakeBatter
|
||||
|
||||
# TG has a cake recipe that uses soy milk instead of eggs.
|
||||
# but afaik it spawns the exact same cake batter entity.
|
||||
# Maybe change this if you want to do allergies or something
|
||||
- type: reaction
|
||||
id: CreateVeganCakeBatter
|
||||
impact: Low
|
||||
quantized: true
|
||||
reactants:
|
||||
Flour:
|
||||
amount: 15
|
||||
MilkSoy:
|
||||
amount: 12
|
||||
Sugar:
|
||||
amount: 5
|
||||
effects:
|
||||
- !type:CreateEntityReactionEffect
|
||||
entity: FoodCakeBatter
|
||||
Reference in New Issue
Block a user