diff --git a/Content.Shared/Metabolism/MetabolizerComponent.cs b/Content.Shared/Metabolism/MetabolizerComponent.cs index 263816be69b..3143f16474e 100644 --- a/Content.Shared/Metabolism/MetabolizerComponent.cs +++ b/Content.Shared/Metabolism/MetabolizerComponent.cs @@ -85,6 +85,7 @@ public sealed partial class MetabolizerComponent : Component /// [DataField] [Access(typeof(MetabolizerSystem), Other = AccessPermissions.ReadExecute)] // FIXME Friends + [AutoNetworkedField] // DEN public HashSet>? MetabolizerTypes; /// diff --git a/Content.Shared/Metabolism/MetabolizerSystem.cs b/Content.Shared/Metabolism/MetabolizerSystem.cs index 21de771dfca..2c8c975d089 100644 --- a/Content.Shared/Metabolism/MetabolizerSystem.cs +++ b/Content.Shared/Metabolism/MetabolizerSystem.cs @@ -40,6 +40,8 @@ public override void Initialize() SubscribeLocalEvent(OnMapInit); SubscribeLocalEvent>(OnApplyMetabolicMultiplier); + + InitializeDen(); // DEN - metabolizer extension } private void OnMapInit(Entity ent, ref MapInitEvent args) diff --git a/Content.Shared/_DEN/Metabolism/MetabolizerSystem.cs b/Content.Shared/_DEN/Metabolism/MetabolizerSystem.cs new file mode 100644 index 00000000000..5e059f331b6 --- /dev/null +++ b/Content.Shared/_DEN/Metabolism/MetabolizerSystem.cs @@ -0,0 +1,80 @@ +using System.Linq; +using Content.Shared.Body; +using Content.Shared.Whitelist; +using Robust.Shared.Prototypes; + +namespace Content.Shared.Metabolism; + +public sealed partial class MetabolizerSystem +{ + [Dependency] private BodySystem _body = default!; + [Dependency] private EntityWhitelistSystem _whitelist = default!; + + private void InitializeDen() + { + SubscribeLocalEvent(_body.RelayEvent); + SubscribeLocalEvent(_body.RelayEvent); + + SubscribeLocalEvent>(OnAddTraitMetabolizerEvent); + SubscribeLocalEvent>(OnRemoveTraitMetabolizerEvent); + } + + /// + /// Adds metabolizers to metabolizer organs that pass a whitelist. + /// + /// The metabolizer organ. + private void OnAddTraitMetabolizerEvent(Entity ent, + ref BodyRelayedEvent args) + { + if (args.Args.Metabolizers.Count == 0 + || _whitelist.IsWhitelistFail(args.Args.OrganWhitelist, ent)) + return; + + var metabolizers = args.Args.Metabolizers; + + if (ent.Comp.MetabolizerTypes != null) + metabolizers = metabolizers.Union(ent.Comp.MetabolizerTypes).ToHashSet(); + + ent.Comp.MetabolizerTypes = metabolizers; + Dirty(ent); + } + + /// + /// Removes metabolizers from metabolizer organs that pass a whitelist. + /// + /// The metabolizer organ. + private void OnRemoveTraitMetabolizerEvent(Entity ent, + ref BodyRelayedEvent args) + { + if (args.Args.Metabolizers.Count == 0 + || ent.Comp.MetabolizerTypes == null + || _whitelist.IsWhitelistFail(args.Args.OrganWhitelist, ent)) + return; + + // TODO: add smarter handling for this + var metabolizers = ent.Comp.MetabolizerTypes + .Except(args.Args.Metabolizers) + .ToHashSet(); + + ent.Comp.MetabolizerTypes = metabolizers; + Dirty(ent); + } +} + +/// +/// An event that adds metabolizers to subscribed entities that pass the whitelist. +/// +/// The metabolizers to add. +/// The whitelist for organs to add metabolizers to. +[ByRefEvent] +public record struct AddTraitMetabolizerEvent(HashSet> Metabolizers, + EntityWhitelist? OrganWhitelist = null); + +/// +/// An event that removes metabolizers from subscribed entities that pass the whitelist. +/// +/// The metabolizers to add. +/// The whitelist for organs to add metabolizers to. +[ByRefEvent] +public record struct RemoveTraitMetabolizerEvent(HashSet> Metabolizers, + EntityWhitelist? OrganWhitelist = null); diff --git a/Content.Shared/_DEN/Traits/TraitFunctions/TraitFunctions.Components.cs b/Content.Shared/_DEN/Traits/TraitFunctions/TraitFunctions.Components.cs index a26f733ac49..a01775f5ea8 100644 --- a/Content.Shared/_DEN/Traits/TraitFunctions/TraitFunctions.Components.cs +++ b/Content.Shared/_DEN/Traits/TraitFunctions/TraitFunctions.Components.cs @@ -1,3 +1,5 @@ +using Content.Shared.Metabolism; +using Content.Shared.Whitelist; using JetBrains.Annotations; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.Manager; @@ -58,3 +60,35 @@ public void OnTraitRemoved(EntityUid owner, EntityManager entityManager) } } } + +/// +/// A trait that adds a metabolizer to this entity's organs. +/// +[UsedImplicitly] +public sealed partial class AddMetabolizerTrait : ITraitFunction +{ + /// + /// A set of metabolizers to add to this entity's organs. + /// + [DataField] public HashSet> MetabolizerTypes = []; + + /// + /// A whitelist of allowed organs to use for this trait. + /// + /// + /// For example: you can have this only apply to the heart or lungs by whitelisting Heart or Lung components. + /// + [DataField] public EntityWhitelist? OrganWhitelist = null; + + public void OnTraitAdded(EntityUid owner, EntityManager entityManager) + { + var ev = new AddTraitMetabolizerEvent(MetabolizerTypes, OrganWhitelist); + entityManager.EventBus.RaiseLocalEvent(owner, ref ev); + } + + public void OnTraitRemoved(EntityUid owner, EntityManager entityManager) + { + var ev = new RemoveTraitMetabolizerEvent(MetabolizerTypes, OrganWhitelist); + entityManager.EventBus.RaiseLocalEvent(owner, ref ev); + } +} diff --git a/Resources/Locale/en-US/_DEN/metabolism/metabolizer-types.ftl b/Resources/Locale/en-US/_DEN/metabolism/metabolizer-types.ftl new file mode 100644 index 00000000000..b3b8f035900 --- /dev/null +++ b/Resources/Locale/en-US/_DEN/metabolism/metabolizer-types.ftl @@ -0,0 +1 @@ +metabolizer-type-detritivore = Detritivore diff --git a/Resources/Locale/en-US/_DEN/traits/categories.ftl b/Resources/Locale/en-US/_DEN/traits/categories.ftl index ea2c28cb065..497bc06bf7c 100644 --- a/Resources/Locale/en-US/_DEN/traits/categories.ftl +++ b/Resources/Locale/en-US/_DEN/traits/categories.ftl @@ -1,2 +1,3 @@ +trait-category-perks = Perks trait-category-species-morphs = Morphotypes trait-category-species-specific = Species-specific diff --git a/Resources/Locale/en-US/_DEN/traits/perks.ftl b/Resources/Locale/en-US/_DEN/traits/perks.ftl new file mode 100644 index 00000000000..0ecea78cc4b --- /dev/null +++ b/Resources/Locale/en-US/_DEN/traits/perks.ftl @@ -0,0 +1,4 @@ +trait-detritivore-name = Detritivore +trait-detritivore-desc = + You can digest gastrotoxin (rotting food), mold, and trash without being + poisoned, and sate your hunger by doing so! diff --git a/Resources/Prototypes/Body/Animals/rat.yml b/Resources/Prototypes/Body/Animals/rat.yml index e8bf585c663..047df6f4c5e 100644 --- a/Resources/Prototypes/Body/Animals/rat.yml +++ b/Resources/Prototypes/Body/Animals/rat.yml @@ -4,7 +4,7 @@ suffix: Rat components: - type: Metabolizer - metabolizerTypes: [ Rat ] + metabolizerTypes: [ Rat, Detritivore ] # DEN: Add Detritivore - type: entity id: BaseMobRat @@ -16,7 +16,7 @@ body_organs: !type:AllSelector children: - id: OrganRatLungs - - id: OrganAnimalHeart - - id: OrganAnimalStomach - - id: OrganAnimalLiver - - id: OrganAnimalKidneys + - id: OrganDetritivoreHeart # DEN: OrganAnimalHeart -> OrganDetritivoreHeart + - id: OrganDetritivoreStomach # DEN: OrganAnimalStomach -> OrganDetritivoreStomach + - id: OrganDetritivoreLiver # DEN: OrganAnimalLiver -> OrganDetritivoreLiver + - id: OrganDetritivoreKidneys # DEN: OrganAnimalKidneys -> OrganDetritivoreKidneys diff --git a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml index 748aa802c95..c01cd3367ba 100644 --- a/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml +++ b/Resources/Prototypes/Entities/Mobs/NPCs/animals.yml @@ -1923,7 +1923,7 @@ - type: entity name: mouse - parent: [SimpleMobBase, BaseMobAnimal, SolutionVermin, BaseSlicingRefinable] + parent: [BaseMobDetritivore, SimpleMobBase, SolutionVermin, BaseSlicingRefinable] # DEN: BaseMobAnimal -> BaseMobDetritivore id: MobMouse description: Squeak! components: diff --git a/Resources/Prototypes/Reagents/toxins.yml b/Resources/Prototypes/Reagents/toxins.yml index 670baa829bd..26eee206c27 100644 --- a/Resources/Prototypes/Reagents/toxins.yml +++ b/Resources/Prototypes/Reagents/toxins.yml @@ -93,6 +93,10 @@ Bloodstream: effects: - !type:HealthChange + conditions: # DEN: Detritivore metabolism + - !type:MetabolizerTypeCondition + type: [ Detritivore ] + inverted: true damage: types: Poison: 2 @@ -101,7 +105,15 @@ - !type:ReagentCondition reagent: GastroToxin min: 2 + - !type:MetabolizerTypeCondition # DEN: Detritivore metabolism + type: [ Detritivore ] + inverted: true probability: 0.2 + - !type:SatiateHunger # DEN: Detritivore metabolism + # DEN Comment: This cannot be in Digestion or the metabolism will break. + conditions: + - !type:MetabolizerTypeCondition + type: [ Detritivore ] - type: reagent id: Mold @@ -116,9 +128,18 @@ Bloodstream: effects: - !type:HealthChange + conditions: # DEN: Detritivore metabolism + - !type:MetabolizerTypeCondition + type: [ Detritivore ] + inverted: true damage: types: Poison: 1 + - !type:SatiateHunger # DEN: Detritivores can digest mold. + # DEN Comment: This cannot be in Digestion or the metabolism will break. + conditions: + - !type:MetabolizerTypeCondition + type: [ Detritivore ] - type: reagent id: PolytrinicAcid @@ -454,6 +475,16 @@ damage: types: Poison: 2 + conditions: # DEN: Detritivores aren't poisoned by vent crud + - !type:MetabolizerTypeCondition + type: [ Detritivore ] + inverted: true + - !type:SatiateHunger # DEN: Detritivores can process vent crud + # DEN Comment: This cannot be in Digestion or the metabolism will break. + factor: 0.75 + conditions: + - !type:MetabolizerTypeCondition + type: [ Detritivore ] - type: reagent id: Romerol @@ -488,7 +519,7 @@ - !type:PopupMessage conditions: - !type:MetabolizerTypeCondition - type: [ Animal, Vox ] + type: [ Animal, Vox, Detritivore ] # DEN: Add Detritivore inverted: true type: Local visualType: MediumCaution @@ -498,12 +529,12 @@ probability: 0.1 conditions: - !type:MetabolizerTypeCondition - type: [ Animal, Vox, Plant ] + type: [ Animal, Vox, Plant, Detritivore ] # DEN: Add Detritivore inverted: true - !type:HealthChange conditions: - !type:MetabolizerTypeCondition - type: [ Animal, Vox, Plant ] + type: [ Animal, Vox, Plant, Detritivore ] # DEN: Add Detritivore inverted: true damage: types: @@ -518,13 +549,16 @@ - !type:AdjustReagent conditions: - !type:MetabolizerTypeCondition - type: [ Animal ] + type: [ Animal, Detritivore ] # DEN: Add Detritivore reagent: Protein amount: 0.5 - !type:AdjustReagent conditions: - !type:MetabolizerTypeCondition type: [ Vox ] + - !type:MetabolizerTypeCondition # DEN: Prevent redundant metabolism for detritivore vox + type: [ Detritivore ] + inverted: true reagent: Protein amount: 0.25 @@ -762,6 +796,31 @@ conditions: - !type:MetabolizerTypeCondition type: [Vox] + - !type:SatiateHunger # DEN: Detritivores can process trash + factor: 0.75 + conditions: + - !type:MetabolizerTypeCondition + type: [ Detritivore ] + - !type:MetabolizerTypeCondition + inverted: true + type: [Vox] + - !type:HealthChange # DEN: Add poison effect to trash + damage: + types: + Poison: 2 + conditions: + - !type:MetabolizerTypeCondition + inverted: true + type: [ Vox, Detritivore ] + - !type:Vomit # DEN: Add poison effect to trash + probability: 0.2 + conditions: + - !type:ReagentCondition + reagent: ToxinTrash + min: 2 + - !type:MetabolizerTypeCondition # DEN: Detritivore metabolism + type: [ Vox, Detritivore ] + inverted: true - type: reagent id: Hemorrhinol diff --git a/Resources/Prototypes/_DEN/Body/Animals/detritivore.yml b/Resources/Prototypes/_DEN/Body/Animals/detritivore.yml new file mode 100644 index 00000000000..afdcdcae9af --- /dev/null +++ b/Resources/Prototypes/_DEN/Body/Animals/detritivore.yml @@ -0,0 +1,54 @@ +- type: entity + id: OrganDetritivoreMetabolizer + abstract: true + components: + - type: Metabolizer + metabolizerTypes: [ Animal, Detritivore ] + +- type: entity + parent: OrganBaseOrganic + id: OrganDetritivore + abstract: true + suffix: Detritivore + +- type: entity + parent: OrganDetritivore + id: OrganDetritivoreInternal + abstract: true + components: + - type: Sprite + sprite: Mobs/Species/Human/organs.rsi # TODO: Custom detritivore organ sprites + +- type: entity + parent: [ OrganBaseLungs, OrganDetritivoreInternal, OrganDetritivoreMetabolizer ] + id: OrganDetritivoreLungs + +- type: entity + parent: [ OrganBaseHeart, OrganDetritivoreInternal, OrganDetritivoreMetabolizer ] + id: OrganDetritivoreHeart + +- type: entity + parent: [ OrganBaseStomach, OrganDetritivoreInternal, OrganDetritivoreMetabolizer ] + id: OrganDetritivoreStomach + +- type: entity + parent: [ OrganBaseLiver, OrganDetritivoreInternal, OrganDetritivoreMetabolizer ] + id: OrganDetritivoreLiver + +- type: entity + parent: [ OrganBaseKidneys, OrganDetritivoreInternal, OrganDetritivoreMetabolizer ] + id: OrganDetritivoreKidneys + +- type: entity + abstract: true + id: BaseMobDetritivore + components: + - type: EntityTableContainerFill + containers: + body_organs: !type:AllSelector + children: + - id: OrganDetritivoreLungs + - id: OrganDetritivoreHeart + - id: OrganDetritivoreStomach + - id: OrganDetritivoreLiver + - id: OrganDetritivoreKidneys diff --git a/Resources/Prototypes/_DEN/Chemistry/metabolizer_types.yml b/Resources/Prototypes/_DEN/Chemistry/metabolizer_types.yml new file mode 100644 index 00000000000..0dcce66e563 --- /dev/null +++ b/Resources/Prototypes/_DEN/Chemistry/metabolizer_types.yml @@ -0,0 +1,5 @@ +# Hardy digestion for trash eaters and decomposers. +# Can consume gastrotoxin, trash, and mold safely, and derive nutrition from doing so. +- type: metabolizerType + id: Detritivore + name: metabolizer-type-detritivore diff --git a/Resources/Prototypes/_DEN/EntityTraits/categories.yml b/Resources/Prototypes/_DEN/EntityTraits/categories.yml index 723ce83024a..43139ce980e 100644 --- a/Resources/Prototypes/_DEN/EntityTraits/categories.yml +++ b/Resources/Prototypes/_DEN/EntityTraits/categories.yml @@ -1,3 +1,8 @@ +- type: traitCategory + id: Perks + name: trait-category-perks + priority: -8 + - type: traitCategory id: SpeciesMorphs name: trait-category-species-morphs diff --git a/Resources/Prototypes/_DEN/EntityTraits/perks.yml b/Resources/Prototypes/_DEN/EntityTraits/perks.yml new file mode 100644 index 00000000000..439e614d7bb --- /dev/null +++ b/Resources/Prototypes/_DEN/EntityTraits/perks.yml @@ -0,0 +1,12 @@ +- type: entityTrait + id: Detritivore + name: trait-detritivore-name + description: trait-detritivore-desc + category: Perks + # requirements: + # - !type:PlayerSpeciesRequirement + # species: [Rodentia] # TODO: Rodentia + # inverted: true + functions: + - !type:AddMetabolizerTrait + metabolizerTypes: [Detritivore]