Cooking simulator 3: Pies (#1540)

* enum -> prototype

* move sprites

* more dirt sprites

* some food data stucking fixing

* pumpkin fix

* pie move sprites

* refactor components

* pie refactor

* remove outdated proto

* new pie types

* Update SliceableFoodSystem.cs

* Refactor food cooking system and add fat flavor

Added 'Fat' to the flavor profile. Refactored food cooking logic to use CreateFoodData and UpdateFoodDataVisuals instead of CookFood and ApplyFoodVisuals. Introduced RenameCooker property to CP14FoodCookerComponent to control entity renaming during cooking. Improved separation of food data creation and visual updates.

* Update migration.yml

* Refactor food visual and sliceable logic in cooking system

Moved sliceable food logic from OnCookFinished to UpdateFoodDataVisuals for better encapsulation. Made UpdateFoodDataVisuals overridable and updated its usage in random food initialization. Added Rename field to CP14RandomFoodDataComponent and cleaned up unused BecomeSliceable field in CP14FoodCookerComponent. Updated pie_pan.yml to add SliceableFood and a new random food entity.

* Update pie_pan.yml

* fill levels
This commit is contained in:
Red
2025-07-20 15:45:59 +03:00
committed by GitHub
parent 6b98c91f73
commit 8721f736e1
79 changed files with 581 additions and 700 deletions

View File

@@ -6,6 +6,7 @@
using System.Linq;
using System.Numerics;
using Content.Shared._CP14.Cooking.Components;
using Content.Shared._CP14.Cooking.Prototypes;
using Content.Shared.Audio;
using Content.Shared.Chemistry.Components;
using Content.Shared.Chemistry.EntitySystems;
@@ -16,7 +17,6 @@ using Content.Shared.Fluids;
using Content.Shared.Nutrition.Components;
using Content.Shared.Popups;
using Content.Shared.Tag;
using Content.Shared.Throwing;
using Robust.Shared.Containers;
using Robust.Shared.Network;
using Robust.Shared.Prototypes;
@@ -26,17 +26,17 @@ namespace Content.Shared._CP14.Cooking;
public abstract partial class CP14SharedCookingSystem : EntitySystem
{
[Dependency] protected readonly IPrototypeManager _proto = default!;
[Dependency] protected readonly SharedContainerSystem _container = default!;
[Dependency] protected readonly IRobustRandom _random = default!;
[Dependency] protected readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] protected readonly SharedSolutionContainerSystem _solution = default!;
[Dependency] private readonly MetaDataSystem _metaData = default!;
[Dependency] private readonly IPrototypeManager _proto = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly SharedPuddleSystem _puddle = default!;
[Dependency] private readonly INetManager _net = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedAmbientSoundSystem _ambientSound = default!;
[Dependency] protected readonly SharedAppearanceSystem _appearance = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
/// <summary>
/// When overcooking food, we will replace the reagents inside with this reagent.
@@ -61,7 +61,7 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
CacheAndOrderRecipes();
SubscribeLocalEvent<PrototypesReloadedEventArgs>(OnPrototypesReloaded);
SubscribeLocalEvent<CP14FoodVisualsComponent, ExaminedEvent>(OnExaminedEvent);
SubscribeLocalEvent<CP14FoodHolderComponent, ExaminedEvent>(OnExaminedEvent);
}
public override void Update(float frameTime)
@@ -85,7 +85,7 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
CacheAndOrderRecipes();
}
private void OnExaminedEvent(Entity<CP14FoodVisualsComponent> ent, ref ExaminedEvent args)
private void OnExaminedEvent(Entity<CP14FoodHolderComponent> ent, ref ExaminedEvent args)
{
if (ent.Comp.FoodData?.Name is null)
return;
@@ -107,31 +107,32 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
/// <summary>
/// Transfer food data from cooker to holder
/// </summary>
private void MoveFoodToHolder(Entity<CP14FoodHolderComponent> holder, Entity<CP14FoodCookerComponent> cooker)
protected virtual bool TryTransferFood(Entity<CP14FoodHolderComponent> target,
Entity<CP14FoodHolderComponent> source)
{
if (holder.Comp.HoldFood || !cooker.Comp.HoldFood)
return;
if (!source.Comp.CanGiveFood || !target.Comp.CanAcceptFood)
return false;
if (holder.Comp.FoodType != cooker.Comp.FoodType)
return;
if (target.Comp.FoodType != source.Comp.FoodType)
return false;
if (!TryComp<FoodComponent>(holder, out var holderFoodComp))
return;
if (source.Comp.FoodData is null)
return false;
if (!TryComp<CP14FoodVisualsComponent>(cooker, out var cookerFoodVisuals) || cookerFoodVisuals.FoodData is null)
return;
if (!TryComp<FoodComponent>(target, out var holderFoodComp))
return false;
if (!_solution.TryGetSolution(cooker.Owner, cooker.Comp.SolutionId, out var cookerSoln, out var cookerSolution))
return;
if (!_solution.TryGetSolution(source.Owner, source.Comp.SolutionId, out var cookerSoln, out var cookerSolution))
return false;
//Solutions
if (_solution.TryGetSolution(holder.Owner, holderFoodComp.Solution, out var holderSoln, out var solution))
if (_solution.TryGetSolution(target.Owner, holderFoodComp.Solution, out var holderSoln, out var solution))
{
if (solution.Volume > 0)
{
_popup.PopupEntity(Loc.GetString("cp14-cooking-popup-not-empty", ("name", MetaData(holder).EntityName)),
holder);
return;
_popup.PopupEntity(Loc.GetString("cp14-cooking-popup-not-empty", ("name", MetaData(target).EntityName)),
target);
return false;
}
_solution.TryTransferSolution(holderSoln.Value, cookerSolution, solution.MaxVolume);
@@ -139,63 +140,77 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
//Trash
//If we have a lot of trash, we put 1 random trash in each plate. If it's a last plate (out of solution in cooker), we put all the remaining trash in it.
if (cookerFoodVisuals.FoodData.Trash.Count > 0)
if (source.Comp.FoodData?.Trash.Count > 0)
{
if (cookerSolution.Volume <= 0)
{
holderFoodComp.Trash.AddRange(cookerFoodVisuals.FoodData.Trash);
holderFoodComp.Trash.AddRange(source.Comp.FoodData.Trash);
}
else
{
if (_net.IsServer)
{
var newTrash = _random.Pick(cookerFoodVisuals.FoodData.Trash);
cookerFoodVisuals.FoodData.Trash.Remove(newTrash);
var newTrash = _random.Pick(source.Comp.FoodData.Trash);
source.Comp.FoodData.Trash.Remove(newTrash);
holderFoodComp.Trash.Add(newTrash);
}
}
}
if (source.Comp.FoodData is not null)
UpdateFoodDataVisuals(target, source.Comp.FoodData);
Dirty(target);
Dirty(source);
_solution.UpdateChemicals(cookerSoln.Value);
return true;
}
private void UpdateFoodDataVisuals(
Entity<CP14FoodHolderComponent> ent,
bool rename = true)
{
var data = ent.Comp.FoodData;
if (data is null)
return;
UpdateFoodDataVisuals(ent, data, rename);
}
protected virtual void UpdateFoodDataVisuals(
Entity<CP14FoodHolderComponent> ent,
CP14FoodData data,
bool rename = true)
{
//Name and Description
if (cookerFoodVisuals.FoodData.Name is not null)
_metaData.SetEntityName(holder, Loc.GetString(cookerFoodVisuals.FoodData.Name));
if (cookerFoodVisuals.FoodData.Desc is not null)
_metaData.SetEntityDescription(holder, Loc.GetString(cookerFoodVisuals.FoodData.Desc));
if (rename)
{
if (data.Name is not null)
_metaData.SetEntityName(ent, Loc.GetString(data.Name));
if (data.Desc is not null)
_metaData.SetEntityDescription(ent, Loc.GetString(data.Desc));
}
//Flavors
EnsureComp<FlavorProfileComponent>(holder, out var flavorComp);
foreach (var flavor in cookerFoodVisuals.FoodData.Flavors)
EnsureComp<FlavorProfileComponent>(ent, out var flavorComp);
foreach (var flavor in data.Flavors)
{
flavorComp.Flavors.Add(flavor);
}
//Visuals
var holderFoodVisuals = EnsureComp<CP14FoodVisualsComponent>(holder);
holderFoodVisuals.FoodData = new CP14FoodData(cookerFoodVisuals.FoodData);
//Visual random
foreach (var layer in holderFoodVisuals.FoodData.Visuals)
ent.Comp.FoodData = new CP14FoodData(data);
foreach (var layer in data.Visuals)
{
if (_random.Prob(0.5f))
layer.Scale = new Vector2(-1, 1);
}
//Clear cooker data
if (cookerSolution.Volume <= 0)
{
cookerFoodVisuals.FoodData = null;
cooker.Comp.HoldFood = false;
}
holder.Comp.HoldFood = true;
Dirty(holder, holderFoodVisuals);
Dirty(cooker, cookerFoodVisuals);
Dirty(holder);
Dirty(cooker);
_solution.UpdateChemicals(cookerSoln.Value);
//Sliceable
// > on server overrided side
}
public CP14CookingRecipePrototype? GetRecipe(Entity<CP14FoodCookerComponent> ent)
@@ -218,7 +233,9 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
return GetRecipe(ent.Comp.FoodType, solution, allTags);
}
public CP14CookingRecipePrototype? GetRecipe(CP14FoodType foodType, Solution? solution, List<ProtoId<TagPrototype>> allTags)
public CP14CookingRecipePrototype? GetRecipe(ProtoId<CP14FoodTypePrototype> foodType,
Solution? solution,
List<ProtoId<TagPrototype>> allTags)
{
if (OrderedRecipes.Count == 0)
{
@@ -252,7 +269,7 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
return selectedRecipe;
}
protected void CookFood(Entity<CP14FoodCookerComponent> ent, CP14CookingRecipePrototype recipe)
protected void CreateFoodData(Entity<CP14FoodCookerComponent> ent, CP14CookingRecipePrototype recipe)
{
if (!_solution.TryGetSolution(ent.Owner, ent.Comp.SolutionId, out var soln, out var solution))
return;
@@ -260,18 +277,7 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
if (!_container.TryGetContainer(ent, ent.Comp.ContainerId, out var container))
return;
var newData = new CP14FoodData
{
Visuals = new List<PrototypeLayerData>(recipe.FoodData.Visuals),
Trash = new List<EntProtoId>(recipe.FoodData.Trash),
Flavors = new HashSet<LocId>(recipe.FoodData.Flavors),
Name = recipe.FoodData.Name,
Desc = recipe.FoodData.Desc,
CurrentRecipe = recipe
};
newData.Name = recipe.FoodData.Name;
newData.Desc = recipe.FoodData.Desc;
var newData = new CP14FoodData(recipe.FoodData);
//Process entities
foreach (var contained in container.ContainedEntities)
@@ -307,36 +313,36 @@ public abstract partial class CP14SharedCookingSystem : EntitySystem
if (solution.Volume <= 0)
return;
var foodVisuals = EnsureComp<CP14FoodVisualsComponent>(ent.Owner);
foodVisuals.FoodData = newData;
ent.Comp.HoldFood = true;
if (TryComp<CP14FoodHolderComponent>(ent.Owner, out var holder))
{
holder.FoodData = newData;
Dirty(ent.Owner, holder);
}
Dirty(ent);
Dirty(ent, foodVisuals);
}
protected void BurntFood(Entity<CP14FoodCookerComponent> ent)
{
if (!TryComp<CP14FoodVisualsComponent>(ent, out var foodVisuals) || foodVisuals.FoodData is null)
if (!TryComp<CP14FoodHolderComponent>(ent, out var holder) || holder.FoodData is null)
return;
if (!_solution.TryGetSolution(ent.Owner, ent.Comp.SolutionId, out var soln, out var solution))
return;
//Brown visual
foreach (var visuals in foodVisuals.FoodData.Visuals)
foreach (var visuals in holder.FoodData.Visuals)
{
visuals.Color = Color.FromHex("#212121");
}
foodVisuals.FoodData.Name = Loc.GetString("cp14-meal-recipe-burned-trash-name");
foodVisuals.FoodData.Desc = Loc.GetString("cp14-meal-recipe-burned-trash-desc");
holder.FoodData.Name = Loc.GetString("cp14-meal-recipe-burned-trash-name");
holder.FoodData.Desc = Loc.GetString("cp14-meal-recipe-burned-trash-desc");
var replacedVolume = solution.Volume / 2;
solution.SplitSolution(replacedVolume);
solution.AddReagent(_burntFoodReagent, replacedVolume / 2);
DirtyField(ent.Owner, foodVisuals, nameof(CP14FoodVisualsComponent.FoodData));
DirtyField(ent.Owner, holder, nameof(CP14FoodHolderComponent.FoodData));
}
}