Food update (#412)

* meat refactor

* document and remove verb

* cooking table

* cutlets

* dough and cheese update

* flat dough

* size edit, egg added

* Update test-ship.yml

* meat and cheese randomsprite
This commit is contained in:
Ed
2024-08-19 18:39:47 +03:00
committed by GitHub
parent df6dbd2ac7
commit 4cb93fc965
43 changed files with 557 additions and 130 deletions

View File

@@ -4,16 +4,28 @@ using Robust.Shared.Prototypes;
namespace Content.Server._CP14.Workbench;
/// <summary>
/// This entity can be used to craft other objects through the interface
/// </summary>
[RegisterComponent]
[Access(typeof(CP14WorkbenchSystem))]
public sealed partial class CP14WorkbenchComponent : Component
{
/// <summary>
/// Crafting speed modifier on this workbench.
/// </summary>
[DataField]
public float CraftSpeed = 1f;
/// <summary>
/// List of recipes available for crafting on this type of workbench
/// </summary>
[DataField]
public List<ProtoId<CP14WorkbenchRecipePrototype>> Recipes = new();
/// <summary>
/// Played during crafting. Can be overwritten by the crafting sound of a specific recipe.
/// </summary>
[DataField]
public SoundSpecifier CraftSound = new SoundCollectionSpecifier("CP14Hammering");
}

View File

@@ -1,3 +1,4 @@
using Content.Server.Chemistry.Containers.EntitySystems;
using Content.Server.DoAfter;
using Content.Server.Popups;
using Content.Server.Stack;
@@ -6,7 +7,6 @@ using Content.Shared._CP14.Workbench.Prototypes;
using Content.Shared.DoAfter;
using Content.Shared.Stacks;
using Content.Shared.UserInterface;
using Content.Shared.Verbs;
using Robust.Server.Audio;
using Robust.Server.GameObjects;
using Robust.Shared.Prototypes;
@@ -22,6 +22,9 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly PopupSystem _popup = default!;
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
[Dependency] private readonly SolutionContainerSystem _solutionContainer = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
private EntityQuery<MetaDataComponent> _metaQuery;
private EntityQuery<StackComponent> _stackQuery;
@@ -39,7 +42,6 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
SubscribeLocalEvent<CP14WorkbenchComponent, BeforeActivatableUIOpenEvent>(OnBeforeUIOpen);
SubscribeLocalEvent<CP14WorkbenchComponent, CP14WorkbenchUiCraftMessage>(OnCraft);
SubscribeLocalEvent<CP14WorkbenchComponent, GetVerbsEvent<InteractionVerb>>(OnInteractionVerb);
SubscribeLocalEvent<CP14WorkbenchComponent, CP14CraftDoAfterEvent>(OnCraftFinished);
}
@@ -48,36 +50,6 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
UpdateUIRecipes(ent);
}
private void OnInteractionVerb(Entity<CP14WorkbenchComponent> ent, ref GetVerbsEvent<InteractionVerb> args)
{
if (!args.CanAccess || !args.CanInteract || args.Hands is null)
return;
var placedEntities = _lookup.GetEntitiesInRange(Transform(ent).Coordinates, WorkbenchRadius);
var user = args.User;
foreach (var craftProto in ent.Comp.Recipes)
{
if (!_proto.TryIndex(craftProto, out var craft))
continue;
if (!_proto.TryIndex(craft.Result, out var result))
continue;
args.Verbs.Add(new()
{
Act = () =>
{
StartCraft(ent, user, craft);
},
Text = result.Name,
Message = GetCraftRecipeMessage(result.Description, craft),
Category = VerbCategory.CP14Craft,
Disabled = !CanCraftRecipe(craft, placedEntities),
});
}
}
// TODO: Replace Del to QueueDel when it's will be works with events
private void OnCraftFinished(Entity<CP14WorkbenchComponent> ent, ref CP14CraftDoAfterEvent args)
{
@@ -87,7 +59,7 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
if (!_proto.TryIndex(args.Recipe, out var recipe))
return;
var placedEntities = _lookup.GetEntitiesInRange(Transform(ent).Coordinates, WorkbenchRadius);
var placedEntities = _lookup.GetEntitiesInRange(Transform(ent).Coordinates, WorkbenchRadius, LookupFlags.Uncontained);
if (!CanCraftRecipe(recipe, placedEntities))
{
@@ -95,14 +67,35 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
return;
}
var resultEntity = Spawn(_proto.Index(args.Recipe).Result);
_solutionContainer.TryGetSolution(resultEntity, recipe.Solution, out var resultSoln, out var resultSolution);
if (recipe.TryMergeSolutions && resultSoln is not null)
{
resultSoln.Value.Comp.Solution.MaxVolume = 0;
_solutionContainer.RemoveAllSolution(resultSoln.Value); //If we combine ingredient solutions, we do not use the default solution prescribed in the entity.
}
foreach (var requiredIngredient in recipe.Entities)
{
var requiredCount = requiredIngredient.Value;
foreach (var placedEntity in placedEntities)
{
var placedProto = MetaData(placedEntity).EntityPrototype?.ID;
if (placedProto != null && placedProto == requiredIngredient.Key && requiredCount > 0)
if (!TryComp<MetaDataComponent>(placedEntity, out var metaData) || metaData.EntityPrototype is null)
continue;
var placedProto = metaData.EntityPrototype.ID;
if (placedProto == requiredIngredient.Key && requiredCount > 0)
{
// Trying merge solutions
if (recipe.TryMergeSolutions
&& resultSoln is not null
&& _solutionContainer.TryGetSolution(placedEntity, recipe.Solution, out var ingredientSoln, out var ingredientSolution))
{
resultSoln.Value.Comp.Solution.MaxVolume += ingredientSoln.Value.Comp.Solution.MaxVolume;
_solutionContainer.TryAddSolution(resultSoln.Value, ingredientSolution);
}
requiredCount--;
Del(placedEntity);
}
@@ -130,8 +123,7 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
requiredCount -= count;
}
}
Spawn(_proto.Index(args.Recipe).Result, Transform(ent).Coordinates);
_transform.SetCoordinates(resultEntity, Transform(ent).Coordinates);
UpdateUIRecipes(ent);
args.Handled = true;
}
@@ -159,26 +151,6 @@ public sealed partial class CP14WorkbenchSystem : SharedCP14WorkbenchSystem
_audio.PlayPvs(recipe.OverrideCraftSound ?? workbench.Comp.CraftSound, workbench);
}
private List<CP14WorkbenchRecipePrototype> GetPossibleCrafts(Entity<CP14WorkbenchComponent> workbench, HashSet<EntityUid> ingrediEnts)
{
List<CP14WorkbenchRecipePrototype> result = new();
if (ingrediEnts.Count == 0)
return result;
foreach (var recipeProto in workbench.Comp.Recipes)
{
var recipe = _proto.Index(recipeProto);
if (CanCraftRecipe(recipe, ingrediEnts))
{
result.Add(recipe);
}
}
return result;
}
private bool CanCraftRecipe(CP14WorkbenchRecipePrototype recipe, HashSet<EntityUid> entities)
{
var indexedIngredients = IndexIngredients(entities);

View File

@@ -24,4 +24,10 @@ public sealed class CP14WorkbenchRecipePrototype : IPrototype
[DataField(required: true)]
public EntProtoId Result;
[DataField]
public bool TryMergeSolutions = false;
[DataField]
public string Solution = "food";
}

