-
Notifications
You must be signed in to change notification settings - Fork 475
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
6258084
commit eeced1a
Showing
20 changed files
with
1,009 additions
and
904 deletions.
There are no files selected for viewing
1 change: 1 addition & 0 deletions
1
Content.Client/Nyanotrasen/Kitchen/Components/DeepFriedComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
Content.Client/Nyanotrasen/Kitchen/Components/DeepFryerComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 1 addition & 1 deletion
2
Content.Client/Nyanotrasen/Kitchen/UI/DeepFryerBoundUserInterface.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
2 changes: 2 additions & 0 deletions
2
Content.Client/Nyanotrasen/Kitchen/Visualizers/DeepFryerVisualizer.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
1 change: 1 addition & 0 deletions
1
Content.Server/Nyanotrasen/Kitchen/Components/DeepFriedComponent.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
181 changes: 181 additions & 0 deletions
181
Content.Server/Nyanotrasen/Kitchen/EntitySystems/DeepFryerSystem.Results.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,181 @@ | ||
using System.Text; | ||
using Content.Server.Atmos.Components; | ||
using Content.Server.Body.Components; | ||
using Content.Server.Ghost.Roles.Components; | ||
using Content.Server.Kitchen.Components; | ||
using Content.Server.Nutrition.Components; | ||
using Content.Server.Nyanotrasen.Kitchen.Components; | ||
using Content.Server.Paper; | ||
using Content.Shared.Atmos.Rotting; | ||
using Content.Shared.Buckle.Components; | ||
using Content.Shared.Chemistry.Components; | ||
using Content.Shared.FixedPoint; | ||
using Content.Shared.Mobs.Components; | ||
using Content.Shared.NPC; | ||
using Content.Shared.Nutrition.Components; | ||
using Content.Shared.Nyanotrasen.Kitchen.Components; | ||
using Robust.Shared.Random; | ||
|
||
namespace Content.Server.Nyanotrasen.Kitchen.EntitySystems; | ||
|
||
public sealed partial class DeepFryerSystem | ||
{ | ||
/// <summary> | ||
/// Make an item look deep-fried. | ||
/// </summary> | ||
public void MakeCrispy(EntityUid item) | ||
{ | ||
EnsureComp<AppearanceComponent>(item); | ||
EnsureComp<DeepFriedComponent>(item); | ||
|
||
_appearanceSystem.SetData(item, DeepFriedVisuals.Fried, true); | ||
} | ||
|
||
/// <summary> | ||
/// Turn a dead mob into food. | ||
/// </summary> | ||
/// <remarks> | ||
/// This is meant to be an irreversible process, similar to gibbing. | ||
/// </remarks> | ||
public bool TryMakeMobIntoFood(EntityUid mob, MobStateComponent mobStateComponent, bool force = false) | ||
{ | ||
// Don't do anything to mobs until they're dead. | ||
if (force || _mobStateSystem.IsDead(mob, mobStateComponent)) | ||
{ | ||
RemComp<ActiveNPCComponent>(mob); | ||
RemComp<AtmosExposedComponent>(mob); | ||
RemComp<BarotraumaComponent>(mob); | ||
RemComp<BuckleComponent>(mob); | ||
RemComp<GhostTakeoverAvailableComponent>(mob); | ||
RemComp<InternalsComponent>(mob); | ||
RemComp<PerishableComponent>(mob); | ||
RemComp<RespiratorComponent>(mob); | ||
RemComp<RottingComponent>(mob); | ||
|
||
// Ensure it's Food here, so it passes the whitelist. | ||
var mobFoodComponent = EnsureComp<FoodComponent>(mob); | ||
_solutionContainerSystem.EnsureSolution(mob, mobFoodComponent.Solution, out var alreadyHadFood); | ||
|
||
if (!_solutionContainerSystem.TryGetSolution(mob, mobFoodComponent.Solution, out var mobFoodSolution)) | ||
return false; | ||
|
||
// This line here is mainly for mice, because they have a food | ||
// component that mirrors how much blood they have, which is | ||
// used for the reagent grinder. | ||
if (alreadyHadFood) | ||
_solutionContainerSystem.RemoveAllSolution(mobFoodSolution.Value); | ||
|
||
if (TryComp<BloodstreamComponent>(mob, out var bloodstreamComponent) && bloodstreamComponent.ChemicalSolution != null) | ||
{ | ||
// Fry off any blood into protein. | ||
var bloodSolution = bloodstreamComponent.BloodSolution; | ||
var solPresent = bloodSolution!.Value.Comp.Solution.Volume; | ||
_solutionContainerSystem.RemoveReagent(bloodSolution.Value, "Blood", FixedPoint2.MaxValue); | ||
var bloodRemoved = solPresent - bloodSolution.Value.Comp.Solution.Volume; | ||
|
||
var proteinQuantity = bloodRemoved * BloodToProteinRatio; | ||
mobFoodSolution.Value.Comp.Solution.MaxVolume += proteinQuantity; | ||
_solutionContainerSystem.TryAddReagent(mobFoodSolution.Value, "Protein", proteinQuantity); | ||
|
||
// This is a heuristic. If you had blood, you might just taste meaty. | ||
if (bloodRemoved > FixedPoint2.Zero) | ||
EnsureComp<FlavorProfileComponent>(mob).Flavors.Add(MobFlavorMeat); | ||
|
||
// Bring in whatever chemicals they had in them too. | ||
mobFoodSolution.Value.Comp.Solution.MaxVolume += | ||
bloodstreamComponent.ChemicalSolution.Value.Comp.Solution.Volume; | ||
_solutionContainerSystem.AddSolution(mobFoodSolution.Value, | ||
bloodstreamComponent.ChemicalSolution.Value.Comp.Solution); | ||
} | ||
|
||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
|
||
/// <summary> | ||
/// Make an item actually edible. | ||
/// </summary> | ||
private void MakeEdible(EntityUid uid, DeepFryerComponent component, EntityUid item, FixedPoint2 solutionQuantity) | ||
{ | ||
if (!TryComp<DeepFriedComponent>(item, out var deepFriedComponent)) | ||
{ | ||
_sawmill.Error($"{ToPrettyString(item)} is missing the DeepFriedComponent before being made Edible."); | ||
return; | ||
} | ||
|
||
// Remove any components that wouldn't make sense anymore. | ||
RemComp<ButcherableComponent>(item); | ||
|
||
if (TryComp<PaperComponent>(item, out var paperComponent)) | ||
{ | ||
var stringBuilder = new StringBuilder(); | ||
|
||
for (var i = 0; i < paperComponent.Content.Length; ++i) | ||
{ | ||
var uchar = paperComponent.Content.Substring(i, 1); | ||
|
||
if (uchar == "\n" || _random.Prob(0.4f)) | ||
stringBuilder.Append(uchar); | ||
else | ||
stringBuilder.Append("x"); | ||
} | ||
|
||
paperComponent.Content = stringBuilder.ToString(); | ||
} | ||
|
||
var foodComponent = EnsureComp<FoodComponent>(item); | ||
var extraSolution = new Solution(); | ||
if (TryComp(item, out FlavorProfileComponent? flavorProfileComponent)) | ||
{ | ||
HashSet<string> goodFlavors = new(flavorProfileComponent.Flavors); | ||
goodFlavors.IntersectWith(component.GoodFlavors); | ||
|
||
HashSet<string> badFlavors = new(flavorProfileComponent.Flavors); | ||
badFlavors.IntersectWith(component.BadFlavors); | ||
|
||
deepFriedComponent.PriceCoefficient = Math.Max(0.01f, | ||
1.0f | ||
+ goodFlavors.Count * component.GoodFlavorPriceBonus | ||
- badFlavors.Count * component.BadFlavorPriceMalus); | ||
|
||
if (goodFlavors.Count > 0) | ||
{ | ||
foreach (var reagent in component.GoodReagents) | ||
{ | ||
extraSolution.AddReagent(reagent.Reagent.ToString(), reagent.Quantity * goodFlavors.Count); | ||
|
||
// Mask the taste of "medicine." | ||
flavorProfileComponent.IgnoreReagents.Add(reagent.Reagent.ToString()); | ||
} | ||
} | ||
|
||
if (badFlavors.Count > 0) | ||
{ | ||
foreach (var reagent in component.BadReagents) | ||
{ | ||
extraSolution.AddReagent(reagent.Reagent.ToString(), reagent.Quantity * badFlavors.Count); | ||
} | ||
} | ||
} | ||
else | ||
{ | ||
flavorProfileComponent = EnsureComp<FlavorProfileComponent>(item); | ||
// TODO: Default flavor? | ||
} | ||
|
||
// Make sure there's enough room for the fryer solution. | ||
var foodSolution = _solutionContainerSystem.EnsureSolution(item, foodComponent.Solution); | ||
if (!_solutionContainerSystem.TryGetSolution(item, foodSolution.Name, out var foodContainer)) | ||
return; | ||
|
||
// The solution quantity is used to give the fried food an extra | ||
// buffer too, to support injectables or condiments. | ||
foodSolution.MaxVolume = 2 * solutionQuantity + foodSolution.Volume + extraSolution.Volume; | ||
_solutionContainerSystem.AddSolution(foodContainer.Value, | ||
component.Solution.SplitSolution(solutionQuantity)); | ||
_solutionContainerSystem.AddSolution(foodContainer.Value, extraSolution); | ||
_solutionContainerSystem.UpdateChemicals(foodContainer.Value); | ||
} | ||
} |
93 changes: 93 additions & 0 deletions
93
Content.Server/Nyanotrasen/Kitchen/EntitySystems/DeepFryerSystem.Storage.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
using Content.Server.Kitchen.Components; | ||
using Content.Server.Nyanotrasen.Kitchen.Components; | ||
using Content.Shared.Chemistry.Components; | ||
using Content.Shared.Database; | ||
using Content.Shared.Hands.Components; | ||
using Content.Shared.Interaction; | ||
using Content.Shared.Item; | ||
using Content.Shared.Nyanotrasen.Kitchen.UI; | ||
using Content.Shared.Storage; | ||
using Content.Shared.Tools.Components; | ||
|
||
namespace Content.Server.Nyanotrasen.Kitchen.EntitySystems; | ||
|
||
public sealed partial class DeepFryerSystem | ||
{ | ||
public bool CanInsertItem(EntityUid uid, DeepFryerComponent component, EntityUid item) | ||
{ | ||
// Keep this consistent with the checks in TryInsertItem. | ||
return HasComp<ItemComponent>(item) && | ||
!HasComp<StorageComponent>(item) && | ||
component.Storage.ContainedEntities.Count < component.StorageMaxEntities; | ||
} | ||
|
||
private bool TryInsertItem(EntityUid uid, DeepFryerComponent component, EntityUid user, EntityUid item) | ||
{ | ||
if (!HasComp<ItemComponent>(item)) | ||
{ | ||
_popupSystem.PopupEntity( | ||
Loc.GetString("deep-fryer-interact-using-not-item"), | ||
uid, | ||
user); | ||
return false; | ||
} | ||
|
||
if (HasComp<StorageComponent>(item)) | ||
{ | ||
_popupSystem.PopupEntity( | ||
Loc.GetString("deep-fryer-storage-no-fit", | ||
("item", item)), | ||
uid, | ||
user); | ||
return false; | ||
} | ||
|
||
if (component.Storage.ContainedEntities.Count >= component.StorageMaxEntities) | ||
{ | ||
_popupSystem.PopupEntity( | ||
Loc.GetString("deep-fryer-storage-full"), | ||
uid, | ||
user); | ||
return false; | ||
} | ||
|
||
if (!_handsSystem.TryDropIntoContainer(user, item, component.Storage)) | ||
return false; | ||
|
||
AfterInsert(uid, component, item); | ||
|
||
_adminLogManager.Add(LogType.Action, LogImpact.Low, | ||
$"{ToPrettyString(user)} put {ToPrettyString(item)} inside {ToPrettyString(uid)}."); | ||
|
||
return true; | ||
} | ||
|
||
private void OnInteractUsing(EntityUid uid, DeepFryerComponent component, InteractUsingEvent args) | ||
{ | ||
if (args.Handled) | ||
return; | ||
|
||
// By default, allow entities with SolutionTransfer or Tool | ||
// components to perform their usual actions. Inserting them (if | ||
// the chef really wants to) will be supported through the UI. | ||
if (HasComp<SolutionTransferComponent>(args.Used) || | ||
HasComp<ToolComponent>(args.Used)) | ||
return; | ||
|
||
if (TryInsertItem(uid, component, args.User, args.Used)) | ||
args.Handled = true; | ||
} | ||
|
||
private void OnInsertItem(EntityUid uid, DeepFryerComponent component, DeepFryerInsertItemMessage args) | ||
{ | ||
var user = args.Session.AttachedEntity; | ||
|
||
if (user == null || | ||
!TryComp<HandsComponent>(user, out var handsComponent) || | ||
handsComponent.ActiveHandEntity == null) | ||
return; | ||
|
||
if (handsComponent.ActiveHandEntity != null) | ||
TryInsertItem(uid, component, user.Value, handsComponent.ActiveHandEntity.Value); | ||
} | ||
} |
Oops, something went wrong.