From 37b02466ffc27fe51a94e142456a7bbf28849c26 Mon Sep 17 00:00:00 2001 From: deltanedas <39013340+deltanedas@users.noreply.github.com> Date: Sun, 6 Aug 2023 04:05:43 +0100 Subject: [PATCH] rotting meat (#18515) Co-authored-by: deltanedas <@deltanedas:kde.org> Co-authored-by: metalgearsloth <31366439+metalgearsloth@users.noreply.github.com> --- Content.Server/Atmos/Miasma/RottingSystem.cs | 32 +++++-- .../Atmos/Miasma/PerishableComponent.cs | 2 +- .../Atmos/Miasma/RotIntoComponent.cs | 26 ++++++ .../Entities/Objects/Consumable/Food/meat.yml | 91 ++++++++----------- 4 files changed, 92 insertions(+), 59 deletions(-) create mode 100644 Content.Shared/Atmos/Miasma/RotIntoComponent.cs diff --git a/Content.Server/Atmos/Miasma/RottingSystem.cs b/Content.Server/Atmos/Miasma/RottingSystem.cs index 9cf81df664..6887cd93e8 100644 --- a/Content.Server/Atmos/Miasma/RottingSystem.cs +++ b/Content.Server/Atmos/Miasma/RottingSystem.cs @@ -6,6 +6,7 @@ using Content.Server.Temperature.Components; using Content.Shared.Atmos.Miasma; using Content.Shared.Examine; using Content.Shared.Mobs; +using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Rejuvenate; using Robust.Server.Containers; @@ -81,8 +82,8 @@ public sealed class RottingSystem : EntitySystem if (!Resolve(uid, ref perishable, false)) return false; - // only dead things perish - if (!_mobState.IsDead(uid)) + // only dead things or inanimate objects can rot + if (TryComp(uid, out var mobState) && !_mobState.IsDead(uid, mobState)) return false; if (_container.TryGetOuterContainer(uid, Transform(uid), out var container) && @@ -119,10 +120,7 @@ public sealed class RottingSystem : EntitySystem private void OnExamined(EntityUid uid, RottingComponent component, ExaminedEvent args) { - if (!TryComp(uid, out var perishable)) - return; - - var stage = (int) (component.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds); + var stage = RotStage(uid, component); var description = stage switch { >= 2 => "miasma-extremely-bloated", @@ -132,6 +130,17 @@ public sealed class RottingSystem : EntitySystem args.PushMarkup(Loc.GetString(description)); } + /// + /// Return the rot stage, usually from 0 to 2 inclusive. + /// + public int RotStage(EntityUid uid, RottingComponent? comp = null, PerishableComponent? perishable = null) + { + if (!Resolve(uid, ref comp, ref perishable)) + return 0; + + return (int) (comp.TotalRotTime.TotalSeconds / perishable.RotAfter.TotalSeconds); + } + private void OnRejuvenate(EntityUid uid, RottingComponent component, RejuvenateEvent args) { RemCompDeferred(uid); @@ -183,6 +192,17 @@ public sealed class RottingSystem : EntitySystem _damageable.TryChangeDamage(uid, damage, true, false); } + if (TryComp(uid, out var rotInto)) + { + var stage = RotStage(uid, rotting, perishable); + if (stage >= rotInto.Stage) + { + Spawn(rotInto.Entity, xform.Coordinates); + QueueDel(uid); + continue; + } + } + if (!TryComp(uid, out var physics)) continue; // We need a way to get the mass of the mob alone without armor etc in the future diff --git a/Content.Shared/Atmos/Miasma/PerishableComponent.cs b/Content.Shared/Atmos/Miasma/PerishableComponent.cs index 799dde621a..088c7a9911 100644 --- a/Content.Shared/Atmos/Miasma/PerishableComponent.cs +++ b/Content.Shared/Atmos/Miasma/PerishableComponent.cs @@ -29,7 +29,7 @@ public sealed class PerishableComponent : Component /// /// How often the rotting ticks. - /// Feel free to weak this if there are perf concerns. + /// Feel free to tweak this if there are perf concerns. /// [DataField("perishUpdateRate"), ViewVariables(VVAccess.ReadWrite)] public TimeSpan PerishUpdateRate = TimeSpan.FromSeconds(5); diff --git a/Content.Shared/Atmos/Miasma/RotIntoComponent.cs b/Content.Shared/Atmos/Miasma/RotIntoComponent.cs new file mode 100644 index 0000000000..552f7ad1c9 --- /dev/null +++ b/Content.Shared/Atmos/Miasma/RotIntoComponent.cs @@ -0,0 +1,26 @@ +using Robust.Shared.GameStates; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; + +namespace Content.Shared.Atmos.Miasma; + +/// +/// Lets an entity rot into another entity. +/// Used by raw meat to turn into rotten meat. +/// +[RegisterComponent, NetworkedComponent] +public sealed class RotIntoComponent : Component +{ + /// + /// Entity to rot into. + /// + [DataField("entity", required: true, customTypeSerializer: typeof(PrototypeIdSerializer)), ViewVariables(VVAccess.ReadWrite)] + public string Entity = string.Empty; + + /// + /// Rotting stage to turn at, this is a multiplier of the total rot time. + /// 0 = rotting, 1 = bloated, 2 = extremely bloated + /// + [DataField("stage"), ViewVariables(VVAccess.ReadWrite)] + public int Stage; +} diff --git a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml index f66ed04207..93fcc81f5c 100644 --- a/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml +++ b/Resources/Prototypes/Entities/Objects/Consumable/Food/meat.yml @@ -33,6 +33,25 @@ materialComposition: Meaterial: 300 +- type: entity + parent: FoodMeatBase + id: FoodMeatRawBase + abstract: true + components: + - type: Tag + tags: + - Raw + - type: Perishable + # raw meat rots in 5 minutes, get it into the freezer fast + rotAfter: 300 + # don't want meat giving off miasma only bodies + molsPerSecondPerUnitMass: 0 + - type: RotInto + entity: FoodMeatRotten + # once it would say bloated, turn into the rotten prototype + stage: 1 + +# bruh - type: Tag id: Raw @@ -46,13 +65,10 @@ - type: entity name: raw meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeat description: A slab of raw meat. components: - - type: Tag - tags: - - Raw - type: Sprite state: plain - type: SolutionContainerManager @@ -73,13 +89,10 @@ - type: entity name: raw human meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatHuman description: Gross. components: - - type: Tag - tags: - - Raw - type: Sprite state: plain - type: SolutionContainerManager @@ -121,6 +134,7 @@ - type: entity name: raw bacon + # bacon is cured so not raw = cant rot parent: FoodMeatBase id: FoodMeatBacon description: A raw piece of bacon. @@ -141,13 +155,10 @@ - type: entity name: raw bear meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatBear description: A very manly slab of raw bear meat. components: - - type: Tag - tags: - - Raw - type: Sprite state: bear - type: SolutionContainerManager @@ -168,13 +179,10 @@ - type: entity name: raw penguin meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatPenguin description: A slab of raw penguin meat. Can be used as a substitute for fish in recipes. components: - - type: Tag - tags: - - Raw - type: Sprite state: bird - type: SolutionContainerManager @@ -195,13 +203,10 @@ - type: entity name: raw chicken meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatChicken description: A slab of raw chicken. Remember to wash your hands! components: - - type: Tag - tags: - - Raw - type: Sprite state: bird - type: SolutionContainerManager @@ -222,13 +227,10 @@ - type: entity name: raw duck meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatDuck description: A slab of raw duck. Remember to wash your hands! components: - - type: Tag - tags: - - Raw - type: Sprite state: bird - type: SolutionContainerManager @@ -249,6 +251,7 @@ - type: entity name: prime-cut corgi meat + # can't rot since that would be very bad for syndies parent: FoodMeatBase id: FoodMeatCorgi description: The tainted gift of an evil crime. The meat may be delicious, but at what cost? @@ -270,16 +273,13 @@ - type: entity name: raw crab meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatCrab description: A pile of raw crab meat. components: - type: FlavorProfile flavors: - crabby - - type: Tag - tags: - - Raw - type: Sprite state: crab - type: SolutionContainerManager @@ -297,13 +297,10 @@ - type: entity name: raw goliath meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatGoliath description: A slab of goliath meat. It's not very edible now, but it cooks great in lava. components: - - type: Tag - tags: - - Raw - type: Sprite state: goliath - type: SolutionContainerManager @@ -347,13 +344,10 @@ - type: entity name: raw rat meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatRat description: Prime meat from maintenance! components: - - type: Tag - tags: - - Raw - type: Sprite state: plain - type: SolutionContainerManager @@ -367,13 +361,10 @@ - type: entity name: raw lizard meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatLizard description: Delicious dino damage. components: - - type: Tag - tags: - - Raw - type: Sprite state: lizard - type: SolutionContainerManager @@ -417,17 +408,18 @@ food: reagents: - ReagentId: UncookedAnimalProteins - Quantity: 20 + Quantity: 5 + - ReagentId: Toxin + Quantity: 4 + - ReagentId: Fat + Quantity: 4 - type: entity name: raw spider meat - parent: FoodMeatBase + parent: FoodMeatRawBase id: FoodMeatSpider description: A slab of spider meat. That's so Kafkaesque. components: - - type: Tag - tags: - - Raw - type: Sprite state: spider - type: SolutionContainerManager @@ -448,9 +440,6 @@ id: FoodMeatSpiderLeg description: A still twitching leg of a giant spider... you don't really want to eat this, do you? components: - - type: Tag - tags: - - Raw - type: Sprite state: spiderleg - type: SolutionContainerManager @@ -468,9 +457,6 @@ id: FoodMeatWheat description: This doesn't look like meat, but your standards aren't that high to begin with. components: - - type: Tag - tags: - - Raw - type: Sprite state: clump - type: SolutionContainerManager @@ -482,6 +468,7 @@ - type: entity name: raw xeno meat + # not raw since acid kills bacteria or something, same as xeno parent: FoodMeatBase id: FoodMeatXeno description: A slab of xeno meat, dripping with acid. @@ -581,7 +568,7 @@ - type: entity parent: BaseItem id: MaterialSmileExtract - name: extract smile + name: smile extract description: It's a real panacea. But at what cost? components: - type: Food