View File

@@ -1243,7 +1243,7 @@ entities:
- type: Transform
pos: -5.439834,-4.863015
parent: 1
- proto: CP14CookedFoodMeat
- proto: CP14FoodMeatLamb
entities:
- uid: 734
components:
@@ -2749,7 +2749,7 @@ entities:
rot: 3.141592653589793 rad
pos: 6.042266,-21.159649
parent: 1
- proto: CP14RawFoodMeat
- proto: CP14FoodCheeseWheel
entities:
- uid: 735
components:

View File

@@ -0,0 +1,78 @@
- type: entity
id: CP14FoodCheeseWheel
parent: FoodInjectableBase
name: cheese wheel
description: A large wheel of soft, fragrant piece of cheese.
components:
- type: Item
size: Normal
- type: FlavorProfile
flavors:
- cheesy
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/cheese.rsi
layers:
- state: cheese_wheel
- type: SolutionContainerManager
solutions:
food:
maxVol: 30
reagents:
- ReagentId: Nutriment
Quantity: 21
- type: SliceableFood
count: 5
slice: CP14FoodCheesePart
- type: entity
id: CP14FoodCheesePart
parent: CP14FoodCheeseWheel
name: cheese
description: A triangle of soft, fragrant cheese.
components:
- type: Item
size: Tiny
- type: Sprite
layers:
- state: cheese_part
map: [ "random" ]
- type: RandomSprite
available:
- random:
cheese_part: ""
cheese_part2: ""
cheese_part3: ""
- type: SolutionContainerManager
solutions:
food:
maxVol: 6 # 1/5 cheese wheel
reagents:
- ReagentId: Nutriment
Quantity: 4.2
- type: SliceableFood
count: 3
slice: CP14FoodCheeseSlice
- type: entity
id: CP14FoodCheeseSlice
parent: CP14FoodCheesePart
name: cheese slice
description: A thin slice of delicious smelling cheese
components:
- type: Sprite
layers:
- state: cheese_slice
map: [ "random" ]
- type: RandomSprite
available:
- random:
cheese_slice: ""
cheese_slice2: ""
cheese_slice3: ""
- type: SolutionContainerManager
solutions:
food:
maxVol: 2 # 1/3 cheese part
reagents:
- ReagentId: Nutriment
Quantity: 1.4

