From cd776d03fe415ef3fd89f39ed5c793f3cc23ea09 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sat, 17 Aug 2024 15:20:08 -0400 Subject: [PATCH 01/19] Use EntityEffects for new mutation system. Now works for Bioluminescent, slippery, sentient. --- Content.Server/Botany/SeedPrototype.cs | 29 +++------- .../Botany/Systems/BotanySystem.Produce.cs | 10 ++++ .../Botany/Systems/BotanySystem.Seed.cs | 25 +-------- .../Botany/Systems/MutationSystem.cs | 54 +++++++++---------- .../Botany/Systems/PlantHolderSystem.cs | 38 +------------ .../Botany/Systems/SeedExtractorSystem.cs | 6 --- Content.Server/EntityEffects/Effects/Glow.cs | 46 ++++++++++++++++ .../EntityEffects/Effects/Slipify.cs | 41 ++++++++++++++ Content.Shared/Random/RandomPlantMutation.cs | 39 ++++++++++++++ .../RandomPlantMutationListPrototype.cs | 18 +++++++ .../{mutations.yml => randomChemicals.yml} | 0 .../Hydroponics/randomMutations.yml | 12 +++++ 12 files changed, 199 insertions(+), 119 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/Glow.cs create mode 100644 Content.Server/EntityEffects/Effects/Slipify.cs create mode 100644 Content.Shared/Random/RandomPlantMutation.cs create mode 100644 Content.Shared/Random/RandomPlantMutationListPrototype.cs rename Resources/Prototypes/Hydroponics/{mutations.yml => randomChemicals.yml} (100%) create mode 100644 Resources/Prototypes/Hydroponics/randomMutations.yml diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index b2882d8e944102..4cb770228cf58b 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -2,6 +2,7 @@ using Content.Server.Botany.Systems; using Content.Shared.Atmos; using Content.Shared.EntityEffects; +using Content.Shared.Random; using Robust.Shared.Audio; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; @@ -190,16 +191,6 @@ public partial class SeedData /// [DataField("viable")] public bool Viable = true; - /// - /// If true, fruit slips players. - /// - [DataField("slip")] public bool Slip = false; - - /// - /// If true, fruits are sentient. - /// - [DataField("sentient")] public bool Sentient = false; - /// /// If true, a sharp tool is required to harvest this plant. /// @@ -233,16 +224,13 @@ public partial class SeedData [DataField("screaming")] public bool CanScream; - [DataField("bioluminescent")] public bool Bioluminescent; - [DataField("bioluminescentColor")] public Color BioluminescentColor { get; set; } = Color.White; - - public float BioluminescentRadius = 2f; - [DataField("kudzuPrototype", customTypeSerializer: typeof(PrototypeIdSerializer))] public string KudzuPrototype = "WeakKudzu"; [DataField("turnIntoKudzu")] public bool TurnIntoKudzu; [DataField("splatPrototype")] public string? SplatPrototype { get; set; } + public List Mutations { get; set; } = new(); + #endregion /// @@ -292,17 +280,14 @@ public SeedData Clone() Seedless = Seedless, Viable = Viable, - Slip = Slip, - Sentient = Sentient, Ligneous = Ligneous, PlantRsi = PlantRsi, PlantIconState = PlantIconState, - Bioluminescent = Bioluminescent, CanScream = CanScream, TurnIntoKudzu = TurnIntoKudzu, - BioluminescentColor = BioluminescentColor, SplatPrototype = SplatPrototype, + Mutations = Mutations, // Newly cloned seed is unique. No need to unnecessarily clone if repeatedly modified. Unique = true, @@ -353,18 +338,16 @@ public SeedData SpeciesChange(SeedData other) HarvestRepeat = HarvestRepeat, Potency = Potency, + Mutations = Mutations, + Seedless = Seedless, Viable = Viable, - Slip = Slip, - Sentient = Sentient, Ligneous = Ligneous, PlantRsi = other.PlantRsi, PlantIconState = other.PlantIconState, - Bioluminescent = Bioluminescent, CanScream = CanScream, TurnIntoKudzu = TurnIntoKudzu, - BioluminescentColor = BioluminescentColor, SplatPrototype = other.SplatPrototype, // Newly cloned seed is unique. No need to unnecessarily clone if repeatedly modified. diff --git a/Content.Server/Botany/Systems/BotanySystem.Produce.cs b/Content.Server/Botany/Systems/BotanySystem.Produce.cs index e309fb47720db3..f772ea9874cbef 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Produce.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Produce.cs @@ -1,4 +1,5 @@ using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; using Content.Shared.FixedPoint; namespace Content.Server.Botany.Systems; @@ -10,6 +11,15 @@ public void ProduceGrown(EntityUid uid, ProduceComponent produce) if (!TryGetSeed(produce, out var seed)) return; + foreach (var mutation in seed.Mutations) + { + if (mutation.AppliesToProduce) + { + var args = new EntityEffectBaseArgs(uid, EntityManager); + mutation.Mutation.Effect(args); + } + } + var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName, FixedPoint2.Zero, out _); solutionContainer.RemoveAllSolution(); diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index f64fcb3c43dc94..941453efb4ed14 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -174,6 +174,7 @@ public IEnumerable GenerateProduct(SeedData proto, EntityCoordinates produce.Seed = proto; ProduceGrown(entity, produce); + _appearance.SetData(entity, ProduceVisuals.Potency, proto.Potency); if (proto.Mysterious) @@ -183,30 +184,6 @@ public IEnumerable GenerateProduct(SeedData proto, EntityCoordinates _metaData.SetEntityDescription(entity, metaData.EntityDescription + " " + Loc.GetString("botany-mysterious-description-addon"), metaData); } - - if (proto.Bioluminescent) - { - var light = _light.EnsureLight(entity); - _light.SetRadius(entity, proto.BioluminescentRadius, light); - _light.SetColor(entity, proto.BioluminescentColor, light); - // TODO: Ayo why you copy-pasting code between here and plantholder? - _light.SetCastShadows(entity, false, light); // this is expensive, and botanists make lots of plants - } - - if (proto.Slip) - { - var slippery = EnsureComp(entity); - Dirty(entity, slippery); - EnsureComp(entity); - // Need a fixture with a slip layer in order to actually do the slipping - var fixtures = EnsureComp(entity); - var body = EnsureComp(entity); - var shape = fixtures.Fixtures["fix1"].Shape; - _fixtureSystem.TryCreateFixture(entity, shape, "slips", 1, false, (int) CollisionGroup.SlipLayer, manager: fixtures, body: body); - // Need to disable collision wake so that mobs can collide with and slip on it - var collisionWake = EnsureComp(entity); - _colWakeSystem.SetEnabled(entity, false, collisionWake); - } } return products; diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index c9272375102691..88eece97110b3c 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -4,6 +4,7 @@ using Content.Shared.Random.Helpers; using System.Linq; using Content.Shared.Atmos; +using Content.Shared.EntityEffects; namespace Content.Server.Botany; @@ -12,11 +13,31 @@ public sealed class MutationSystem : EntitySystem [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private WeightedRandomFillSolutionPrototype _randomChems = default!; + private RandomPlantMutationListPrototype _randomMutations = default!; public override void Initialize() { _randomChems = _prototypeManager.Index("RandomPickBotanyReagent"); + _randomMutations = _prototypeManager.Index("RandomPlantMutations"); + } + + /// + /// For each random mutation, see if it occurs on this plant this check. + /// + /// + /// + public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float severity) + { + foreach (var mutation in _randomMutations.mutations) + { + if (Random(mutation.BaseOdds * severity)) + { + EntityEffectBaseArgs args = new EntityEffectBaseArgs(plantHolder, EntityManager); + mutation.Mutation.Effect(args); + seed.Mutations.Add(mutation); + } + } } /// @@ -29,7 +50,7 @@ public override void Initialize() /// /// You MUST clone() seed before mutating it! /// - public void MutateSeed(ref SeedData seed, float severity) + public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) { if (!seed.Unique) { @@ -37,6 +58,8 @@ public void MutateSeed(ref SeedData seed, float severity) return; } + CheckRandomMutations(plantHolder, ref seed, severity); //TODO Will be the main call later, just check if this runs for now. + // Add up everything in the bits column and put the number here. const int totalbits = 262; @@ -67,13 +90,9 @@ public void MutateSeed(ref SeedData seed, float severity) // Fun (72) MutateBool(ref seed.Seedless , true , 10, totalbits, severity); - MutateBool(ref seed.Slip , true , 10, totalbits, severity); - MutateBool(ref seed.Sentient , true , 2 , totalbits, severity); MutateBool(ref seed.Ligneous , true , 10, totalbits, severity); - MutateBool(ref seed.Bioluminescent, true , 10, totalbits, severity); MutateBool(ref seed.TurnIntoKudzu , true , 10, totalbits, severity); MutateBool(ref seed.CanScream , true , 10, totalbits, severity); - seed.BioluminescentColor = RandomColor(seed.BioluminescentColor, 10, totalbits, severity); #pragma warning restore IDE0055 // ConstantUpgade (10) @@ -115,19 +134,16 @@ public SeedData Cross(SeedData a, SeedData b) CrossFloat(ref result.Production, a.Production); CrossFloat(ref result.Potency, a.Potency); - // we do not transfer Sentient to another plant to avoid ghost role spam CrossBool(ref result.Seedless, a.Seedless); CrossBool(ref result.Viable, a.Viable); - CrossBool(ref result.Slip, a.Slip); CrossBool(ref result.Ligneous, a.Ligneous); - CrossBool(ref result.Bioluminescent, a.Bioluminescent); CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); CrossBool(ref result.CanScream, a.CanScream); CrossGasses(ref result.ExudeGasses, a.ExudeGasses); CrossGasses(ref result.ConsumeGasses, a.ConsumeGasses); - result.BioluminescentColor = Random(0.5f) ? a.BioluminescentColor : result.BioluminescentColor; + result.Mutations = result.Mutations.Where(m => Random(0.5f)).Union(a.Mutations.Where(m => Random(0.5f))).DistinctBy(m => m.Name).ToList(); // Hybrids have a high chance of being seedless. Balances very // effective hybrid crossings. @@ -301,26 +317,6 @@ private void MutateSpecies(ref SeedData seed, int bits, int totalbits, float mul seed = seed.SpeciesChange(protoSeed); } - - private Color RandomColor(Color color, int bits, int totalbits, float mult) - { - float probModify = mult * bits / totalbits; - if (Random(probModify)) - { - var colors = new List{ - Color.White, - Color.Red, - Color.Yellow, - Color.Green, - Color.Blue, - Color.Purple, - Color.Pink - }; - return _robustRandom.Pick(colors); - } - return color; - } - private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/Botany/Systems/PlantHolderSystem.cs b/Content.Server/Botany/Systems/PlantHolderSystem.cs index 53cee92a2987c3..9d8daefeced784 100644 --- a/Content.Server/Botany/Systems/PlantHolderSystem.cs +++ b/Content.Server/Botany/Systems/PlantHolderSystem.cs @@ -299,15 +299,6 @@ private void OnInteractUsing(Entity entity, ref InteractUs healthOverride = component.Health; } var packetSeed = component.Seed; - if (packetSeed.Sentient) - { - packetSeed = packetSeed.Clone(); // clone before modifying the seed - packetSeed.Sentient = false; - } - else - { - packetSeed.Unique = false; - } var seed = _botany.SpawnSeedPacket(packetSeed, Transform(args.User).Coordinates, args.User, healthOverride); _randomHelper.RandomOffset(seed, 0.25f); var displayName = Loc.GetString(component.Seed.DisplayName); @@ -636,12 +627,6 @@ public void Update(EntityUid uid, PlantHolderComponent? component = null) else if (component.Age < 0) // Revert back to seed packet! { var packetSeed = component.Seed; - if (packetSeed.Sentient) - { - if (!packetSeed.Unique) // clone if necessary before modifying the seed - packetSeed = packetSeed.Clone(); - packetSeed.Sentient = false; // remove Sentient to avoid ghost role spam - } // will put it in the trays hands if it has any, please do not try doing this _botany.SpawnSeedPacket(packetSeed, Transform(uid).Coordinates, uid); RemovePlant(uid, component); @@ -678,14 +663,6 @@ public void Update(EntityUid uid, PlantHolderComponent? component = null) CheckLevelSanity(uid, component); - if (component.Seed.Sentient) - { - var ghostRole = EnsureComp(uid); - EnsureComp(uid); - ghostRole.RoleName = MetaData(uid).EntityName; - ghostRole.RoleDescription = Loc.GetString("station-event-random-sentience-role-description", ("name", ghostRole.RoleName)); - } - if (component.UpdateSpriteAfterUpdate) UpdateSprite(uid, component); } @@ -903,7 +880,7 @@ private void Mutate(EntityUid uid, float severity, PlantHolderComponent? compone if (component.Seed != null) { EnsureUniqueSeed(uid, component); - _mutation.MutateSeed(ref component.Seed, severity); + _mutation.MutateSeed(uid, ref component.Seed, severity); } } @@ -914,19 +891,6 @@ public void UpdateSprite(EntityUid uid, PlantHolderComponent? component = null) component.UpdateSpriteAfterUpdate = false; - if (component.Seed != null && component.Seed.Bioluminescent) - { - var light = EnsureComp(uid); - _pointLight.SetRadius(uid, component.Seed.BioluminescentRadius, light); - _pointLight.SetColor(uid, component.Seed.BioluminescentColor, light); - _pointLight.SetCastShadows(uid, false, light); - Dirty(uid, light); - } - else - { - RemComp(uid); - } - if (!TryComp(uid, out var app)) return; diff --git a/Content.Server/Botany/Systems/SeedExtractorSystem.cs b/Content.Server/Botany/Systems/SeedExtractorSystem.cs index 4a0d56bfe98133..93f76473ff886a 100644 --- a/Content.Server/Botany/Systems/SeedExtractorSystem.cs +++ b/Content.Server/Botany/Systems/SeedExtractorSystem.cs @@ -43,12 +43,6 @@ private void OnInteractUsing(EntityUid uid, SeedExtractorComponent seedExtractor var coords = Transform(uid).Coordinates; var packetSeed = seed; - if (packetSeed.Sentient) - { - if (!packetSeed.Unique) // clone if necessary before modifying the seed - packetSeed = packetSeed.Clone(); - packetSeed.Sentient = false; // remove Sentient to avoid ghost role spam - } if (amount > 1) packetSeed.Unique = false; diff --git a/Content.Server/EntityEffects/Effects/Glow.cs b/Content.Server/EntityEffects/Effects/Glow.cs new file mode 100644 index 00000000000000..b679590decaf1f --- /dev/null +++ b/Content.Server/EntityEffects/Effects/Glow.cs @@ -0,0 +1,46 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Database; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Makes a mob glow. +/// +public sealed partial class Glow : EntityEffect +{ + public float Radius = 2f; + public Color Color = Color.Black; + + static List colors = new List{ + Color.White, + Color.Red, + Color.Yellow, + Color.Green, + Color.Blue, + Color.Purple, + Color.Pink + }; + + public override void Effect(EntityEffectBaseArgs args) + { + if (Color == Color.Black) + { + var random = IoCManager.Resolve(); //works + Color = random.Pick(colors); + } + + var _light = args.EntityManager.System(); + var light = _light.EnsureLight(args.TargetEntity); + _light.SetRadius(args.TargetEntity, Radius, light); + _light.SetColor(args.TargetEntity, Color, light); + _light.SetCastShadows(args.TargetEntity, false, light); // this is expensive, and botanists make lots of plants + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + throw new NotImplementedException(); + } +} diff --git a/Content.Server/EntityEffects/Effects/Slipify.cs b/Content.Server/EntityEffects/Effects/Slipify.cs new file mode 100644 index 00000000000000..242e6bbf214930 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/Slipify.cs @@ -0,0 +1,41 @@ +using Content.Server.Atmos.EntitySystems; +using Content.Shared.Database; +using Content.Shared.EntityEffects; +using Content.Shared.Physics; +using Content.Shared.Slippery; +using Content.Shared.StepTrigger.Components; +using Robust.Shared.Physics; +using Robust.Shared.Physics.Components; +using Robust.Shared.Physics.Systems; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Makes a mob slippery. +/// +public sealed partial class Slipify : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var _fixtureSystem = args.EntityManager.System(); + var _colWakeSystem = args.EntityManager.System(); + var slippery = args.EntityManager.EnsureComponent(args.TargetEntity); + args.EntityManager.Dirty(args.TargetEntity, slippery); + args.EntityManager.EnsureComponent(args.TargetEntity); + // Need a fixture with a slip layer in order to actually do the slipping + var fixtures = args.EntityManager.EnsureComponent(args.TargetEntity); + var body = args.EntityManager.EnsureComponent(args.TargetEntity); + var shape = fixtures.Fixtures["fix1"].Shape; + _fixtureSystem.TryCreateFixture(args.TargetEntity, shape, "slips", 1, false, (int)CollisionGroup.SlipLayer, manager: fixtures, body: body); + // Need to disable collision wake so that mobs can collide with and slip on it + var collisionWake = args.EntityManager.EnsureComponent(args.TargetEntity); + _colWakeSystem.SetEnabled(args.TargetEntity, false, collisionWake); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + throw new NotImplementedException(); + } +} diff --git a/Content.Shared/Random/RandomPlantMutation.cs b/Content.Shared/Random/RandomPlantMutation.cs new file mode 100644 index 00000000000000..9be6d9fe42cf0f --- /dev/null +++ b/Content.Shared/Random/RandomPlantMutation.cs @@ -0,0 +1,39 @@ +using Content.Shared.Chemistry.Reagent; +using Content.Shared.EntityEffects; +using Content.Shared.FixedPoint; +using Robust.Shared.Serialization; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; +using System.Text.Json.Serialization; + +namespace Content.Shared.Random; + +/// +/// Data that specifies reagents that share the same weight and quantity for use with WeightedRandomSolution. +/// +[Serializable, NetSerializable] +[DataDefinition] +public sealed partial class RandomPlantMutation +{ + /// + /// Odds of this mutation occurring with 1 point of mutation severity on a plant. + /// + [DataField("baseOdds")] + public float BaseOdds = 0; + + /// + /// The name of this mutation. + /// + [DataField("name")] + public string Name = ""; + + /// + /// The actual EntityEffect to apply to the target + /// + [JsonPropertyName("mutation")] + [DataField("mutation")] + public EntityEffect Mutation = default!; + + [DataField("appliesToProduce")] + public bool AppliesToProduce = true; +} diff --git a/Content.Shared/Random/RandomPlantMutationListPrototype.cs b/Content.Shared/Random/RandomPlantMutationListPrototype.cs new file mode 100644 index 00000000000000..ab28594a04b1d3 --- /dev/null +++ b/Content.Shared/Random/RandomPlantMutationListPrototype.cs @@ -0,0 +1,18 @@ +using Robust.Shared.Prototypes; + +namespace Content.Shared.Random; + +/// +/// Random weighting dataset for solutions, able to specify reagents quantity. +/// +[Prototype("RandomPlantMutationList")] +public sealed partial class RandomPlantMutationListPrototype : IPrototype +{ + [IdDataField] public string ID { get; } = default!; + + /// + /// List of RandomFills that can be picked from. + /// + [DataField("mutations", required: true)] + public List mutations = new(); +} diff --git a/Resources/Prototypes/Hydroponics/mutations.yml b/Resources/Prototypes/Hydroponics/randomChemicals.yml similarity index 100% rename from Resources/Prototypes/Hydroponics/mutations.yml rename to Resources/Prototypes/Hydroponics/randomChemicals.yml diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml new file mode 100644 index 00000000000000..a72e1c94c34faf --- /dev/null +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -0,0 +1,12 @@ +- type: RandomPlantMutationList + id: RandomPlantMutations + mutations: + - name: Bioluminescent + baseOdds: 0.0072 + mutation: !type:Glow # new effect + - name: Sentient + baseOdds: 0.0072 + mutation: !type:MakeSentient #existing effect. + - name: Slippery + baseOdds: 0.0072 + mutation: !type:Slipify \ No newline at end of file From 64fb0857dded436bf030803c17a2db4df69ebebc Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sat, 17 Aug 2024 15:55:53 -0400 Subject: [PATCH 02/19] Sentient shouldn't apply to the botany tray. --- Content.Server/Botany/Systems/MutationSystem.cs | 7 +++++-- Content.Shared/Random/RandomPlantMutation.cs | 15 ++++++++++++--- .../Prototypes/Hydroponics/randomMutations.yml | 1 + 3 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 88eece97110b3c..acd72bf20ffb37 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -33,8 +33,11 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float { if (Random(mutation.BaseOdds * severity)) { - EntityEffectBaseArgs args = new EntityEffectBaseArgs(plantHolder, EntityManager); - mutation.Mutation.Effect(args); + if (mutation.AppliesToPlant) + { + EntityEffectBaseArgs args = new EntityEffectBaseArgs(plantHolder, EntityManager); + mutation.Mutation.Effect(args); + } seed.Mutations.Add(mutation); } } diff --git a/Content.Shared/Random/RandomPlantMutation.cs b/Content.Shared/Random/RandomPlantMutation.cs index 9be6d9fe42cf0f..ebace1deb04b72 100644 --- a/Content.Shared/Random/RandomPlantMutation.cs +++ b/Content.Shared/Random/RandomPlantMutation.cs @@ -9,7 +9,7 @@ namespace Content.Shared.Random; /// -/// Data that specifies reagents that share the same weight and quantity for use with WeightedRandomSolution. +/// Data that specifies the odds and effects of possible random plant mutations. /// [Serializable, NetSerializable] [DataDefinition] @@ -30,10 +30,19 @@ public sealed partial class RandomPlantMutation /// /// The actual EntityEffect to apply to the target /// - [JsonPropertyName("mutation")] + //[JsonPropertyName("mutation")] [DataField("mutation")] - public EntityEffect Mutation = default!; + public EntityEffect Mutation = default!; //TODO: rename to Effect or something. + /// + /// This mutation will target the harvested produce + /// [DataField("appliesToProduce")] public bool AppliesToProduce = true; + + /// + /// This mutation will target the growing plant as soon as this mutation is applied. + /// + [DataField("appliesToPlant")] + public bool AppliesToPlant = true; } diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index a72e1c94c34faf..4a7a66fa3b30a0 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -6,6 +6,7 @@ mutation: !type:Glow # new effect - name: Sentient baseOdds: 0.0072 + appliesToPlant: false #current makes the botany tray sentient. mutation: !type:MakeSentient #existing effect. - name: Slippery baseOdds: 0.0072 From 112155ec2b77e68c57ce2b1139251c20e967a20e Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 01:13:43 -0400 Subject: [PATCH 03/19] Add speciesChange and Unviable mutations --- .../Botany/Systems/MutationSystem.cs | 19 ++++---- Content.Server/EntityEffects/Effects/Glow.cs | 11 ++--- .../Effects/PlantSpeciesChange.cs | 44 +++++++++++++++++++ .../EntityEffects/Effects/PlantUnviable.cs | 27 ++++++++++++ .../Hydroponics/randomMutations.yml | 11 ++++- 5 files changed, 97 insertions(+), 15 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantUnviable.cs diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index acd72bf20ffb37..66e41a67333ec2 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -13,8 +13,18 @@ public sealed class MutationSystem : EntitySystem [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private WeightedRandomFillSolutionPrototype _randomChems = default!; - private RandomPlantMutationListPrototype _randomMutations = default!; + private RandomPlantMutationListPrototype _randomMutations = default!; + //Additonal TODO: + //clean up errors on client side about missing concrete Glow class? + + //Remaining mutations to port: + //all tolerance adjustments (11) + //stat adjustments (6) + //remaining fun (4) + //harvest type and autoharvest (2) + //gases (2, eat/make) + //chems (1) public override void Initialize() { @@ -88,9 +98,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) MutateFloat(ref seed.Production , 1f , 10f , 5, totalbits, 2 * severity); MutateFloat(ref seed.Potency , 30f , 100f, 5, totalbits, 2 * severity); - // Kill the plant (30) - MutateBool(ref seed.Viable , false, 30, totalbits, severity); - // Fun (72) MutateBool(ref seed.Seedless , true , 10, totalbits, severity); MutateBool(ref seed.Ligneous , true , 10, totalbits, severity); @@ -107,9 +114,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) // Chems (20) MutateChemicals(ref seed.Chemicals, 20, totalbits, severity); - - // Species (10) - MutateSpecies(ref seed, 10, totalbits, severity); } public SeedData Cross(SeedData a, SeedData b) @@ -138,7 +142,6 @@ public SeedData Cross(SeedData a, SeedData b) CrossFloat(ref result.Potency, a.Potency); CrossBool(ref result.Seedless, a.Seedless); - CrossBool(ref result.Viable, a.Viable); CrossBool(ref result.Ligneous, a.Ligneous); CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); CrossBool(ref result.CanScream, a.CanScream); diff --git a/Content.Server/EntityEffects/Effects/Glow.cs b/Content.Server/EntityEffects/Effects/Glow.cs index b679590decaf1f..842d12348fa920 100644 --- a/Content.Server/EntityEffects/Effects/Glow.cs +++ b/Content.Server/EntityEffects/Effects/Glow.cs @@ -1,5 +1,3 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Database; using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -7,11 +5,14 @@ namespace Content.Server.EntityEffects.Effects; /// -/// Makes a mob glow. +/// Makes a mob glow. /// public sealed partial class Glow : EntityEffect { + [DataField] public float Radius = 2f; + + [DataField] public Color Color = Color.Black; static List colors = new List{ @@ -28,7 +29,7 @@ public override void Effect(EntityEffectBaseArgs args) { if (Color == Color.Black) { - var random = IoCManager.Resolve(); //works + var random = IoCManager.Resolve(); Color = random.Pick(colors); } @@ -41,6 +42,6 @@ public override void Effect(EntityEffectBaseArgs args) protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) { - throw new NotImplementedException(); + return "TODO"; } } diff --git a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs new file mode 100644 index 00000000000000..4fecdbcbcaceac --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs @@ -0,0 +1,44 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using Serilog; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Changes a plant into one of the species its able to mutate into. +/// +public sealed partial class PlantSpeciesChange : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var prototypeManager = IoCManager.Resolve(); + //TODO: get plant seed, then species + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + if (plantholder.Seed.MutationPrototypes.Count == 0) + return; + + var random = IoCManager.Resolve(); + var targetProto = random.Pick(plantholder.Seed.MutationPrototypes); + prototypeManager.TryIndex(targetProto, out SeedPrototype? protoSeed); + + if (protoSeed == null) + { + Log.Error($"Seed prototype could not be found: {targetProto}!"); + return; + } + + plantholder.Seed = plantholder.Seed.SpeciesChange(protoSeed); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantUnviable.cs b/Content.Server/EntityEffects/Effects/PlantUnviable.cs new file mode 100644 index 00000000000000..4a1fe00e9f17cd --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantUnviable.cs @@ -0,0 +1,27 @@ +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Makes a mob glow. +/// +public sealed partial class PlantUnviable : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.Viable = false; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 4a7a66fa3b30a0..d41abc8064358f 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -6,8 +6,15 @@ mutation: !type:Glow # new effect - name: Sentient baseOdds: 0.0072 - appliesToPlant: false #current makes the botany tray sentient. + appliesToPlant: false #makes the botany tray sentient right now. mutation: !type:MakeSentient #existing effect. - name: Slippery baseOdds: 0.0072 - mutation: !type:Slipify \ No newline at end of file + mutation: !type:Slipify + - name: ChangeSpecies + baseOdds: 0.0072 + appliesToProduce: false + mutation: !type:PlantSpeciesChange + - name: Unviable + baseOdds: 0.00012 + mutation: !type:PlantUnviable \ No newline at end of file From 268abb7f9d21e90741569ae12a805be959dc7ed4 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 14:20:13 -0400 Subject: [PATCH 04/19] Add tolerance mutation effects --- Content.Server/Botany/SeedPrototype.cs | 8 +- .../Botany/Systems/MutationSystem.cs | 46 +-- .../Effects/PlantStatAdjustments.cs | 316 ++++++++++++++++++ Content.Shared/Random/RandomPlantMutation.cs | 8 +- .../Hydroponics/randomMutations.yml | 48 ++- 5 files changed, 382 insertions(+), 44 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 4cb770228cf58b..2baeaf4a55707f 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -229,10 +229,14 @@ public partial class SeedData [DataField("turnIntoKudzu")] public bool TurnIntoKudzu; [DataField("splatPrototype")] public string? SplatPrototype { get; set; } - public List Mutations { get; set; } = new(); - #endregion + /// + /// The mutation effects that have been applied to this plant. + /// + [DataField("mutations")] //TODO confirm this is sufficient. + public List Mutations { get; set; } = new(); + /// /// The seed prototypes this seed may mutate into when prompted to. /// diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 66e41a67333ec2..e48b4205c2745f 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -19,9 +19,10 @@ public sealed class MutationSystem : EntitySystem //clean up errors on client side about missing concrete Glow class? //Remaining mutations to port: - //all tolerance adjustments (11) //stat adjustments (6) //remaining fun (4) + // - Seedless, Ligneous, turnintokudzu are plant traits rather than effects and their value should stay in SeedData for now + // - Screaming will need updated with new screams from more recent commit. //harvest type and autoharvest (2) //gases (2, eat/make) //chems (1) @@ -48,7 +49,8 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float EntityEffectBaseArgs args = new EntityEffectBaseArgs(plantHolder, EntityManager); mutation.Mutation.Effect(args); } - seed.Mutations.Add(mutation); + if (mutation.Persists) //Stat adjustments do not persist by being an attached effect, they just change the stat. + seed.Mutations.Add(mutation); } } } @@ -77,19 +79,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) const int totalbits = 262; #pragma warning disable IDE0055 // disable formatting warnings because this looks more readable - // Tolerances (55) - MutateFloat(ref seed.NutrientConsumption , 0.05f, 1.2f, 5, totalbits, severity); - MutateFloat(ref seed.WaterConsumption , 3f , 9f , 5, totalbits, severity); - MutateFloat(ref seed.IdealHeat , 263f , 323f, 5, totalbits, severity); - MutateFloat(ref seed.HeatTolerance , 2f , 25f , 5, totalbits, severity); - MutateFloat(ref seed.IdealLight , 0f , 14f , 5, totalbits, severity); - MutateFloat(ref seed.LightTolerance , 1f , 5f , 5, totalbits, severity); - MutateFloat(ref seed.ToxinsTolerance , 1f , 10f , 5, totalbits, severity); - MutateFloat(ref seed.LowPressureTolerance , 60f , 100f, 5, totalbits, severity); - MutateFloat(ref seed.HighPressureTolerance, 100f , 140f, 5, totalbits, severity); - MutateFloat(ref seed.PestTolerance , 0f , 15f , 5, totalbits, severity); - MutateFloat(ref seed.WeedTolerance , 0f , 15f , 5, totalbits, severity); - // Stats (30*2 = 60) MutateFloat(ref seed.Endurance , 50f , 150f, 5, totalbits, 2 * severity); MutateInt(ref seed.Yield , 3 , 10 , 5, totalbits, 2 * severity); @@ -141,9 +130,9 @@ public SeedData Cross(SeedData a, SeedData b) CrossFloat(ref result.Production, a.Production); CrossFloat(ref result.Potency, a.Potency); - CrossBool(ref result.Seedless, a.Seedless); - CrossBool(ref result.Ligneous, a.Ligneous); - CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); + CrossBool(ref result.Seedless, a.Seedless); + CrossBool(ref result.Ligneous, a.Ligneous); + CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); CrossBool(ref result.CanScream, a.CanScream); CrossGasses(ref result.ExudeGasses, a.ExudeGasses); @@ -302,27 +291,6 @@ private void MutateChemicals(ref Dictionary chemicals, } } - private void MutateSpecies(ref SeedData seed, int bits, int totalbits, float mult) - { - float p = mult * bits / totalbits; - p = Math.Clamp(p, 0, 1); - if (!Random(p)) - return; - - if (seed.MutationPrototypes.Count == 0) - return; - - var targetProto = _robustRandom.Pick(seed.MutationPrototypes); - _prototypeManager.TryIndex(targetProto, out SeedPrototype? protoSeed); - - if (protoSeed == null) - { - Log.Error($"Seed prototype could not be found: {targetProto}!"); - return; - } - - seed = seed.SpeciesChange(protoSeed); - } private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs new file mode 100644 index 00000000000000..43f5283a41d407 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs @@ -0,0 +1,316 @@ +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; + +namespace Content.Server.EntityEffects.Effects; + + +/// +/// Changes the value on a plant's WaterConsumption value randomly when applied. +/// +public sealed partial class PlantMutateWaterConsumption : EntityEffect +{ + [DataField] + public float minValue = 0.3f; + [DataField] + public float maxValue = 0.9f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.WaterConsumption = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's NutrientConsumption value randomly when applied. +/// +public sealed partial class PlantMutateNutrientConsumption : EntityEffect +{ + [DataField] + public float minValue = 0.05f; + [DataField] + public float maxValue = 1.2f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.NutrientConsumption = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's IdealHeat value randomly when applied. +/// +public sealed partial class PlantMutateIdealHeat : EntityEffect +{ + [DataField] + public float minValue = 263f; + [DataField] + public float maxValue = 323f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.IdealHeat = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's HeatTolerance value randomly when applied. +/// +public sealed partial class PlantMutateHeatTolerance : EntityEffect +{ + [DataField] + public float minValue = 2f; + [DataField] + public float maxValue = 25f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.HeatTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's IdealLight value randomly when applied. +/// +public sealed partial class PlantMutateIdealLight : EntityEffect +{ + [DataField] + public float minValue = 0f; + [DataField] + public float maxValue = 14f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.IdealLight = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's LightTolerance value randomly when applied. +/// +public sealed partial class PlantMutateLightTolerance : EntityEffect +{ + [DataField] + public float minValue = 1f; + [DataField] + public float maxValue = 5f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.LightTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's ToxinsTolerance value randomly when applied. +/// +public sealed partial class PlantMutateToxinsTolerance : EntityEffect +{ + [DataField] + public float minValue = 1f; + [DataField] + public float maxValue = 10f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.ToxinsTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's LowPressureTolerance value randomly when applied. +/// +public sealed partial class PlantMutateLowPressureTolerance : EntityEffect +{ + [DataField] + public float minValue = 60f; + [DataField] + public float maxValue = 100f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.LowPressureTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's HighPressureTolerance value randomly when applied. +/// +public sealed partial class PlantMutateHighPressureTolerance : EntityEffect +{ + [DataField] + public float minValue = 100f; + [DataField] + public float maxValue = 140f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.HighPressureTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's PestTolerance value randomly when applied. +/// +public sealed partial class PlantMutatePestTolerance : EntityEffect +{ + [DataField] + public float minValue = 0f; + [DataField] + public float maxValue = 15f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.PestTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's WeedTolerance value randomly when applied. +/// +public sealed partial class PlantMutateWeedTolerance : EntityEffect +{ + [DataField] + public float minValue = 0f; + [DataField] + public float maxValue = 15f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.WeedTolerance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + diff --git a/Content.Shared/Random/RandomPlantMutation.cs b/Content.Shared/Random/RandomPlantMutation.cs index ebace1deb04b72..3f5309c9a14bae 100644 --- a/Content.Shared/Random/RandomPlantMutation.cs +++ b/Content.Shared/Random/RandomPlantMutation.cs @@ -32,7 +32,7 @@ public sealed partial class RandomPlantMutation /// //[JsonPropertyName("mutation")] [DataField("mutation")] - public EntityEffect Mutation = default!; //TODO: rename to Effect or something. + public EntityEffect Mutation = default!; //TODO: rename to Effect or something? /// /// This mutation will target the harvested produce @@ -45,4 +45,10 @@ public sealed partial class RandomPlantMutation /// [DataField("appliesToPlant")] public bool AppliesToPlant = true; + + /// + /// This mutation stays on the plant and its produce. If false while AppliesToPlant is true, the effect will run when triggered. + /// + [DataField("persists")] + public bool Persists = true; } diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index d41abc8064358f..458350c78aca86 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -6,7 +6,7 @@ mutation: !type:Glow # new effect - name: Sentient baseOdds: 0.0072 - appliesToPlant: false #makes the botany tray sentient right now. + appliesToPlant: false #makes the botany tray sentient if true mutation: !type:MakeSentient #existing effect. - name: Slippery baseOdds: 0.0072 @@ -17,4 +17,48 @@ mutation: !type:PlantSpeciesChange - name: Unviable baseOdds: 0.00012 - mutation: !type:PlantUnviable \ No newline at end of file + mutation: !type:PlantUnviable + - name: ChangeWaterConsumption + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateWaterConsumption + - name: ChangeNutrientConsumption + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateNutrientConsumption + - name: ChangeIdealHeat + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateIdealHeat + - name: ChangeHeatTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateHeatTolerance + - name: ChangeIdealLight + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateIdealLight + - name: ChangeLightTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateLightTolerance + - name: ChangeToxinsTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateToxinsTolerance + - name: ChangeLowPressureTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateLowPressureTolerance + - name: ChangeHighPressureTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateHighPressureTolerance + - name: ChangePestTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutatePestTolerance + - name: ChangeWeedTolerance + baseOdds: 0.018 + persists: false + mutation: !type:PlantMutateWeedTolerance \ No newline at end of file From d84b3c63803c8c1d735b1a6559a3f79833155c76 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 14:36:06 -0400 Subject: [PATCH 05/19] add stat mutation effects --- .../Botany/Systems/MutationSystem.cs | 74 -------- .../Effects/PlantStatAdjustments.cs | 164 ++++++++++++++++++ .../Hydroponics/randomMutations.yml | 26 ++- 3 files changed, 189 insertions(+), 75 deletions(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index e48b4205c2745f..30b0406e8ffedd 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -19,7 +19,6 @@ public sealed class MutationSystem : EntitySystem //clean up errors on client side about missing concrete Glow class? //Remaining mutations to port: - //stat adjustments (6) //remaining fun (4) // - Seedless, Ligneous, turnintokudzu are plant traits rather than effects and their value should stay in SeedData for now // - Screaming will need updated with new screams from more recent commit. @@ -79,14 +78,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) const int totalbits = 262; #pragma warning disable IDE0055 // disable formatting warnings because this looks more readable - // Stats (30*2 = 60) - MutateFloat(ref seed.Endurance , 50f , 150f, 5, totalbits, 2 * severity); - MutateInt(ref seed.Yield , 3 , 10 , 5, totalbits, 2 * severity); - MutateFloat(ref seed.Lifespan , 10f , 80f , 5, totalbits, 2 * severity); - MutateFloat(ref seed.Maturation , 3f , 8f , 5, totalbits, 2 * severity); - MutateFloat(ref seed.Production , 1f , 10f , 5, totalbits, 2 * severity); - MutateFloat(ref seed.Potency , 30f , 100f, 5, totalbits, 2 * severity); - // Fun (72) MutateBool(ref seed.Seedless , true , 10, totalbits, severity); MutateBool(ref seed.Ligneous , true , 10, totalbits, severity); @@ -150,71 +141,6 @@ public SeedData Cross(SeedData a, SeedData b) return result; } - // Mutate reference 'val' between 'min' and 'max' by pretending the value - // is representable by a thermometer code with 'bits' number of bits and - // randomly flipping some of them. - // - // 'totalbits' and 'mult' are used only to calculate the probability that - // one bit gets flipped. - private void MutateFloat(ref float val, float min, float max, int bits, int totalbits, float mult) - { - // Probability that a bit flip happens for this value's representation in thermometer code. - float probBitflip = mult * bits / totalbits; - probBitflip = Math.Clamp(probBitflip, 0, 1); - if (!Random(probBitflip)) - return; - - // Starting number of bits that are high, between 0 and bits. - // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. - int valInt = (int)MathF.Round((val - min) / (max - min) * bits); - // val may be outside the range of min/max due to starting prototype values, so clamp. - valInt = Math.Clamp(valInt, 0, bits); - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)valInt / bits; - int valIntMutated; - if (Random(probIncrease)) - { - valIntMutated = valInt + 1; - } - else - { - valIntMutated = valInt - 1; - } - - // Set value based on mutated thermometer code. - float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); - val = valMutated; - } - - private void MutateInt(ref int val, int min, int max, int bits, int totalbits, float mult) - { - // Probability that a bit flip happens for this value's representation in thermometer code. - float probBitflip = mult * bits / totalbits; - probBitflip = Math.Clamp(probBitflip, 0, 1); - if (!Random(probBitflip)) - return; - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)val / bits; - int valMutated; - if (Random(probIncrease)) - { - valMutated = val + 1; - } - else - { - valMutated = val - 1; - } - - valMutated = Math.Clamp(valMutated, min, max); - val = valMutated; - } - private void MutateBool(ref bool val, bool polarity, int bits, int totalbits, float mult) { // Probability that a bit flip happens for this value. diff --git a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs index 43f5283a41d407..7a20ca227c9524 100644 --- a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs +++ b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs @@ -314,3 +314,167 @@ public override void Effect(EntityEffectBaseArgs args) } } +/// +/// Changes the value on a plant's Endurance value randomly when applied. +/// +public sealed partial class PlantMutateEndurance : EntityEffect +{ + [DataField] + public float minValue = 50f; + [DataField] + public float maxValue = 150f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Endurance = random.NextFloat(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's Yield value randomly when applied. +/// +public sealed partial class PlantMutateYield : EntityEffect +{ + [DataField] + public int minValue = 3; + [DataField] + public int maxValue = 10; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Yield = random.Next(minValue, maxValue); + + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's Lifespan value randomly when applied. +/// +public sealed partial class PlantMutateLifespan : EntityEffect +{ + [DataField] + public float minValue = 10f; + [DataField] + public float maxValue = 80f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Lifespan = random.NextFloat(minValue, maxValue); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's Maturation value randomly when applied. +/// +public sealed partial class PlantMutateMaturation : EntityEffect +{ + [DataField] + public float minValue = 3f; + [DataField] + public float maxValue = 8f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Maturation = random.NextFloat(minValue, maxValue); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's Production value randomly when applied. +/// +public sealed partial class PlantMutateProduction : EntityEffect +{ + [DataField] + public float minValue = 1f; + [DataField] + public float maxValue = 10f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Production = random.NextFloat(minValue, maxValue); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes the value on a plant's Potency value randomly when applied. +/// +public sealed partial class PlantMutatePotency : EntityEffect +{ + [DataField] + public float minValue = 30f; + [DataField] + public float maxValue = 100f; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + plantholder.Seed.Potency = random.NextFloat(minValue, maxValue); + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 458350c78aca86..728c2f03d28961 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -61,4 +61,28 @@ - name: ChangeWeedTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateWeedTolerance \ No newline at end of file + mutation: !type:PlantMutateWeedTolerance + - name: ChangeEndurance + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutateEndurance + - name: ChangeYield + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutateYield + - name: ChangeLifespan + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutateLifespan + - name: ChangeMaturation + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutateMaturation + - name: ChangeProduction + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutateProduction + - name: ChangePotency + baseOdds: 0.036 + persists: false + mutation: !type:PlantMutatePotency \ No newline at end of file From c7768673ae3aa8c3367c52b12a46c0013fbcba98 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 14:50:22 -0400 Subject: [PATCH 06/19] Add the last 4 boolean mutations. --- .../Botany/Systems/MutationSystem.cs | 10 --- .../Effects/PlantStatAdjustments.cs | 83 +++++++++++++++++++ .../Hydroponics/randomMutations.yml | 18 +++- 3 files changed, 100 insertions(+), 11 deletions(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 30b0406e8ffedd..40601cd1fc6b86 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -19,9 +19,6 @@ public sealed class MutationSystem : EntitySystem //clean up errors on client side about missing concrete Glow class? //Remaining mutations to port: - //remaining fun (4) - // - Seedless, Ligneous, turnintokudzu are plant traits rather than effects and their value should stay in SeedData for now - // - Screaming will need updated with new screams from more recent commit. //harvest type and autoharvest (2) //gases (2, eat/make) //chems (1) @@ -77,13 +74,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) // Add up everything in the bits column and put the number here. const int totalbits = 262; - #pragma warning disable IDE0055 // disable formatting warnings because this looks more readable - // Fun (72) - MutateBool(ref seed.Seedless , true , 10, totalbits, severity); - MutateBool(ref seed.Ligneous , true , 10, totalbits, severity); - MutateBool(ref seed.TurnIntoKudzu , true , 10, totalbits, severity); - MutateBool(ref seed.CanScream , true , 10, totalbits, severity); - #pragma warning restore IDE0055 // ConstantUpgade (10) MutateHarvestType(ref seed.HarvestRepeat, 10, totalbits, severity); diff --git a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs index 7a20ca227c9524..12c7c0b9896129 100644 --- a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs +++ b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs @@ -478,3 +478,86 @@ public override void Effect(EntityEffectBaseArgs args) } } +/// +/// Changes if the plant has seeds or not. +/// +public sealed partial class PlantMutateSeedless : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.Seedless = !plantholder.Seed.Seedless; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes if the plant requires a hatchet to harvest. +/// +public sealed partial class PlantMutateLigneous : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.Ligneous = !plantholder.Seed.Ligneous; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes if the plant will turn into kudzu once weed levels are high +/// +public sealed partial class PlantMutateKudzu : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.TurnIntoKudzu = !plantholder.Seed.TurnIntoKudzu; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// Changes if the plant and its produce scream. +/// +public sealed partial class PlantMutateScream : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.CanScream = !plantholder.Seed.CanScream; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 728c2f03d28961..57161d457504c4 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -85,4 +85,20 @@ - name: ChangePotency baseOdds: 0.036 persists: false - mutation: !type:PlantMutatePotency \ No newline at end of file + mutation: !type:PlantMutatePotency + - name: ChangeSeedless + baseOdds: 0.00036 + persists: false + mutation: !type:PlantMutateSeedless + - name: ChangeLigneous + baseOdds: 0.00036 + persists: false + mutation: !type:PlantMutateLigneous + - name: ChangeTurnIntoKudzu + baseOdds: 0.00036 + persists: false + mutation: !type:PlantMutateKudzu + - name: ChangeScreaming + baseOdds: 0.00036 + persists: false + mutation: !type:PlantMutateScream \ No newline at end of file From f64fa4930c293c9e999c89c23ed1eaa135b6ecff Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 15:12:09 -0400 Subject: [PATCH 07/19] move chemical mutation to effect. --- .../Botany/Systems/MutationSystem.cs | 34 ----------- .../Effects/PlantMutateChemicals.cs | 57 +++++++++++++++++++ .../Hydroponics/randomMutations.yml | 6 +- 3 files changed, 62 insertions(+), 35 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 40601cd1fc6b86..2798be846c1d7d 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -81,9 +81,6 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) // Gas (5) MutateGasses(ref seed.ExudeGasses, 0.01f, 0.5f, 4, totalbits, severity); MutateGasses(ref seed.ConsumeGasses, 0.01f, 0.5f, 1, totalbits, severity); - - // Chems (20) - MutateChemicals(ref seed.Chemicals, 20, totalbits, severity); } public SeedData Cross(SeedData a, SeedData b) @@ -176,37 +173,6 @@ private void MutateGasses(ref Dictionary gasses, float min, float ma } } - private void MutateChemicals(ref Dictionary chemicals, int bits, int totalbits, float mult) - { - float probModify = mult * bits / totalbits; - probModify = Math.Clamp(probModify, 0, 1); - if (!Random(probModify)) - return; - - // Add a random amount of a random chemical to this set of chemicals - if (_randomChems != null) - { - var pick = _randomChems.Pick(_robustRandom); - string chemicalId = pick.reagent; - int amount = _robustRandom.Next(1, (int)pick.quantity); - SeedChemQuantity seedChemQuantity = new SeedChemQuantity(); - if (chemicals.ContainsKey(chemicalId)) - { - seedChemQuantity.Min = chemicals[chemicalId].Min; - seedChemQuantity.Max = chemicals[chemicalId].Max + amount; - } - else - { - seedChemQuantity.Min = 1; - seedChemQuantity.Max = 1 + amount; - seedChemQuantity.Inherent = false; - } - int potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); - seedChemQuantity.PotencyDivisor = potencyDivisor; - chemicals[chemicalId] = seedChemQuantity; - } - } - private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs new file mode 100644 index 00000000000000..b5a199681666f7 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs @@ -0,0 +1,57 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Content.Shared.Random; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using System.Linq; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// changes the chemicals available in a plant's produce +/// +public sealed partial class PlantMutateChemicals : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + var prototypeManager = IoCManager.Resolve(); + var chemicals = plantholder.Seed.Chemicals; + var _randomChems = prototypeManager.Index("RandomPickBotanyReagent").Fills; + + + // Add a random amount of a random chemical to this set of chemicals + if (_randomChems != null) + { + var pick = random.Pick(_randomChems); + string chemicalId = random.Pick(pick.Reagents); + int amount = random.Next(1, (int)pick.Quantity); + SeedChemQuantity seedChemQuantity = new SeedChemQuantity(); + if (chemicals.ContainsKey(chemicalId)) + { + seedChemQuantity.Min = chemicals[chemicalId].Min; + seedChemQuantity.Max = chemicals[chemicalId].Max + amount; + } + else + { + seedChemQuantity.Min = 1; + seedChemQuantity.Max = 1 + amount; + seedChemQuantity.Inherent = false; + } + int potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); + seedChemQuantity.PotencyDivisor = potencyDivisor; + chemicals[chemicalId] = seedChemQuantity; + } + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 57161d457504c4..2f11027d85958c 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -101,4 +101,8 @@ - name: ChangeScreaming baseOdds: 0.00036 persists: false - mutation: !type:PlantMutateScream \ No newline at end of file + mutation: !type:PlantMutateScream + - name: ChangeChemicals + baseOdds: 0.00018 + persists: false + mutation: !type:PlantMutateChemicals \ No newline at end of file From ed775bf1c38b4fda3ba093b21e48bc525d59c786 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 15:50:04 -0400 Subject: [PATCH 08/19] move gas and harvest mutations to effects. All existing effects moved. --- .../Botany/Systems/MutationSystem.cs | 83 ++--------------- .../EntityEffects/Effects/PlantMutateGases.cs | 88 +++++++++++++++++++ .../Effects/PlantMutateHarvest.cs | 30 +++++++ .../Hydroponics/randomMutations.yml | 14 ++- 4 files changed, 138 insertions(+), 77 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateGases.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 2798be846c1d7d..32646bece781ae 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -1,10 +1,9 @@ +using Content.Shared.Atmos; +using Content.Shared.EntityEffects; +using Content.Shared.Random; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using Content.Shared.Random; -using Content.Shared.Random.Helpers; using System.Linq; -using Content.Shared.Atmos; -using Content.Shared.EntityEffects; namespace Content.Server.Botany; @@ -12,20 +11,15 @@ public sealed class MutationSystem : EntitySystem { [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly IPrototypeManager _prototypeManager = default!; - private WeightedRandomFillSolutionPrototype _randomChems = default!; private RandomPlantMutationListPrototype _randomMutations = default!; //Additonal TODO: //clean up errors on client side about missing concrete Glow class? - - //Remaining mutations to port: - //harvest type and autoharvest (2) - //gases (2, eat/make) - //chems (1) + //Investigate Ligneous pop-up message not appearing if the trait is acquired via mutation. + //clean up warnings in new code formatting. public override void Initialize() { - _randomChems = _prototypeManager.Index("RandomPickBotanyReagent"); _randomMutations = _prototypeManager.Index("RandomPlantMutations"); } @@ -52,14 +46,7 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float } /// - /// Main idea: Simulate genetic mutation using random binary flips. Each - /// seed attribute can be encoded with a variable number of bits, e.g. - /// NutrientConsumption is represented by 5 bits randomly distributed in the - /// plant's genome which thermometer code the floating value between 0.1 and - /// 5. 1 unit of mutation flips one bit in the plant's genome, which changes - /// NutrientConsumption if one of those 5 bits gets affected. - /// - /// You MUST clone() seed before mutating it! + /// Checks all defined mutations against a seed to see which of them are applied. /// public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) { @@ -69,18 +56,7 @@ public void MutateSeed(EntityUid plantHolder, ref SeedData seed, float severity) return; } - CheckRandomMutations(plantHolder, ref seed, severity); //TODO Will be the main call later, just check if this runs for now. - - // Add up everything in the bits column and put the number here. - const int totalbits = 262; - - - // ConstantUpgade (10) - MutateHarvestType(ref seed.HarvestRepeat, 10, totalbits, severity); - - // Gas (5) - MutateGasses(ref seed.ExudeGasses, 0.01f, 0.5f, 4, totalbits, severity); - MutateGasses(ref seed.ConsumeGasses, 0.01f, 0.5f, 1, totalbits, severity); + CheckRandomMutations(plantHolder, ref seed, severity); } public SeedData Cross(SeedData a, SeedData b) @@ -128,51 +104,6 @@ public SeedData Cross(SeedData a, SeedData b) return result; } - private void MutateBool(ref bool val, bool polarity, int bits, int totalbits, float mult) - { - // Probability that a bit flip happens for this value. - float probSet = mult * bits / totalbits; - probSet = Math.Clamp(probSet, 0, 1); - if (!Random(probSet)) - return; - - val = polarity; - } - - private void MutateHarvestType(ref HarvestType val, int bits, int totalbits, float mult) - { - float probModify = mult * bits / totalbits; - probModify = Math.Clamp(probModify, 0, 1); - - if (!Random(probModify)) - return; - - if (val == HarvestType.NoRepeat) - val = HarvestType.Repeat; - else if (val == HarvestType.Repeat) - val = HarvestType.SelfHarvest; - } - - private void MutateGasses(ref Dictionary gasses, float min, float max, int bits, int totalbits, float mult) - { - float probModify = mult * bits / totalbits; - probModify = Math.Clamp(probModify, 0, 1); - if (!Random(probModify)) - return; - - // Add a random amount of a random gas to this gas dictionary - float amount = _robustRandom.NextFloat(min, max); - Gas gas = _robustRandom.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); - if (gasses.ContainsKey(gas)) - { - gasses[gas] += amount; - } - else - { - gasses.Add(gas, amount); - } - } - private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs new file mode 100644 index 00000000000000..1c9e00e72b1bc7 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs @@ -0,0 +1,88 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Shared.Atmos; +using Content.Shared.EntityEffects; +using Content.Shared.Random; +using Robust.Shared.Prototypes; +using Robust.Shared.Random; +using System.Linq; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// changes the gases that a plant or produce create. +/// +public sealed partial class PlantMutateExudeGasses : EntityEffect +{ + [DataField] + public float minValue = 0.01f; + [DataField] + public float maxValue = 0.5f; + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + var prototypeManager = IoCManager.Resolve(); + var gasses = plantholder.Seed.ExudeGasses; + + // Add a random amount of a random gas to this gas dictionary + float amount = random.NextFloat(minValue, maxValue); + Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); + if (gasses.ContainsKey(gas)) + { + gasses[gas] += amount; + } + else + { + gasses.Add(gas, amount); + } + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} + +/// +/// changes the gases that a plant or produce consumes. +/// +public sealed partial class PlantMutateConsumeGasses : EntityEffect +{ + [DataField] + public float minValue = 0.01f; + [DataField] + public float maxValue = 0.5f; + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + var random = IoCManager.Resolve(); + var prototypeManager = IoCManager.Resolve(); + var gasses = plantholder.Seed.ConsumeGasses; + + // Add a random amount of a random gas to this gas dictionary + float amount = random.NextFloat(minValue, maxValue); + Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); + if (gasses.ContainsKey(gas)) + { + gasses[gas] += amount; + } + else + { + gasses.Add(gas, amount); + } + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs b/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs new file mode 100644 index 00000000000000..e67176ee16db5e --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateHarvest.cs @@ -0,0 +1,30 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Upgrades a plant's harvest type. +/// +public sealed partial class PlantMutateHarvest : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + if (plantholder.Seed.HarvestRepeat == HarvestType.NoRepeat) + plantholder.Seed.HarvestRepeat = HarvestType.Repeat; + else if (plantholder.Seed.HarvestRepeat == HarvestType.Repeat) + plantholder.Seed.HarvestRepeat = HarvestType.SelfHarvest; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 2f11027d85958c..29f83c0f4c0921 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -105,4 +105,16 @@ - name: ChangeChemicals baseOdds: 0.00018 persists: false - mutation: !type:PlantMutateChemicals \ No newline at end of file + mutation: !type:PlantMutateChemicals + - name: ChangeExudeGasses + baseOdds: 0.00091 + persists: false + mutation: !type:PlantMutateExudeGasses + - name: ChangeConsumeGasses + baseOdds: 0.0036 + persists: false + mutation: !type:PlantMutateConsumeGasses + - name: ChangeHarvest + baseOdds: 0.00036 + persists: false + mutation: !type:PlantMutateHarvest \ No newline at end of file From e46252e5be465e7ee33c5d18e49f73df56b92fc4 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 18 Aug 2024 19:07:35 -0400 Subject: [PATCH 09/19] cleanup IDE warning and messages in files I touched. --- .../Botany/Components/PlantHolderComponent.cs | 58 ++++----- .../Botany/Components/ProduceComponent.cs | 4 +- Content.Server/Botany/SeedPrototype.cs | 73 ++++++----- .../Botany/Systems/BotanySystem.Seed.cs | 6 - .../Botany/Systems/MutationSystem.cs | 12 +- .../Botany/Systems/PlantHolderSystem.cs | 13 +- Content.Server/EntityEffects/Effects/Glow.cs | 31 ++--- .../Effects/PlantMutateChemicals.cs | 15 ++- .../EntityEffects/Effects/PlantMutateGases.cs | 16 +-- .../Effects/PlantSpeciesChange.cs | 2 +- .../Effects/PlantStatAdjustments.cs | 116 ++++++++---------- .../EntityEffects/Effects/PlantUnviable.cs | 3 +- .../EntityEffects/Effects/Slipify.cs | 11 +- Content.Shared/Random/RandomPlantMutation.cs | 18 +-- 14 files changed, 169 insertions(+), 209 deletions(-) diff --git a/Content.Server/Botany/Components/PlantHolderComponent.cs b/Content.Server/Botany/Components/PlantHolderComponent.cs index 809af737ac666f..8218bead72cbae 100644 --- a/Content.Server/Botany/Components/PlantHolderComponent.cs +++ b/Content.Server/Botany/Components/PlantHolderComponent.cs @@ -6,90 +6,90 @@ namespace Content.Server.Botany.Components; [RegisterComponent] public sealed partial class PlantHolderComponent : Component { - [DataField("nextUpdate", customTypeSerializer: typeof(TimeOffsetSerializer))] + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan NextUpdate = TimeSpan.Zero; - [ViewVariables(VVAccess.ReadWrite), DataField("updateDelay")] + [DataField] public TimeSpan UpdateDelay = TimeSpan.FromSeconds(3); - [DataField("lastProduce")] + [DataField] public int LastProduce; - [ViewVariables(VVAccess.ReadWrite), DataField("missingGas")] + [DataField] public int MissingGas; - [DataField("cycleDelay")] + [DataField] public TimeSpan CycleDelay = TimeSpan.FromSeconds(15f); - [DataField("lastCycle", customTypeSerializer: typeof(TimeOffsetSerializer))] + [DataField(customTypeSerializer: typeof(TimeOffsetSerializer))] public TimeSpan LastCycle = TimeSpan.Zero; - [ViewVariables(VVAccess.ReadWrite), DataField("updateSpriteAfterUpdate")] + [DataField] public bool UpdateSpriteAfterUpdate; - [ViewVariables(VVAccess.ReadWrite), DataField("drawWarnings")] + [DataField] public bool DrawWarnings = false; - [ViewVariables(VVAccess.ReadWrite), DataField("waterLevel")] + [DataField] public float WaterLevel = 100f; - [ViewVariables(VVAccess.ReadWrite), DataField("nutritionLevel")] + [DataField] public float NutritionLevel = 100f; - [ViewVariables(VVAccess.ReadWrite), DataField("pestLevel")] + [DataField] public float PestLevel; - [ViewVariables(VVAccess.ReadWrite), DataField("weedLevel")] + [DataField] public float WeedLevel; - [ViewVariables(VVAccess.ReadWrite), DataField("toxins")] + [DataField] public float Toxins; - [ViewVariables(VVAccess.ReadWrite), DataField("age")] + [DataField] public int Age; - [ViewVariables(VVAccess.ReadWrite), DataField("skipAging")] + [DataField] public int SkipAging; - [ViewVariables(VVAccess.ReadWrite), DataField("dead")] + [DataField] public bool Dead; - [ViewVariables(VVAccess.ReadWrite), DataField("harvest")] + [DataField] public bool Harvest; - [ViewVariables(VVAccess.ReadWrite), DataField("sampled")] + [DataField] public bool Sampled; - [ViewVariables(VVAccess.ReadWrite), DataField("yieldMod")] + [DataField] public int YieldMod = 1; - [ViewVariables(VVAccess.ReadWrite), DataField("mutationMod")] + [DataField] public float MutationMod = 1f; - [ViewVariables(VVAccess.ReadWrite), DataField("mutationLevel")] + [DataField] public float MutationLevel; - [ViewVariables(VVAccess.ReadWrite), DataField("health")] + [DataField] public float Health; - [ViewVariables(VVAccess.ReadWrite), DataField("weedCoefficient")] + [DataField] public float WeedCoefficient = 1f; - [ViewVariables(VVAccess.ReadWrite), DataField("seed")] + [DataField] public SeedData? Seed; - [ViewVariables(VVAccess.ReadWrite), DataField("improperHeat")] + [DataField] public bool ImproperHeat; - [ViewVariables(VVAccess.ReadWrite), DataField("improperPressure")] + [DataField] public bool ImproperPressure; - [ViewVariables(VVAccess.ReadWrite), DataField("improperLight")] + [DataField] public bool ImproperLight; - [ViewVariables(VVAccess.ReadWrite), DataField("forceUpdate")] + [DataField] public bool ForceUpdate; - [ViewVariables(VVAccess.ReadWrite), DataField("solution")] + [DataField] public string SoilSolutionName = "soil"; [DataField] diff --git a/Content.Server/Botany/Components/ProduceComponent.cs b/Content.Server/Botany/Components/ProduceComponent.cs index b3c4e1c95a9b30..db4ed62dd381ae 100644 --- a/Content.Server/Botany/Components/ProduceComponent.cs +++ b/Content.Server/Botany/Components/ProduceComponent.cs @@ -13,12 +13,12 @@ public sealed partial class ProduceComponent : SharedProduceComponent /// /// Seed data used to create a when this produce has its seeds extracted. /// - [DataField("seed")] + [DataField] public SeedData? Seed; /// /// Seed data used to create a when this produce has its seeds extracted. /// - [DataField("seedId", customTypeSerializer: typeof(PrototypeIdSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string? SeedId; } diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 57d03e93435591..7a3e08883ded76 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -133,68 +133,67 @@ public partial class SeedData [DataField("productPrototypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] public List ProductPrototypes = new(); - [DataField("chemicals")] public Dictionary Chemicals = new(); + [DataField] public Dictionary Chemicals = new(); - [DataField("consumeGasses")] public Dictionary ConsumeGasses = new(); + [DataField] public Dictionary ConsumeGasses = new(); - [DataField("exudeGasses")] public Dictionary ExudeGasses = new(); + [DataField] public Dictionary ExudeGasses = new(); #endregion #region Tolerances - [DataField("nutrientConsumption")] public float NutrientConsumption = 0.75f; + [DataField] public float NutrientConsumption = 0.75f; - [DataField("waterConsumption")] public float WaterConsumption = 0.5f; - [DataField("idealHeat")] public float IdealHeat = 293f; - [DataField("heatTolerance")] public float HeatTolerance = 10f; - [DataField("idealLight")] public float IdealLight = 7f; - [DataField("lightTolerance")] public float LightTolerance = 3f; - [DataField("toxinsTolerance")] public float ToxinsTolerance = 4f; + [DataField] public float WaterConsumption = 0.5f; + [DataField] public float IdealHeat = 293f; + [DataField] public float HeatTolerance = 10f; + [DataField] public float IdealLight = 7f; + [DataField] public float LightTolerance = 3f; + [DataField] public float ToxinsTolerance = 4f; - [DataField("lowPressureTolerance")] public float LowPressureTolerance = 81f; + [DataField] public float LowPressureTolerance = 81f; - [DataField("highPressureTolerance")] public float HighPressureTolerance = 121f; + [DataField] public float HighPressureTolerance = 121f; - [DataField("pestTolerance")] public float PestTolerance = 5f; + [DataField] public float PestTolerance = 5f; - [DataField("weedTolerance")] public float WeedTolerance = 5f; + [DataField] public float WeedTolerance = 5f; - [DataField("weedHighLevelThreshold")] public float WeedHighLevelThreshold = 10f; + [DataField] public float WeedHighLevelThreshold = 10f; #endregion #region General traits - [DataField("endurance")] public float Endurance = 100f; + [DataField] public float Endurance = 100f; - [DataField("yield")] public int Yield; - [DataField("lifespan")] public float Lifespan; - [DataField("maturation")] public float Maturation; - [DataField("production")] public float Production; - [DataField("growthStages")] public int GrowthStages = 6; + [DataField] public int Yield; + [DataField] public float Lifespan; + [DataField] public float Maturation; + [DataField] public float Production; + [DataField] public int GrowthStages = 6; - [ViewVariables(VVAccess.ReadWrite)] - [DataField("harvestRepeat")] public HarvestType HarvestRepeat = HarvestType.NoRepeat; + [DataField] public HarvestType HarvestRepeat = HarvestType.NoRepeat; - [DataField("potency")] public float Potency = 1f; + [DataField] public float Potency = 1f; /// /// If true, cannot be harvested for seeds. Balances hybrids and /// mutations. /// - [DataField("seedless")] public bool Seedless = false; + [DataField] public bool Seedless = false; /// /// If false, rapidly decrease health while growing. Used to kill off /// plants with "bad" mutations. /// - [DataField("viable")] public bool Viable = true; + [DataField] public bool Viable = true; /// /// If true, a sharp tool is required to harvest this plant. /// - [DataField("ligneous")] public bool Ligneous; + [DataField] public bool Ligneous; // No, I'm not removing these. // if you re-add these, make sure that they get cloned. @@ -213,37 +212,35 @@ public partial class SeedData #region Cosmetics - [DataField("plantRsi", required: true)] + [DataField(required: true)] public ResPath PlantRsi { get; set; } = default!; - [DataField("plantIconState")] public string PlantIconState { get; set; } = "produce"; + [DataField] public string PlantIconState { get; set; } = "produce"; /// - /// Screams random sound, could be strict sound SoundPathSpecifier or collection SoundCollectionSpecifier - /// base class is SoundSpecifier + /// Screams random sound from collection SoundCollectionSpecifier /// - [DataField("screamSound")] + [DataField] public SoundSpecifier ScreamSound = new SoundCollectionSpecifier("PlantScreams", AudioParams.Default.WithVolume(-10)); [DataField("screaming")] public bool CanScream; - [DataField("kudzuPrototype", customTypeSerializer: typeof(PrototypeIdSerializer))] public string KudzuPrototype = "WeakKudzu"; + [DataField(customTypeSerializer: typeof(PrototypeIdSerializer))] public string KudzuPrototype = "WeakKudzu"; - [DataField("turnIntoKudzu")] public bool TurnIntoKudzu; - [DataField("splatPrototype")] public string? SplatPrototype { get; set; } + [DataField] public bool TurnIntoKudzu; + [DataField] public string? SplatPrototype { get; set; } #endregion /// /// The mutation effects that have been applied to this plant. /// - [DataField("mutations")] //TODO confirm this is sufficient. - public List Mutations { get; set; } = new(); + [DataField] public List Mutations { get; set; } = new(); /// /// The seed prototypes this seed may mutate into when prompted to. /// - [DataField("mutationPrototypes", customTypeSerializer: typeof(PrototypeIdListSerializer))] + [DataField(customTypeSerializer: typeof(PrototypeIdListSerializer))] public List MutationPrototypes = new(); public SeedData Clone() diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index 941453efb4ed14..5569f75b9d9fa9 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -5,16 +5,11 @@ using Content.Shared.Botany; using Content.Shared.Examine; using Content.Shared.Hands.EntitySystems; -using Content.Shared.Physics; using Content.Shared.Popups; using Content.Shared.Random; using Content.Shared.Random.Helpers; -using Content.Shared.Slippery; -using Content.Shared.StepTrigger.Components; using Robust.Server.GameObjects; using Robust.Shared.Map; -using Robust.Shared.Physics; -using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; using Robust.Shared.Random; @@ -34,7 +29,6 @@ public sealed partial class BotanySystem : EntitySystem [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly MetaDataSystem _metaData = default!; [Dependency] private readonly FixtureSystem _fixtureSystem = default!; - [Dependency] private readonly CollisionWakeSystem _colWakeSystem = default!; [Dependency] private readonly RandomHelperSystem _randomHelper = default!; public override void Initialize() diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 32646bece781ae..647cccfcfa6bdc 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -16,7 +16,7 @@ public sealed class MutationSystem : EntitySystem //Additonal TODO: //clean up errors on client side about missing concrete Glow class? //Investigate Ligneous pop-up message not appearing if the trait is acquired via mutation. - //clean up warnings in new code formatting. + //Balance: RobustHarvest can now negate mutating into a low Potency Value, rather than being the primary way to boost Potency. public override void Initialize() { @@ -35,8 +35,8 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float if (Random(mutation.BaseOdds * severity)) { if (mutation.AppliesToPlant) - { - EntityEffectBaseArgs args = new EntityEffectBaseArgs(plantHolder, EntityManager); + { + var args = new EntityEffectBaseArgs(plantHolder, EntityManager); mutation.Mutation.Effect(args); } if (mutation.Persists) //Stat adjustments do not persist by being an attached effect, they just change the stat. @@ -84,9 +84,9 @@ public SeedData Cross(SeedData a, SeedData b) CrossFloat(ref result.Production, a.Production); CrossFloat(ref result.Potency, a.Potency); - CrossBool(ref result.Seedless, a.Seedless); - CrossBool(ref result.Ligneous, a.Ligneous); - CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); + CrossBool(ref result.Seedless, a.Seedless); + CrossBool(ref result.Ligneous, a.Ligneous); + CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu); CrossBool(ref result.CanScream, a.CanScream); CrossGasses(ref result.ExudeGasses, a.ExudeGasses); diff --git a/Content.Server/Botany/Systems/PlantHolderSystem.cs b/Content.Server/Botany/Systems/PlantHolderSystem.cs index 21aa271a96e09c..c45f7bc8a61cb3 100644 --- a/Content.Server/Botany/Systems/PlantHolderSystem.cs +++ b/Content.Server/Botany/Systems/PlantHolderSystem.cs @@ -1,9 +1,7 @@ -using Content.Server.Atmos; using Content.Server.Atmos.EntitySystems; using Content.Server.Botany.Components; using Content.Server.Chemistry.Containers.EntitySystems; using Content.Server.Fluids.Components; -using Content.Server.Ghost.Roles.Components; using Content.Server.Kitchen.Components; using Content.Server.Popups; using Content.Shared.Atmos; @@ -39,7 +37,6 @@ public sealed class PlantHolderSystem : EntitySystem [Dependency] private readonly SharedAudioSystem _audio = default!; [Dependency] private readonly PopupSystem _popup = default!; [Dependency] private readonly IGameTiming _gameTiming = default!; - [Dependency] private readonly SharedPointLightSystem _pointLight = default!; [Dependency] private readonly SolutionContainerSystem _solutionContainerSystem = default!; [Dependency] private readonly TagSystem _tagSystem = default!; [Dependency] private readonly RandomHelperSystem _randomHelper = default!; @@ -79,7 +76,7 @@ private int GetCurrentGrowthStage(Entity entity) if (component.Seed == null) return 0; - var result = Math.Max(1, (int) (component.Age * component.Seed.GrowthStages / component.Seed.Maturation)); + var result = Math.Max(1, (int)(component.Age * component.Seed.GrowthStages / component.Seed.Maturation)); return result; } @@ -125,9 +122,9 @@ private void OnExamine(Entity entity, ref ExaminedEvent ar args.PushMarkup(Loc.GetString("plant-holder-component-pest-high-level-message")); args.PushMarkup(Loc.GetString($"plant-holder-component-water-level-message", - ("waterLevel", (int) component.WaterLevel))); + ("waterLevel", (int)component.WaterLevel))); args.PushMarkup(Loc.GetString($"plant-holder-component-nutrient-level-message", - ("nutritionLevel", (int) component.NutritionLevel))); + ("nutritionLevel", (int)component.NutritionLevel))); if (component.DrawWarnings) { @@ -304,7 +301,7 @@ private void OnInteractUsing(Entity entity, ref InteractUs var displayName = Loc.GetString(component.Seed.DisplayName); _popup.PopupCursor(Loc.GetString("plant-holder-component-take-sample-message", ("seedName", displayName)), args.User); - + DoScream(entity.Owner, component.Seed); if (_random.Prob(0.3f)) @@ -450,7 +447,7 @@ public void Update(EntityUid uid, PlantHolderComponent? component = null) else { if (_random.Prob(0.8f)) - component.Age += (int) (1 * HydroponicsSpeedMultiplier); + component.Age += (int)(1 * HydroponicsSpeedMultiplier); component.UpdateSpriteAfterUpdate = true; } diff --git a/Content.Server/EntityEffects/Effects/Glow.cs b/Content.Server/EntityEffects/Effects/Glow.cs index 842d12348fa920..9f0347672975d7 100644 --- a/Content.Server/EntityEffects/Effects/Glow.cs +++ b/Content.Server/EntityEffects/Effects/Glow.cs @@ -15,29 +15,30 @@ public sealed partial class Glow : EntityEffect [DataField] public Color Color = Color.Black; - static List colors = new List{ - Color.White, - Color.Red, - Color.Yellow, - Color.Green, - Color.Blue, - Color.Purple, - Color.Pink - }; + private static readonly List Colors = new() + { + Color.White, + Color.Red, + Color.Yellow, + Color.Green, + Color.Blue, + Color.Purple, + Color.Pink + }; public override void Effect(EntityEffectBaseArgs args) { if (Color == Color.Black) { var random = IoCManager.Resolve(); - Color = random.Pick(colors); + Color = random.Pick(Colors); } - var _light = args.EntityManager.System(); - var light = _light.EnsureLight(args.TargetEntity); - _light.SetRadius(args.TargetEntity, Radius, light); - _light.SetColor(args.TargetEntity, Color, light); - _light.SetCastShadows(args.TargetEntity, false, light); // this is expensive, and botanists make lots of plants + var lightSystem = args.EntityManager.System(); + var light = lightSystem.EnsureLight(args.TargetEntity); + lightSystem.SetRadius(args.TargetEntity, Radius, light); + lightSystem.SetColor(args.TargetEntity, Color, light); + lightSystem.SetCastShadows(args.TargetEntity, false, light); // this is expensive, and botanists make lots of plants } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs index b5a199681666f7..273ba005d4cdbf 100644 --- a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs +++ b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs @@ -4,7 +4,6 @@ using Content.Shared.Random; using Robust.Shared.Prototypes; using Robust.Shared.Random; -using System.Linq; namespace Content.Server.EntityEffects.Effects; @@ -23,16 +22,16 @@ public override void Effect(EntityEffectBaseArgs args) var random = IoCManager.Resolve(); var prototypeManager = IoCManager.Resolve(); var chemicals = plantholder.Seed.Chemicals; - var _randomChems = prototypeManager.Index("RandomPickBotanyReagent").Fills; + var randomChems = prototypeManager.Index("RandomPickBotanyReagent").Fills; // Add a random amount of a random chemical to this set of chemicals - if (_randomChems != null) + if (randomChems != null) { - var pick = random.Pick(_randomChems); - string chemicalId = random.Pick(pick.Reagents); - int amount = random.Next(1, (int)pick.Quantity); - SeedChemQuantity seedChemQuantity = new SeedChemQuantity(); + var pick = random.Pick(randomChems); + var chemicalId = random.Pick(pick.Reagents); + var amount = random.Next(1, (int)pick.Quantity); + var seedChemQuantity = new SeedChemQuantity(); if (chemicals.ContainsKey(chemicalId)) { seedChemQuantity.Min = chemicals[chemicalId].Min; @@ -44,7 +43,7 @@ public override void Effect(EntityEffectBaseArgs args) seedChemQuantity.Max = 1 + amount; seedChemQuantity.Inherent = false; } - int potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); + var potencyDivisor = (int)Math.Ceiling(100.0f / seedChemQuantity.Max); seedChemQuantity.PotencyDivisor = potencyDivisor; chemicals[chemicalId] = seedChemQuantity; } diff --git a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs index 1c9e00e72b1bc7..3d40a7bf6805db 100644 --- a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs +++ b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs @@ -1,8 +1,6 @@ -using Content.Server.Botany; using Content.Server.Botany.Components; using Content.Shared.Atmos; using Content.Shared.EntityEffects; -using Content.Shared.Random; using Robust.Shared.Prototypes; using Robust.Shared.Random; using System.Linq; @@ -15,9 +13,9 @@ namespace Content.Server.EntityEffects.Effects; public sealed partial class PlantMutateExudeGasses : EntityEffect { [DataField] - public float minValue = 0.01f; + public float MinValue = 0.01f; [DataField] - public float maxValue = 0.5f; + public float MaxValue = 0.5f; public override void Effect(EntityEffectBaseArgs args) { var plantholder = args.EntityManager.GetComponent(args.TargetEntity); @@ -26,11 +24,10 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - var prototypeManager = IoCManager.Resolve(); var gasses = plantholder.Seed.ExudeGasses; // Add a random amount of a random gas to this gas dictionary - float amount = random.NextFloat(minValue, maxValue); + float amount = random.NextFloat(MinValue, MaxValue); Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); if (gasses.ContainsKey(gas)) { @@ -54,9 +51,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateConsumeGasses : EntityEffect { [DataField] - public float minValue = 0.01f; + public float MinValue = 0.01f; [DataField] - public float maxValue = 0.5f; + public float MaxValue = 0.5f; public override void Effect(EntityEffectBaseArgs args) { var plantholder = args.EntityManager.GetComponent(args.TargetEntity); @@ -65,11 +62,10 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - var prototypeManager = IoCManager.Resolve(); var gasses = plantholder.Seed.ConsumeGasses; // Add a random amount of a random gas to this gas dictionary - float amount = random.NextFloat(minValue, maxValue); + float amount = random.NextFloat(MinValue, MaxValue); Gas gas = random.Pick(Enum.GetValues(typeof(Gas)).Cast().ToList()); if (gasses.ContainsKey(gas)) { diff --git a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs index 4fecdbcbcaceac..130cab9f1811cd 100644 --- a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs +++ b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs @@ -24,7 +24,7 @@ public override void Effect(EntityEffectBaseArgs args) if (plantholder.Seed.MutationPrototypes.Count == 0) return; - var random = IoCManager.Resolve(); + var random = IoCManager.Resolve(); var targetProto = random.Pick(plantholder.Seed.MutationPrototypes); prototypeManager.TryIndex(targetProto, out SeedPrototype? protoSeed); diff --git a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs index 12c7c0b9896129..86191b9a29fa6b 100644 --- a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs +++ b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs @@ -5,16 +5,15 @@ namespace Content.Server.EntityEffects.Effects; - /// /// Changes the value on a plant's WaterConsumption value randomly when applied. /// public sealed partial class PlantMutateWaterConsumption : EntityEffect { [DataField] - public float minValue = 0.3f; + public float MinValue = 0.3f; [DataField] - public float maxValue = 0.9f; + public float MaxValue = 0.9f; public override void Effect(EntityEffectBaseArgs args) { @@ -24,8 +23,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.WaterConsumption = random.NextFloat(minValue, maxValue); - + plantholder.Seed.WaterConsumption = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -40,9 +38,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateNutrientConsumption : EntityEffect { [DataField] - public float minValue = 0.05f; + public float MinValue = 0.05f; [DataField] - public float maxValue = 1.2f; + public float MaxValue = 1.2f; public override void Effect(EntityEffectBaseArgs args) { @@ -52,8 +50,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.NutrientConsumption = random.NextFloat(minValue, maxValue); - + plantholder.Seed.NutrientConsumption = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -68,9 +65,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateIdealHeat : EntityEffect { [DataField] - public float minValue = 263f; + public float MinValue = 263f; [DataField] - public float maxValue = 323f; + public float MaxValue = 323f; public override void Effect(EntityEffectBaseArgs args) { @@ -80,8 +77,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.IdealHeat = random.NextFloat(minValue, maxValue); - + plantholder.Seed.IdealHeat = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -96,9 +92,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateHeatTolerance : EntityEffect { [DataField] - public float minValue = 2f; + public float MinValue = 2f; [DataField] - public float maxValue = 25f; + public float MaxValue = 25f; public override void Effect(EntityEffectBaseArgs args) { @@ -108,8 +104,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.HeatTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.HeatTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -124,9 +119,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateIdealLight : EntityEffect { [DataField] - public float minValue = 0f; + public float MinValue = 0f; [DataField] - public float maxValue = 14f; + public float MaxValue = 14f; public override void Effect(EntityEffectBaseArgs args) { @@ -136,8 +131,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.IdealLight = random.NextFloat(minValue, maxValue); - + plantholder.Seed.IdealLight = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -152,9 +146,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateLightTolerance : EntityEffect { [DataField] - public float minValue = 1f; + public float MinValue = 1f; [DataField] - public float maxValue = 5f; + public float MaxValue = 5f; public override void Effect(EntityEffectBaseArgs args) { @@ -164,8 +158,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.LightTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.LightTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -180,9 +173,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateToxinsTolerance : EntityEffect { [DataField] - public float minValue = 1f; + public float MinValue = 1f; [DataField] - public float maxValue = 10f; + public float MaxValue = 10f; public override void Effect(EntityEffectBaseArgs args) { @@ -192,8 +185,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.ToxinsTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.ToxinsTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -208,9 +200,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateLowPressureTolerance : EntityEffect { [DataField] - public float minValue = 60f; + public float MinValue = 60f; [DataField] - public float maxValue = 100f; + public float MaxValue = 100f; public override void Effect(EntityEffectBaseArgs args) { @@ -220,8 +212,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.LowPressureTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.LowPressureTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -236,9 +227,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateHighPressureTolerance : EntityEffect { [DataField] - public float minValue = 100f; + public float MinValue = 100f; [DataField] - public float maxValue = 140f; + public float MaxValue = 140f; public override void Effect(EntityEffectBaseArgs args) { @@ -248,8 +239,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.HighPressureTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.HighPressureTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -264,9 +254,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutatePestTolerance : EntityEffect { [DataField] - public float minValue = 0f; + public float MinValue = 0f; [DataField] - public float maxValue = 15f; + public float MaxValue = 15f; public override void Effect(EntityEffectBaseArgs args) { @@ -276,8 +266,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.PestTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.PestTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -292,9 +281,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateWeedTolerance : EntityEffect { [DataField] - public float minValue = 0f; + public float MinValue = 0f; [DataField] - public float maxValue = 15f; + public float MaxValue = 15f; public override void Effect(EntityEffectBaseArgs args) { @@ -304,8 +293,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.WeedTolerance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.WeedTolerance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -320,9 +308,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateEndurance : EntityEffect { [DataField] - public float minValue = 50f; + public float MinValue = 50f; [DataField] - public float maxValue = 150f; + public float MaxValue = 150f; public override void Effect(EntityEffectBaseArgs args) { @@ -332,8 +320,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Endurance = random.NextFloat(minValue, maxValue); - + plantholder.Seed.Endurance = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -348,9 +335,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateYield : EntityEffect { [DataField] - public int minValue = 3; + public int MinValue = 3; [DataField] - public int maxValue = 10; + public int MaxValue = 10; public override void Effect(EntityEffectBaseArgs args) { @@ -360,8 +347,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Yield = random.Next(minValue, maxValue); - + plantholder.Seed.Yield = random.Next(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -376,9 +362,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateLifespan : EntityEffect { [DataField] - public float minValue = 10f; + public float MinValue = 10f; [DataField] - public float maxValue = 80f; + public float MaxValue = 80f; public override void Effect(EntityEffectBaseArgs args) { @@ -388,7 +374,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Lifespan = random.NextFloat(minValue, maxValue); + plantholder.Seed.Lifespan = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -403,9 +389,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateMaturation : EntityEffect { [DataField] - public float minValue = 3f; + public float MinValue = 3f; [DataField] - public float maxValue = 8f; + public float MaxValue = 8f; public override void Effect(EntityEffectBaseArgs args) { @@ -415,7 +401,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Maturation = random.NextFloat(minValue, maxValue); + plantholder.Seed.Maturation = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -430,9 +416,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutateProduction : EntityEffect { [DataField] - public float minValue = 1f; + public float MinValue = 1f; [DataField] - public float maxValue = 10f; + public float MaxValue = 10f; public override void Effect(EntityEffectBaseArgs args) { @@ -442,7 +428,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Production = random.NextFloat(minValue, maxValue); + plantholder.Seed.Production = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) @@ -457,9 +443,9 @@ public override void Effect(EntityEffectBaseArgs args) public sealed partial class PlantMutatePotency : EntityEffect { [DataField] - public float minValue = 30f; + public float MinValue = 30f; [DataField] - public float maxValue = 100f; + public float MaxValue = 100f; public override void Effect(EntityEffectBaseArgs args) { @@ -469,7 +455,7 @@ public override void Effect(EntityEffectBaseArgs args) return; var random = IoCManager.Resolve(); - plantholder.Seed.Potency = random.NextFloat(minValue, maxValue); + plantholder.Seed.Potency = random.NextFloat(MinValue, MaxValue); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/EntityEffects/Effects/PlantUnviable.cs b/Content.Server/EntityEffects/Effects/PlantUnviable.cs index 4a1fe00e9f17cd..c7c4625e97ec83 100644 --- a/Content.Server/EntityEffects/Effects/PlantUnviable.cs +++ b/Content.Server/EntityEffects/Effects/PlantUnviable.cs @@ -1,7 +1,6 @@ using Content.Server.Botany.Components; using Content.Shared.EntityEffects; using Robust.Shared.Prototypes; -using Robust.Shared.Random; namespace Content.Server.EntityEffects.Effects; @@ -17,7 +16,7 @@ public override void Effect(EntityEffectBaseArgs args) if (plantholder.Seed == null) return; - plantholder.Seed.Viable = false; + plantholder.Seed.Viable = !plantholder.Seed.Viable; } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/EntityEffects/Effects/Slipify.cs b/Content.Server/EntityEffects/Effects/Slipify.cs index 242e6bbf214930..bc1cc062a387d8 100644 --- a/Content.Server/EntityEffects/Effects/Slipify.cs +++ b/Content.Server/EntityEffects/Effects/Slipify.cs @@ -1,5 +1,3 @@ -using Content.Server.Atmos.EntitySystems; -using Content.Shared.Database; using Content.Shared.EntityEffects; using Content.Shared.Physics; using Content.Shared.Slippery; @@ -8,7 +6,6 @@ using Robust.Shared.Physics.Components; using Robust.Shared.Physics.Systems; using Robust.Shared.Prototypes; -using Robust.Shared.Random; namespace Content.Server.EntityEffects.Effects; @@ -19,8 +16,8 @@ public sealed partial class Slipify : EntityEffect { public override void Effect(EntityEffectBaseArgs args) { - var _fixtureSystem = args.EntityManager.System(); - var _colWakeSystem = args.EntityManager.System(); + var fixtureSystem = args.EntityManager.System(); + var colWakeSystem = args.EntityManager.System(); var slippery = args.EntityManager.EnsureComponent(args.TargetEntity); args.EntityManager.Dirty(args.TargetEntity, slippery); args.EntityManager.EnsureComponent(args.TargetEntity); @@ -28,10 +25,10 @@ public override void Effect(EntityEffectBaseArgs args) var fixtures = args.EntityManager.EnsureComponent(args.TargetEntity); var body = args.EntityManager.EnsureComponent(args.TargetEntity); var shape = fixtures.Fixtures["fix1"].Shape; - _fixtureSystem.TryCreateFixture(args.TargetEntity, shape, "slips", 1, false, (int)CollisionGroup.SlipLayer, manager: fixtures, body: body); + fixtureSystem.TryCreateFixture(args.TargetEntity, shape, "slips", 1, false, (int)CollisionGroup.SlipLayer, manager: fixtures, body: body); // Need to disable collision wake so that mobs can collide with and slip on it var collisionWake = args.EntityManager.EnsureComponent(args.TargetEntity); - _colWakeSystem.SetEnabled(args.TargetEntity, false, collisionWake); + colWakeSystem.SetEnabled(args.TargetEntity, false, collisionWake); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Shared/Random/RandomPlantMutation.cs b/Content.Shared/Random/RandomPlantMutation.cs index 3f5309c9a14bae..315fcc01987423 100644 --- a/Content.Shared/Random/RandomPlantMutation.cs +++ b/Content.Shared/Random/RandomPlantMutation.cs @@ -1,10 +1,5 @@ -using Content.Shared.Chemistry.Reagent; using Content.Shared.EntityEffects; -using Content.Shared.FixedPoint; using Robust.Shared.Serialization; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; -using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List; -using System.Text.Json.Serialization; namespace Content.Shared.Random; @@ -18,37 +13,36 @@ public sealed partial class RandomPlantMutation /// /// Odds of this mutation occurring with 1 point of mutation severity on a plant. /// - [DataField("baseOdds")] + [DataField] public float BaseOdds = 0; /// /// The name of this mutation. /// - [DataField("name")] + [DataField] public string Name = ""; /// /// The actual EntityEffect to apply to the target /// - //[JsonPropertyName("mutation")] - [DataField("mutation")] + [DataField] public EntityEffect Mutation = default!; //TODO: rename to Effect or something? /// /// This mutation will target the harvested produce /// - [DataField("appliesToProduce")] + [DataField] public bool AppliesToProduce = true; /// /// This mutation will target the growing plant as soon as this mutation is applied. /// - [DataField("appliesToPlant")] + [DataField] public bool AppliesToPlant = true; /// /// This mutation stays on the plant and its produce. If false while AppliesToPlant is true, the effect will run when triggered. /// - [DataField("persists")] + [DataField] public bool Persists = true; } From ae9c27febe8704ab1d5ab854aa5bda0cca50bc5c Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Mon, 19 Aug 2024 00:00:55 -0400 Subject: [PATCH 10/19] Fix 'concrete type' error --- Content.Server/Botany/Systems/MutationSystem.cs | 5 ----- Content.Shared/Random/RandomPlantMutationListPrototype.cs | 2 +- Resources/Prototypes/Hydroponics/randomMutations.yml | 2 +- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 647cccfcfa6bdc..9959972f97779b 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -13,11 +13,6 @@ public sealed class MutationSystem : EntitySystem [Dependency] private readonly IPrototypeManager _prototypeManager = default!; private RandomPlantMutationListPrototype _randomMutations = default!; - //Additonal TODO: - //clean up errors on client side about missing concrete Glow class? - //Investigate Ligneous pop-up message not appearing if the trait is acquired via mutation. - //Balance: RobustHarvest can now negate mutating into a low Potency Value, rather than being the primary way to boost Potency. - public override void Initialize() { _randomMutations = _prototypeManager.Index("RandomPlantMutations"); diff --git a/Content.Shared/Random/RandomPlantMutationListPrototype.cs b/Content.Shared/Random/RandomPlantMutationListPrototype.cs index ab28594a04b1d3..84e3b9256c3b4a 100644 --- a/Content.Shared/Random/RandomPlantMutationListPrototype.cs +++ b/Content.Shared/Random/RandomPlantMutationListPrototype.cs @@ -13,6 +13,6 @@ public sealed partial class RandomPlantMutationListPrototype : IPrototype /// /// List of RandomFills that can be picked from. /// - [DataField("mutations", required: true)] + [DataField("mutations", required: true, serverOnly: true)] public List mutations = new(); } diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 29f83c0f4c0921..8935a4b75bced5 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -3,7 +3,7 @@ mutations: - name: Bioluminescent baseOdds: 0.0072 - mutation: !type:Glow # new effect + mutation: !type:Glow - name: Sentient baseOdds: 0.0072 appliesToPlant: false #makes the botany tray sentient if true From 085e92589e29959a2e0c69e49bc10f1c28105fb9 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Sun, 25 Aug 2024 11:34:40 -0400 Subject: [PATCH 11/19] Do not apply the same persistent mutation twice. --- Content.Server/Botany/Systems/MutationSystem.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 9959972f97779b..d851748cd32e70 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -34,7 +34,8 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float var args = new EntityEffectBaseArgs(plantHolder, EntityManager); mutation.Mutation.Effect(args); } - if (mutation.Persists) //Stat adjustments do not persist by being an attached effect, they just change the stat. + //Stat adjustments do not persist by being an attached effect, they just change the stat. + if (mutation.Persists && !seed.Mutations.Any(m => m.Name == mutation.Name)) seed.Mutations.Add(mutation); } } From 90b15b409e3c78f457eda46506c93d6fb19e5b97 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Thu, 29 Aug 2024 16:13:38 -0400 Subject: [PATCH 12/19] correct odds for mutations. --- .../Hydroponics/randomMutations.yml | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 8935a4b75bced5..531748416e4136 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -2,21 +2,21 @@ id: RandomPlantMutations mutations: - name: Bioluminescent - baseOdds: 0.0072 + baseOdds: 0.036 mutation: !type:Glow - name: Sentient baseOdds: 0.0072 appliesToPlant: false #makes the botany tray sentient if true mutation: !type:MakeSentient #existing effect. - name: Slippery - baseOdds: 0.0072 + baseOdds: 0.036 mutation: !type:Slipify - name: ChangeSpecies - baseOdds: 0.0072 + baseOdds: 0.036 appliesToProduce: false mutation: !type:PlantSpeciesChange - name: Unviable - baseOdds: 0.00012 + baseOdds: 0.109 mutation: !type:PlantUnviable - name: ChangeWaterConsumption baseOdds: 0.018 @@ -87,27 +87,27 @@ persists: false mutation: !type:PlantMutatePotency - name: ChangeSeedless - baseOdds: 0.00036 + baseOdds: 0.036 persists: false mutation: !type:PlantMutateSeedless - name: ChangeLigneous - baseOdds: 0.00036 + baseOdds: 0.036 persists: false mutation: !type:PlantMutateLigneous - name: ChangeTurnIntoKudzu - baseOdds: 0.00036 + baseOdds: 0.036 persists: false mutation: !type:PlantMutateKudzu - name: ChangeScreaming - baseOdds: 0.00036 + baseOdds: 0.036 persists: false mutation: !type:PlantMutateScream - name: ChangeChemicals - baseOdds: 0.00018 + baseOdds: 0.072 persists: false mutation: !type:PlantMutateChemicals - name: ChangeExudeGasses - baseOdds: 0.00091 + baseOdds: 0.0145 persists: false mutation: !type:PlantMutateExudeGasses - name: ChangeConsumeGasses @@ -115,6 +115,6 @@ persists: false mutation: !type:PlantMutateConsumeGasses - name: ChangeHarvest - baseOdds: 0.00036 + baseOdds: 0.036 persists: false mutation: !type:PlantMutateHarvest \ No newline at end of file From 73c36c9cf15a775063abbd34f6aec5d71912b2c1 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Mon, 9 Sep 2024 19:30:56 -0400 Subject: [PATCH 13/19] Review change requests. --- .../Botany/Systems/BotanySystem.Produce.cs | 3 +- .../Botany/Systems/BotanySystem.Seed.cs | 1 - .../Botany/Systems/MutationSystem.cs | 74 ++- .../EntityEffects/Effects/PlantChangeStat.cs | 59 ++ .../Effects/PlantMutateChemicals.cs | 1 - .../EntityEffects/Effects/PlantMutateGases.cs | 2 + .../EntityEffects/Effects/PlantMutateKudzu.cs | 26 + .../Effects/PlantMutateLigneous.cs | 27 + .../Effects/PlantMutateScream.cs | 26 + .../Effects/PlantMutateSeedless.cs | 26 + .../Effects/PlantSpeciesChange.cs | 1 - .../Effects/PlantStatAdjustments.cs | 549 ------------------ Content.Shared/Random/RandomPlantMutation.cs | 2 +- .../Hydroponics/randomMutations.yml | 126 ++-- 14 files changed, 329 insertions(+), 594 deletions(-) create mode 100644 Content.Server/EntityEffects/Effects/PlantChangeStat.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateScream.cs create mode 100644 Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs diff --git a/Content.Server/Botany/Systems/BotanySystem.Produce.cs b/Content.Server/Botany/Systems/BotanySystem.Produce.cs index 0bda20e140fd80..8fdf96f57ba997 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Produce.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Produce.cs @@ -16,7 +16,7 @@ public void ProduceGrown(EntityUid uid, ProduceComponent produce) if (mutation.AppliesToProduce) { var args = new EntityEffectBaseArgs(uid, EntityManager); - mutation.Mutation.Effect(args); + mutation.Effect.Effect(args); } } @@ -26,7 +26,6 @@ public void ProduceGrown(EntityUid uid, ProduceComponent produce) FixedPoint2.Zero)) return; - solutionContainer.RemoveAllSolution(); foreach (var (chem, quantity) in seed.Chemicals) { diff --git a/Content.Server/Botany/Systems/BotanySystem.Seed.cs b/Content.Server/Botany/Systems/BotanySystem.Seed.cs index 51faffa5c215f4..1487ed71d471c6 100644 --- a/Content.Server/Botany/Systems/BotanySystem.Seed.cs +++ b/Content.Server/Botany/Systems/BotanySystem.Seed.cs @@ -168,7 +168,6 @@ public IEnumerable GenerateProduct(SeedData proto, EntityCoordinates produce.Seed = proto; ProduceGrown(entity, produce); - _appearance.SetData(entity, ProduceVisuals.Potency, proto.Potency); if (proto.Mysterious) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index d851748cd32e70..1e6fb62bf6f27f 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -32,9 +32,9 @@ public void CheckRandomMutations(EntityUid plantHolder, ref SeedData seed, float if (mutation.AppliesToPlant) { var args = new EntityEffectBaseArgs(plantHolder, EntityManager); - mutation.Mutation.Effect(args); + mutation.Effect.Effect(args); } - //Stat adjustments do not persist by being an attached effect, they just change the stat. + // Stat adjustments do not persist by being an attached effect, they just change the stat. if (mutation.Persists && !seed.Mutations.Any(m => m.Name == mutation.Name)) seed.Mutations.Add(mutation); } @@ -100,6 +100,76 @@ public SeedData Cross(SeedData a, SeedData b) return result; } + // Mutate reference 'val' between 'min' and 'max' by pretending the value + // is representable by a thermometer code with 'bits' number of bits and + // randomly flipping some of them. + public void MutateFloat(ref float val, float min, float max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valIntMutated; + if (Random(probIncrease)) + { + valIntMutated = valInt + 1; + } + else + { + valIntMutated = valInt - 1; + } + + // Set value based on mutated thermometer code. + float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); + val = valMutated; + } + + public void MutateInt(ref int val, int min, int max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasing it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valMutated; + if (Random(probIncrease)) + { + valMutated = val + 1; + } + else + { + valMutated = val - 1; + } + + valMutated = Math.Clamp(valMutated, min, max); + val = valMutated; + } + + + private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs new file mode 100644 index 00000000000000..cfd1d328069745 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs @@ -0,0 +1,59 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Server.Botany.Systems; +using Content.Shared.EntityEffects; +using JetBrains.Annotations; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects.PlantMetabolism; + +[UsedImplicitly] +public sealed partial class PlantChangeStat : EntityEffect +{ + [DataField] + public string TargetValue; + + [DataField] + public float MinValue; + + [DataField] + public float MaxValue; + + [DataField] + public int Steps; + + public override void Effect(EntityEffectBaseArgs args) + { + var plantHolder = args.EntityManager.GetComponent(args.TargetEntity); + if (plantHolder == null || plantHolder.Seed == null) + return; + + var member = plantHolder.Seed.GetType().GetField(TargetValue); + + if (member == null) + return; + + var currentValObj = member.GetValue(plantHolder.Seed); + if (currentValObj == null) + return; + + var mutationSys = args.EntityManager.System(); + if (member.FieldType == typeof(float)) + { + var floatVal = (float)currentValObj; + mutationSys.MutateFloat(ref floatVal, MinValue, MaxValue, Steps); + member.SetValue(plantHolder.Seed, floatVal); + } + else if (member.FieldType == typeof(int)) + { + var intVal = (int)currentValObj; + mutationSys.MutateInt(ref intVal, (int)MinValue, (int)MaxValue, Steps); + member.SetValue(plantHolder.Seed, intVal); + } + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + throw new NotImplementedException(); + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs index 273ba005d4cdbf..7ee6cd13d758c2 100644 --- a/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs +++ b/Content.Server/EntityEffects/Effects/PlantMutateChemicals.cs @@ -24,7 +24,6 @@ public override void Effect(EntityEffectBaseArgs args) var chemicals = plantholder.Seed.Chemicals; var randomChems = prototypeManager.Index("RandomPickBotanyReagent").Fills; - // Add a random amount of a random chemical to this set of chemicals if (randomChems != null) { diff --git a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs index 3d40a7bf6805db..710aa09650fd55 100644 --- a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs +++ b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs @@ -14,6 +14,7 @@ public sealed partial class PlantMutateExudeGasses : EntityEffect { [DataField] public float MinValue = 0.01f; + [DataField] public float MaxValue = 0.5f; public override void Effect(EntityEffectBaseArgs args) @@ -52,6 +53,7 @@ public sealed partial class PlantMutateConsumeGasses : EntityEffect { [DataField] public float MinValue = 0.01f; + [DataField] public float MaxValue = 0.5f; public override void Effect(EntityEffectBaseArgs args) diff --git a/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs b/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs new file mode 100644 index 00000000000000..ee28981ba7e7ed --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs @@ -0,0 +1,26 @@ +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Changes if the plant will turn into kudzu once weed levels are high +/// +public sealed partial class PlantMutateKudzu : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.TurnIntoKudzu = !plantholder.Seed.TurnIntoKudzu; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs b/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs new file mode 100644 index 00000000000000..796aeb96852cba --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs @@ -0,0 +1,27 @@ +using Content.Server.Botany; +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Changes if the plant requires a hatchet to harvest. +/// +public sealed partial class PlantMutateLigneous : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.Ligneous = !plantholder.Seed.Ligneous; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateScream.cs b/Content.Server/EntityEffects/Effects/PlantMutateScream.cs new file mode 100644 index 00000000000000..646df7ad053f29 --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateScream.cs @@ -0,0 +1,26 @@ +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Changes if the plant and its produce scream. +/// +public sealed partial class PlantMutateScream : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.CanScream = !plantholder.Seed.CanScream; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs b/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs new file mode 100644 index 00000000000000..a0353e05b6f4ac --- /dev/null +++ b/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs @@ -0,0 +1,26 @@ +using Content.Server.Botany.Components; +using Content.Shared.EntityEffects; +using Robust.Shared.Prototypes; + +namespace Content.Server.EntityEffects.Effects; + +/// +/// Changes if the plant has seeds or not. +/// +public sealed partial class PlantMutateSeedless : EntityEffect +{ + public override void Effect(EntityEffectBaseArgs args) + { + var plantholder = args.EntityManager.GetComponent(args.TargetEntity); + + if (plantholder.Seed == null) + return; + + plantholder.Seed.Seedless = !plantholder.Seed.Seedless; + } + + protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) + { + return "TODO"; + } +} diff --git a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs index 130cab9f1811cd..65bd59daa37068 100644 --- a/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs +++ b/Content.Server/EntityEffects/Effects/PlantSpeciesChange.cs @@ -15,7 +15,6 @@ public sealed partial class PlantSpeciesChange : EntityEffect public override void Effect(EntityEffectBaseArgs args) { var prototypeManager = IoCManager.Resolve(); - //TODO: get plant seed, then species var plantholder = args.EntityManager.GetComponent(args.TargetEntity); if (plantholder.Seed == null) diff --git a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs b/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs deleted file mode 100644 index 86191b9a29fa6b..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantStatAdjustments.cs +++ /dev/null @@ -1,549 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; -using Robust.Shared.Random; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes the value on a plant's WaterConsumption value randomly when applied. -/// -public sealed partial class PlantMutateWaterConsumption : EntityEffect -{ - [DataField] - public float MinValue = 0.3f; - [DataField] - public float MaxValue = 0.9f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.WaterConsumption = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's NutrientConsumption value randomly when applied. -/// -public sealed partial class PlantMutateNutrientConsumption : EntityEffect -{ - [DataField] - public float MinValue = 0.05f; - [DataField] - public float MaxValue = 1.2f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.NutrientConsumption = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's IdealHeat value randomly when applied. -/// -public sealed partial class PlantMutateIdealHeat : EntityEffect -{ - [DataField] - public float MinValue = 263f; - [DataField] - public float MaxValue = 323f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.IdealHeat = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's HeatTolerance value randomly when applied. -/// -public sealed partial class PlantMutateHeatTolerance : EntityEffect -{ - [DataField] - public float MinValue = 2f; - [DataField] - public float MaxValue = 25f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.HeatTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's IdealLight value randomly when applied. -/// -public sealed partial class PlantMutateIdealLight : EntityEffect -{ - [DataField] - public float MinValue = 0f; - [DataField] - public float MaxValue = 14f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.IdealLight = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's LightTolerance value randomly when applied. -/// -public sealed partial class PlantMutateLightTolerance : EntityEffect -{ - [DataField] - public float MinValue = 1f; - [DataField] - public float MaxValue = 5f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.LightTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's ToxinsTolerance value randomly when applied. -/// -public sealed partial class PlantMutateToxinsTolerance : EntityEffect -{ - [DataField] - public float MinValue = 1f; - [DataField] - public float MaxValue = 10f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.ToxinsTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's LowPressureTolerance value randomly when applied. -/// -public sealed partial class PlantMutateLowPressureTolerance : EntityEffect -{ - [DataField] - public float MinValue = 60f; - [DataField] - public float MaxValue = 100f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.LowPressureTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's HighPressureTolerance value randomly when applied. -/// -public sealed partial class PlantMutateHighPressureTolerance : EntityEffect -{ - [DataField] - public float MinValue = 100f; - [DataField] - public float MaxValue = 140f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.HighPressureTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's PestTolerance value randomly when applied. -/// -public sealed partial class PlantMutatePestTolerance : EntityEffect -{ - [DataField] - public float MinValue = 0f; - [DataField] - public float MaxValue = 15f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.PestTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's WeedTolerance value randomly when applied. -/// -public sealed partial class PlantMutateWeedTolerance : EntityEffect -{ - [DataField] - public float MinValue = 0f; - [DataField] - public float MaxValue = 15f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.WeedTolerance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Endurance value randomly when applied. -/// -public sealed partial class PlantMutateEndurance : EntityEffect -{ - [DataField] - public float MinValue = 50f; - [DataField] - public float MaxValue = 150f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Endurance = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Yield value randomly when applied. -/// -public sealed partial class PlantMutateYield : EntityEffect -{ - [DataField] - public int MinValue = 3; - [DataField] - public int MaxValue = 10; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Yield = random.Next(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Lifespan value randomly when applied. -/// -public sealed partial class PlantMutateLifespan : EntityEffect -{ - [DataField] - public float MinValue = 10f; - [DataField] - public float MaxValue = 80f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Lifespan = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Maturation value randomly when applied. -/// -public sealed partial class PlantMutateMaturation : EntityEffect -{ - [DataField] - public float MinValue = 3f; - [DataField] - public float MaxValue = 8f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Maturation = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Production value randomly when applied. -/// -public sealed partial class PlantMutateProduction : EntityEffect -{ - [DataField] - public float MinValue = 1f; - [DataField] - public float MaxValue = 10f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Production = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes the value on a plant's Potency value randomly when applied. -/// -public sealed partial class PlantMutatePotency : EntityEffect -{ - [DataField] - public float MinValue = 30f; - [DataField] - public float MaxValue = 100f; - - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - var random = IoCManager.Resolve(); - plantholder.Seed.Potency = random.NextFloat(MinValue, MaxValue); - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes if the plant has seeds or not. -/// -public sealed partial class PlantMutateSeedless : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.Seedless = !plantholder.Seed.Seedless; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes if the plant requires a hatchet to harvest. -/// -public sealed partial class PlantMutateLigneous : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.Ligneous = !plantholder.Seed.Ligneous; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes if the plant will turn into kudzu once weed levels are high -/// -public sealed partial class PlantMutateKudzu : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.TurnIntoKudzu = !plantholder.Seed.TurnIntoKudzu; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} - -/// -/// Changes if the plant and its produce scream. -/// -public sealed partial class PlantMutateScream : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.CanScream = !plantholder.Seed.CanScream; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Shared/Random/RandomPlantMutation.cs b/Content.Shared/Random/RandomPlantMutation.cs index 315fcc01987423..d95cf7bf422bf7 100644 --- a/Content.Shared/Random/RandomPlantMutation.cs +++ b/Content.Shared/Random/RandomPlantMutation.cs @@ -26,7 +26,7 @@ public sealed partial class RandomPlantMutation /// The actual EntityEffect to apply to the target /// [DataField] - public EntityEffect Mutation = default!; //TODO: rename to Effect or something? + public EntityEffect Effect = default!; /// /// This mutation will target the harvested produce diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 531748416e4136..88d3b393eb7877 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -3,118 +3,170 @@ mutations: - name: Bioluminescent baseOdds: 0.036 - mutation: !type:Glow + effect: !type:Glow - name: Sentient baseOdds: 0.0072 - appliesToPlant: false #makes the botany tray sentient if true - mutation: !type:MakeSentient #existing effect. + appliesToPlant: false # makes the botany tray sentient if true + effect: !type:MakeSentient # existing effect. - name: Slippery baseOdds: 0.036 - mutation: !type:Slipify + effect: !type:Slipify - name: ChangeSpecies baseOdds: 0.036 appliesToProduce: false - mutation: !type:PlantSpeciesChange + effect: !type:PlantSpeciesChange - name: Unviable baseOdds: 0.109 - mutation: !type:PlantUnviable + effect: !type:PlantUnviable - name: ChangeWaterConsumption baseOdds: 0.018 persists: false - mutation: !type:PlantMutateWaterConsumption + effect: !type:PlantChangeStat + targetValue: WaterConsumption + minValue: 0.3 + maxValue: 0.9 + steps: 5 - name: ChangeNutrientConsumption baseOdds: 0.018 persists: false - mutation: !type:PlantMutateNutrientConsumption + effect: !type:PlantChangeStat + targetValue: NutrientConsumption + minValue: 0.05 + maxValue: 1.2 + steps: 5 - name: ChangeIdealHeat baseOdds: 0.018 persists: false - mutation: !type:PlantMutateIdealHeat + effect: !type:PlantChangeStat + targetValue: IdealHeat + minValue: 263 + maxValue: 323 + steps: 5 - name: ChangeHeatTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateHeatTolerance - - name: ChangeIdealLight - baseOdds: 0.018 - persists: false - mutation: !type:PlantMutateIdealLight - - name: ChangeLightTolerance - baseOdds: 0.018 - persists: false - mutation: !type:PlantMutateLightTolerance + effect: !type:PlantChangeStat + targetValue: HeatTolerance + minValue: 2 + maxValue: 25 + steps: 5 - name: ChangeToxinsTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateToxinsTolerance + effect: !type:PlantChangeStat + targetValue: ToxinsTolerance + minValue: 1 + maxValue: 10 + steps: 5 - name: ChangeLowPressureTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateLowPressureTolerance + effect: !type:PlantChangeStat + targetValue: LowPressureTolerance + minValue: 60 + maxValue: 100 + steps: 5 - name: ChangeHighPressureTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateHighPressureTolerance + effect: !type:PlantChangeStat + targetValue: HighPressureTolerance + minValue: 100 + maxValue: 140 + steps: 5 - name: ChangePestTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutatePestTolerance + effect: !type:PlantChangeStat + targetValue: PestTolerance + minValue: 0 + maxValue: 15 + steps: 5 - name: ChangeWeedTolerance baseOdds: 0.018 persists: false - mutation: !type:PlantMutateWeedTolerance + effect: !type:PlantChangeStat + targetValue: WeedTolerance + minValue: 0 + maxValue: 15 + steps: 5 - name: ChangeEndurance baseOdds: 0.036 persists: false - mutation: !type:PlantMutateEndurance + effect: !type:PlantChangeStat + targetValue: Endurance + minValue: 50 + maxValue: 150 + steps: 5 - name: ChangeYield baseOdds: 0.036 persists: false - mutation: !type:PlantMutateYield + effect: !type:PlantChangeStat + targetValue: Yield + minValue: 3 + maxValue: 10 + steps: 5 - name: ChangeLifespan baseOdds: 0.036 persists: false - mutation: !type:PlantMutateLifespan + effect: !type:PlantChangeStat + targetValue: Lifespan + minValue: 10 + maxValue: 80 + steps: 5 - name: ChangeMaturation baseOdds: 0.036 persists: false - mutation: !type:PlantMutateMaturation + effect: !type:PlantChangeStat + targetValue: Maturation + minValue: 3 + maxValue: 8 + steps: 5 - name: ChangeProduction baseOdds: 0.036 persists: false - mutation: !type:PlantMutateProduction + effect: !type:PlantChangeStat + targetValue: Production + minValue: 1 + maxValue: 10 + steps: 5 - name: ChangePotency baseOdds: 0.036 persists: false - mutation: !type:PlantMutatePotency + effect: !type:PlantChangeStat + targetValue: Potency + minValue: 30 + maxValue: 100 + steps: 5 - name: ChangeSeedless baseOdds: 0.036 persists: false - mutation: !type:PlantMutateSeedless + effect: !type:PlantMutateSeedless - name: ChangeLigneous baseOdds: 0.036 persists: false - mutation: !type:PlantMutateLigneous + effect: !type:PlantMutateLigneous - name: ChangeTurnIntoKudzu baseOdds: 0.036 persists: false - mutation: !type:PlantMutateKudzu + effect: !type:PlantMutateKudzu - name: ChangeScreaming baseOdds: 0.036 persists: false - mutation: !type:PlantMutateScream + effect: !type:PlantMutateScream - name: ChangeChemicals baseOdds: 0.072 persists: false - mutation: !type:PlantMutateChemicals + effect: !type:PlantMutateChemicals - name: ChangeExudeGasses baseOdds: 0.0145 persists: false - mutation: !type:PlantMutateExudeGasses + effect: !type:PlantMutateExudeGasses - name: ChangeConsumeGasses baseOdds: 0.0036 persists: false - mutation: !type:PlantMutateConsumeGasses + effect: !type:PlantMutateConsumeGasses - name: ChangeHarvest baseOdds: 0.036 persists: false - mutation: !type:PlantMutateHarvest \ No newline at end of file + effect: !type:PlantMutateHarvest \ No newline at end of file From eb44612d490f85dc5a0d51aac23bb923df619743 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Mon, 9 Sep 2024 22:27:10 -0400 Subject: [PATCH 14/19] BEGONE LINEBREAKS --- Content.Server/Botany/Systems/MutationSystem.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 1e6fb62bf6f27f..b80d3bed05c065 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -168,8 +168,6 @@ public void MutateInt(ref int val, int min, int max, int bits) val = valMutated; } - - private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab From 6f13f04d5cddc2088106e442a752e50f69b243d6 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Mon, 9 Sep 2024 22:30:21 -0400 Subject: [PATCH 15/19] Log an error the best we can if the stat to modify wasn't found --- Content.Server/EntityEffects/Effects/PlantChangeStat.cs | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs index cfd1d328069745..27f3a8df47945e 100644 --- a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs +++ b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs @@ -1,6 +1,5 @@ using Content.Server.Botany; using Content.Server.Botany.Components; -using Content.Server.Botany.Systems; using Content.Shared.EntityEffects; using JetBrains.Annotations; using Robust.Shared.Prototypes; @@ -29,15 +28,18 @@ public override void Effect(EntityEffectBaseArgs args) return; var member = plantHolder.Seed.GetType().GetField(TargetValue); + var mutationSys = args.EntityManager.System(); if (member == null) + { + mutationSys.Log.Error(this.GetType().Name + " Error: Member " + TargetValue + " not found on " + plantHolder.GetType().Name + ". Did you misspell it?"); return; + } var currentValObj = member.GetValue(plantHolder.Seed); if (currentValObj == null) return; - var mutationSys = args.EntityManager.System(); if (member.FieldType == typeof(float)) { var floatVal = (float)currentValObj; From 02364fc16af346fb51ace0a88dceb1560c077d61 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Fri, 13 Sep 2024 22:24:43 -0400 Subject: [PATCH 16/19] PlantChangeStat now supports bools, includes MutateInt/Float. --- .../Botany/Systems/MutationSystem.cs | 68 --------------- .../EntityEffects/Effects/PlantChangeStat.cs | 85 ++++++++++++++++++- .../EntityEffects/Effects/PlantMutateGases.cs | 1 + .../EntityEffects/Effects/PlantMutateKudzu.cs | 26 ------ .../Effects/PlantMutateLigneous.cs | 27 ------ .../Effects/PlantMutateScream.cs | 26 ------ .../Effects/PlantMutateSeedless.cs | 26 ------ .../EntityEffects/Effects/PlantUnviable.cs | 26 ------ .../Hydroponics/randomMutations.yml | 12 ++- 9 files changed, 92 insertions(+), 205 deletions(-) delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateScream.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs delete mode 100644 Content.Server/EntityEffects/Effects/PlantUnviable.cs diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index b80d3bed05c065..f4060df6527a81 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -100,74 +100,6 @@ public SeedData Cross(SeedData a, SeedData b) return result; } - // Mutate reference 'val' between 'min' and 'max' by pretending the value - // is representable by a thermometer code with 'bits' number of bits and - // randomly flipping some of them. - public void MutateFloat(ref float val, float min, float max, int bits) - { - if (min == max) - { - val = min; - return; - } - - // Starting number of bits that are high, between 0 and bits. - // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. - int valInt = (int)MathF.Round((val - min) / (max - min) * bits); - // val may be outside the range of min/max due to starting prototype values, so clamp. - valInt = Math.Clamp(valInt, 0, bits); - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)valInt / bits; - int valIntMutated; - if (Random(probIncrease)) - { - valIntMutated = valInt + 1; - } - else - { - valIntMutated = valInt - 1; - } - - // Set value based on mutated thermometer code. - float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); - val = valMutated; - } - - public void MutateInt(ref int val, int min, int max, int bits) - { - if (min == max) - { - val = min; - return; - } - - // Starting number of bits that are high, between 0 and bits. - // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. - int valInt = (int)MathF.Round((val - min) / (max - min) * bits); - // val may be outside the range of min/max due to starting prototype values, so clamp. - valInt = Math.Clamp(valInt, 0, bits); - - // Probability that the bit flip increases n. - // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasing it. - // In other words, it tends to go to the middle. - float probIncrease = 1 - (float)valInt / bits; - int valMutated; - if (Random(probIncrease)) - { - valMutated = val + 1; - } - else - { - valMutated = val - 1; - } - - valMutated = Math.Clamp(valMutated, min, max); - val = valMutated; - } - private void CrossChemicals(ref Dictionary val, Dictionary other) { // Go through chemicals from the pollen in swab diff --git a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs index 27f3a8df47945e..9592ff779daa8b 100644 --- a/Content.Server/EntityEffects/Effects/PlantChangeStat.cs +++ b/Content.Server/EntityEffects/Effects/PlantChangeStat.cs @@ -3,6 +3,7 @@ using Content.Shared.EntityEffects; using JetBrains.Annotations; using Robust.Shared.Prototypes; +using Robust.Shared.Random; namespace Content.Server.EntityEffects.Effects.PlantMetabolism; @@ -43,15 +44,95 @@ public override void Effect(EntityEffectBaseArgs args) if (member.FieldType == typeof(float)) { var floatVal = (float)currentValObj; - mutationSys.MutateFloat(ref floatVal, MinValue, MaxValue, Steps); + MutateFloat(ref floatVal, MinValue, MaxValue, Steps); member.SetValue(plantHolder.Seed, floatVal); } else if (member.FieldType == typeof(int)) { var intVal = (int)currentValObj; - mutationSys.MutateInt(ref intVal, (int)MinValue, (int)MaxValue, Steps); + MutateInt(ref intVal, (int)MinValue, (int)MaxValue, Steps); member.SetValue(plantHolder.Seed, intVal); } + else if (member.FieldType == typeof(bool)) + { + var boolVal = (bool)currentValObj; + boolVal = !boolVal; + member.SetValue(plantHolder.Seed, boolVal); + } + } + + // Mutate reference 'val' between 'min' and 'max' by pretending the value + // is representable by a thermometer code with 'bits' number of bits and + // randomly flipping some of them. + private void MutateFloat(ref float val, float min, float max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasive it it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valIntMutated; + if (Random(probIncrease)) + { + valIntMutated = valInt + 1; + } + else + { + valIntMutated = valInt - 1; + } + + // Set value based on mutated thermometer code. + float valMutated = Math.Clamp((float)valIntMutated / bits * (max - min) + min, min, max); + val = valMutated; + } + + private void MutateInt(ref int val, int min, int max, int bits) + { + if (min == max) + { + val = min; + return; + } + + // Starting number of bits that are high, between 0 and bits. + // In other words, it's val mapped linearly from range [min, max] to range [0, bits], and then rounded. + int valInt = (int)MathF.Round((val - min) / (max - min) * bits); + // val may be outside the range of min/max due to starting prototype values, so clamp. + valInt = Math.Clamp(valInt, 0, bits); + + // Probability that the bit flip increases n. + // The higher the current value is, the lower the probability of increasing value is, and the higher the probability of decreasing it. + // In other words, it tends to go to the middle. + float probIncrease = 1 - (float)valInt / bits; + int valMutated; + if (Random(probIncrease)) + { + valMutated = val + 1; + } + else + { + valMutated = val - 1; + } + + valMutated = Math.Clamp(valMutated, min, max); + val = valMutated; + } + + private bool Random(float odds) + { + var random = IoCManager.Resolve(); + return random.Prob(odds); } protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) diff --git a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs index 710aa09650fd55..52b9da3a851512 100644 --- a/Content.Server/EntityEffects/Effects/PlantMutateGases.cs +++ b/Content.Server/EntityEffects/Effects/PlantMutateGases.cs @@ -17,6 +17,7 @@ public sealed partial class PlantMutateExudeGasses : EntityEffect [DataField] public float MaxValue = 0.5f; + public override void Effect(EntityEffectBaseArgs args) { var plantholder = args.EntityManager.GetComponent(args.TargetEntity); diff --git a/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs b/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs deleted file mode 100644 index ee28981ba7e7ed..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateKudzu.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes if the plant will turn into kudzu once weed levels are high -/// -public sealed partial class PlantMutateKudzu : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.TurnIntoKudzu = !plantholder.Seed.TurnIntoKudzu; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs b/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs deleted file mode 100644 index 796aeb96852cba..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateLigneous.cs +++ /dev/null @@ -1,27 +0,0 @@ -using Content.Server.Botany; -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes if the plant requires a hatchet to harvest. -/// -public sealed partial class PlantMutateLigneous : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.Ligneous = !plantholder.Seed.Ligneous; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateScream.cs b/Content.Server/EntityEffects/Effects/PlantMutateScream.cs deleted file mode 100644 index 646df7ad053f29..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateScream.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes if the plant and its produce scream. -/// -public sealed partial class PlantMutateScream : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.CanScream = !plantholder.Seed.CanScream; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs b/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs deleted file mode 100644 index a0353e05b6f4ac..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantMutateSeedless.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Changes if the plant has seeds or not. -/// -public sealed partial class PlantMutateSeedless : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.Seedless = !plantholder.Seed.Seedless; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Content.Server/EntityEffects/Effects/PlantUnviable.cs b/Content.Server/EntityEffects/Effects/PlantUnviable.cs deleted file mode 100644 index c7c4625e97ec83..00000000000000 --- a/Content.Server/EntityEffects/Effects/PlantUnviable.cs +++ /dev/null @@ -1,26 +0,0 @@ -using Content.Server.Botany.Components; -using Content.Shared.EntityEffects; -using Robust.Shared.Prototypes; - -namespace Content.Server.EntityEffects.Effects; - -/// -/// Makes a mob glow. -/// -public sealed partial class PlantUnviable : EntityEffect -{ - public override void Effect(EntityEffectBaseArgs args) - { - var plantholder = args.EntityManager.GetComponent(args.TargetEntity); - - if (plantholder.Seed == null) - return; - - plantholder.Seed.Viable = !plantholder.Seed.Viable; - } - - protected override string? ReagentEffectGuidebookText(IPrototypeManager prototype, IEntitySystemManager entSys) - { - return "TODO"; - } -} diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 88d3b393eb7877..ae23f8a388923a 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -141,19 +141,23 @@ - name: ChangeSeedless baseOdds: 0.036 persists: false - effect: !type:PlantMutateSeedless + effect: !type:PlantChangeStat + targetValue: Seedless - name: ChangeLigneous baseOdds: 0.036 persists: false - effect: !type:PlantMutateLigneous + effect: !type:PlantChangeStat + targetValue: Ligneous - name: ChangeTurnIntoKudzu baseOdds: 0.036 persists: false - effect: !type:PlantMutateKudzu + effect: !type:PlantChangeStat + targetValue: TurnIntoKudzu - name: ChangeScreaming baseOdds: 0.036 persists: false - effect: !type:PlantMutateScream + effect: !type:PlantChangeStat + targetValue: CanScream - name: ChangeChemicals baseOdds: 0.072 persists: false From 75029e72ee547b3b23da7e33714e9569d4d48526 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Fri, 13 Sep 2024 22:38:03 -0400 Subject: [PATCH 17/19] Missed 1 entry in yml --- Resources/Prototypes/Hydroponics/randomMutations.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index ae23f8a388923a..868c3a67c4c87b 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -17,7 +17,8 @@ effect: !type:PlantSpeciesChange - name: Unviable baseOdds: 0.109 - effect: !type:PlantUnviable + effect: !type:PlantChangeStat + targetValue: Viable - name: ChangeWaterConsumption baseOdds: 0.018 persists: false From 4cda18eed1d8a958fc316e0dd5a622b290ae8559 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Fri, 13 Sep 2024 23:00:17 -0400 Subject: [PATCH 18/19] Unviable is a stat change, don't add it to the mutations list --- Resources/Prototypes/Hydroponics/randomMutations.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/Resources/Prototypes/Hydroponics/randomMutations.yml b/Resources/Prototypes/Hydroponics/randomMutations.yml index 868c3a67c4c87b..50f6845ec32bb3 100644 --- a/Resources/Prototypes/Hydroponics/randomMutations.yml +++ b/Resources/Prototypes/Hydroponics/randomMutations.yml @@ -17,6 +17,7 @@ effect: !type:PlantSpeciesChange - name: Unviable baseOdds: 0.109 + persists: false effect: !type:PlantChangeStat targetValue: Viable - name: ChangeWaterConsumption From 24835b93ad4e8d41b3d67ddb54865ad175b52218 Mon Sep 17 00:00:00 2001 From: PraxisMapper Date: Fri, 13 Sep 2024 23:04:23 -0400 Subject: [PATCH 19/19] Add quick explainer for LINQ line --- Content.Server/Botany/Systems/MutationSystem.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index f4060df6527a81..07a24d19f6badb 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -88,6 +88,9 @@ public SeedData Cross(SeedData a, SeedData b) CrossGasses(ref result.ExudeGasses, a.ExudeGasses); CrossGasses(ref result.ConsumeGasses, a.ConsumeGasses); + // LINQ Explanation + // For the list of mutation effects on both plants, use a 50% chance to pick each one. + // Union all of the chosen mutations into one list, and pick ones with a Distinct (unique) name. result.Mutations = result.Mutations.Where(m => Random(0.5f)).Union(a.Mutations.Where(m => Random(0.5f))).DistinctBy(m => m.Name).ToList(); // Hybrids have a high chance of being seedless. Balances very