View File

@@ -0,0 +1,64 @@
- type: entity
parent: FoodInjectableBase
id: CP14FoodDoughLarge
name: large piece of dough
description: The perfect ingredient for any flour product. The only thing left to do is to shape it.
components:
- type: Item
size: Normal
- type: FlavorProfile
flavors:
- bread #TODO smth disguisting. raw dough
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/dough.rsi
state: dough_large
- type: SolutionContainerManager
solutions:
food:
maxVol: 30
reagents:
- ReagentId: Nutriment
Quantity: 21
- ReagentId: UncookedAnimalProteins
Quantity: 2
- type: SliceableFood
count: 5
slice: CP14FoodDoughMedium
- type: entity
parent: CP14FoodDoughLarge
id: CP14FoodDoughMedium
name: medium piece of dough
components:
- type: Item
size: Tiny
- type: Sprite
state: dough_medium
- type: SolutionContainerManager
solutions:
food:
maxVol: 6 # 1/5 large dough
reagents:
- ReagentId: Nutriment
Quantity: 4.2
- ReagentId: UncookedAnimalProteins
Quantity: 0.4
- type: entity
parent: CP14FoodDoughMedium
id: CP14FoodDoughMediumFlat
name: rolled dough
components:
- type: Item
size: Normal
- type: Sprite
state: dough_medium_flat
- type: SolutionContainerManager
solutions:
food:
maxVol: 6 # 1/5 large dough
reagents:
- ReagentId: Nutriment
Quantity: 4.2
- ReagentId: UncookedAnimalProteins
Quantity: 0.4

View File

@@ -0,0 +1,100 @@
# Base
- type: entity
parent: [FoodInjectableBase, ItemHeftyBase]
id: CP14FoodEggBase
description: An egg!
abstract: true
components:
- type: Food
trash:
- CP14Eggshells
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/egg.rsi
state: brown
- type: Item
size: Tiny
- type: SolutionContainerManager
solutions:
food:
maxVol: 6
reagents:
- ReagentId: Egg
Quantity: 6
- type: DrawableSolution
solution: food
- type: SolutionSpiker
sourceSolution: food
ignoreEmpty: true
popup: spike-solution-egg
# egg fragile
- type: DamageOnHighSpeedImpact
minimumSpeed: 0.1
damage:
types:
Blunt: 1
- type: Damageable
damageContainer: Biological
- type: Destructible
thresholds:
- trigger:
!type:DamageTrigger
damage: 1
behaviors:
- !type:PlaySoundBehavior
sound:
collection: desecration
- !type:SpillBehavior
solution: food
- !type:SpawnEntitiesBehavior
spawn:
CP14Eggshells:
min: 1
max: 1
# Wow double-yolk you're so lucky!
- !type:DoActsBehavior
acts: [ "Destruction" ]
- type: Temperature
currentTemperature: 290
- type: InternalTemperature
# ~1mm shell and ~1cm of albumen
thickness: 0.011
area: 0.04
# conductivity of egg shell based on a paper from Romanoff and Romanoff (1949)
conductivity: 0.456
# Splat
- type: entity
name: eggshells
parent: BaseItem
id: CP14Eggshells
description: You're walkin' on 'em bud.
components:
- type: Food
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/egg.rsi
state: brown_shell
- type: Item
size: Tiny
- type: SolutionContainerManager
solutions:
food:
maxVol: 2
reagents:
- ReagentId: Egg
Quantity: 1
- type: entity
parent: CP14FoodEggBase
id: CP14FoodEgg
name: egg
components:
- type: Sprite
layers:
- state: icon
map: [ "random" ]
- type: RandomSprite
available:
- random:
brown: ""
icon: ""

View File

@@ -1,27 +1,110 @@
- type: entity
name: raw meat
parent: FoodMeat
id: CP14RawFoodMeat
description: It smells weird, but looks like normal meat...
# Base
- type: entity
parent: FoodInjectableBase
id: CP14FoodMeatBase
abstract: true
components:
- type: FlavorProfile
flavors:
- meaty
- type: Extractable
grindableSolutionName: food
- type: SolutionContainerManager
solutions:
food:
maxVol: 15
reagents:
- ReagentId: Nutriment
Quantity: 6
- ReagentId: UncookedAnimalProteins
Quantity: 1
- ReagentId: Fat
Quantity: 6
- type: Temperature
currentTemperature: 290
- type: InternalTemperature
thickness: 0.02
area: 0.02 # arbitrary number that sounds right for a slab of meat
- type: entity
id: CP14FoodMeatSliceBase
parent: CP14FoodMeatBase
abstract: true
components:
- type: SolutionContainerManager
solutions:
food:
maxVol: 5
reagents:
- ReagentId: Nutriment
Quantity: 2
- ReagentId: UncookedAnimalProteins
Quantity: 0.33
- ReagentId: Fat
Quantity: 2
- type: InternalTemperature
thickness: 0.006
area: 0.006 # 1\3 of meat value
# Lamb Meat
- type: entity
id: CP14FoodMeatLamb
parent: CP14FoodMeatBase
name: raw lamb
description: Succulent lamb steak
components:
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/meat.rsi
state: sheepmeat
- type: Construction
graph: CP14MeatSteak
node: start
defaultTarget: sheep steak
- type: SliceableFood
count: 3
slice: CP14FoodMeatLambSlice
- type: Item
size: Tiny
shape:
- 0,0,1,0
- type: entity
name: steak
parent: FoodMeatCooked
id: CP14CookedFoodMeat
description: A cooked slab of meat. Smells primal.
id: CP14FoodMeatLambSlice
parent: CP14FoodMeatSliceBase
name: meat pieces
description: Succulent lamb steak
components:
- type: Item
size: Tiny
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/meat.rsi
layers:
- state: sheepmeat-cooked
- type: Construction
graph: CP14MeatSteak
node: sheep steak
- state: sheepmeat_slice
map: [ "random" ]
- type: RandomSprite
available:
- random:
sheepmeat_slice: ""
sheepmeat_slice2: ""
sheepmeat_slice3: ""
- type: entity
id: CP14FoodMeatLambCutlet
parent: CP14FoodMeatSliceBase
name: lamb cutlet
description: the result of mixing sliced lamb and egg - a raw round cutlet.
components:
- type: Sprite
sprite: _CP14/Objects/Consumable/Food/meat.rsi
state: cutlet
- type: SolutionContainerManager
solutions:
food:
maxVol: 10
reagents:
- ReagentId: Nutriment
Quantity: 4
- ReagentId: UncookedAnimalProteins
Quantity: 0.66
- ReagentId: Fat
Quantity: 4
- ReagentId: Egg
Quantity: 6

View File

@@ -91,41 +91,6 @@
- type: Icon
sprite: _CP14/Structures/Furniture/workbench.rsi
state: melting_crafter
- type: Damageable
damageContainer: Inorganic
damageModifierSet: Wood
- type: Destructible
thresholds:
- trigger:
!type:DamageTypeTrigger
damageType: Heat
damage: 40
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: WoodDestroy
- trigger:
!type:DamageTrigger
damage: 60
behaviors:
- !type:DoActsBehavior
acts: ["Destruction"]
- !type:PlaySoundBehavior
sound:
collection: WoodDestroy
- !type:SpawnEntitiesBehavior
spawn:
CP14WoodenPlanks1:
min: 1
max: 2
- type: FootstepModifier
footstepSoundCollection:
collection: FootstepWood
- type: FireVisuals
sprite: _CP14/Effects/fire.rsi
normalState: full
- type: CP14Workbench
craftSound:
collection: CP14Sawing
@@ -138,4 +103,21 @@
- CP14MeltingMoldSickle
- CP14MeltingMoldSword
- CP14MeltingMoldThrowableSpear
- CP14MeltingMoldTwoHandedSword
- CP14MeltingMoldTwoHandedSword
- type: entity
id: CP14WorkbenchCooking
parent:
- CP14WorkbenchMeltingMolds
- CP14BaseWooden
name: cooking table
description: Lets cook
components:
- type: CP14Workbench
craftSound:
collection: CP14Sawing
recipes:
- CP14FoodDoughLarge
- CP14FoodDoughMediumFlat
- CP14FoodDoughMedium
- CP14FoodMeatLamb

View File

@@ -1,16 +0,0 @@
- type: constructionGraph
id: CP14MeatSteak
start: start
graph:
- node: start
edges:
- to: sheep steak
completed:
- !type:PlaySound
sound: /Audio/Effects/sizzle.ogg
steps:
- minTemperature: 335
- node: sheep steak
entity: CP14CookedFoodMeat

View File

@@ -0,0 +1,32 @@
- type: CP14Recipe
id: CP14FoodMeatLamb
craftTime: 2
entities:
CP14FoodMeatLambSlice: 2
CP14FoodEgg: 1
result: CP14FoodMeatLambCutlet
tryMergeSolutions: true
- type: CP14Recipe
id: CP14FoodDoughLarge
craftTime: 3
entities:
CP14FoodDoughMedium: 5
result: CP14FoodDoughLarge
tryMergeSolutions: true
- type: CP14Recipe
id: CP14FoodDoughMedium
craftTime: 3
entities:
CP14FoodDoughMediumFlat: 1
result: CP14FoodDoughMedium
tryMergeSolutions: true
- type: CP14Recipe
id: CP14FoodDoughMediumFlat
craftTime: 3
entities:
CP14FoodDoughMedium: 1
result: CP14FoodDoughMediumFlat
tryMergeSolutions: true

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 334 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 282 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 297 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 279 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 339 B

View File

@@ -0,0 +1,32 @@
{
"version": 1,
"license": "All rights reserved for the CrystallPunk14 project only",
"copyright": "Created by Artista.rar",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "cheese_part"
},
{
"name": "cheese_part2"
},
{
"name": "cheese_part3"
},
{
"name": "cheese_slice"
},
{
"name": "cheese_slice2"
},
{
"name": "cheese_slice3"
},
{
"name": "cheese_wheel"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 446 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 308 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 351 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 346 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

View File

@@ -0,0 +1,32 @@
{
"version": 1,
"license": "All rights reserved for the CrystallPunk14 project only",
"copyright": "bun_cooked bun_cooked_slice_bottom bun_cooked_slice_top dough_medium Created by Artista.rar, bread_cooked dough_large dough_medium_flat created by TheShuEd",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "bread_cooked"
},
{
"name": "bun_cooked"
},
{
"name": "bun_cooked_slice_bottom"
},
{
"name": "bun_cooked_slice_top"
},
{
"name": "dough_large"
},
{
"name": "dough_medium"
},
{
"name": "dough_medium_flat"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 288 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 303 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 277 B

View File

@@ -0,0 +1,23 @@
{
"version": 1,
"license": "All rights reserved for the CrystallPunk14 project only",
"copyright": "By Prazat",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "icon"
},
{
"name": "brown"
},
{
"name": "white_shell"
},
{
"name": "brown_shell"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 341 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 243 B

View File

@@ -1,17 +1,44 @@
{
"version": 1,
"license": "All rights reserved for the CrystallPunk14 project only",
"copyright": "By omsoyk",
"copyright": "sheepmeat and sheepmeat_cooked By omsoyk, sheepmeat_slice and sheepmeat_slice_cooked by TheShuEd, cutlet and cutlet_cooked and meat_slice by Artista.rar",
"size": {
"x": 32,
"y": 32
},
"states": [
{
"name": "cutlet"
},
{
"name": "cutlet_cooked"
},
{
"name": "meat_slice"
},
{
"name": "sheepmeat"
},
{
"name": "sheepmeat-cooked"
"name": "sheepmeat_cooked"
},
{
"name": "sheepmeat_slice"
},
{
"name": "sheepmeat_slice2"
},
{
"name": "sheepmeat_slice3"
},
{
"name": "sheepmeat_slice_cooked"
},
{
"name": "sheepmeat_slice2_cooked"
},
{
"name": "sheepmeat_slice3_cooked"
}
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 250 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 259 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 296 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 313 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 305 B