diff --git a/Content.Server/Botany/SeedPrototype.cs b/Content.Server/Botany/SeedPrototype.cs index 3d700f2775..82d5b8de10 100644 --- a/Content.Server/Botany/SeedPrototype.cs +++ b/Content.Server/Botany/SeedPrototype.cs @@ -56,9 +56,26 @@ public enum HarvestType : byte [DataDefinition] public partial struct SeedChemQuantity { + /// + /// Minimum amount of chemical that is added to produce, regardless of the potency + /// [DataField("Min")] public int Min; + + /// + /// Maximum amount of chemical that can be produced after taking plant potency into account. + /// [DataField("Max")] public int Max; + + /// + /// When chemicals are added to produce, the potency of the seed is divided with this value. Final chemical amount is the result plus the `Min` value. + /// Example: PotencyDivisor of 20 with seed potency of 55 results in 2.75, 55/20 = 2.75. If minimum is 1 then final result will be 3.75 of that chemical, 55/20+1 = 3.75. + /// [DataField("PotencyDivisor")] public int PotencyDivisor; + + /// + /// Inherent chemical is one that is NOT result of mutation or crossbreeding. These chemicals are removed if species mutation is executed. + /// + [DataField("Inherent")] public bool Inherent = true; } // TODO reduce the number of friends to a reasonable level. Requires ECS-ing things like plant holder component. @@ -293,4 +310,82 @@ public partial class SeedData return newSeed; } + + + /// + /// Handles copying most species defining data from 'other' to this seed while keeping the accumulated mutations intact. + /// + public SeedData SpeciesChange(SeedData other) + { + var newSeed = new SeedData + { + Name = other.Name, + Noun = other.Noun, + DisplayName = other.DisplayName, + Mysterious = other.Mysterious, + + PacketPrototype = other.PacketPrototype, + ProductPrototypes = new List(other.ProductPrototypes), + MutationPrototypes = new List(other.MutationPrototypes), + + Chemicals = new Dictionary(Chemicals), + ConsumeGasses = new Dictionary(ConsumeGasses), + ExudeGasses = new Dictionary(ExudeGasses), + + NutrientConsumption = NutrientConsumption, + WaterConsumption = WaterConsumption, + IdealHeat = IdealHeat, + HeatTolerance = HeatTolerance, + IdealLight = IdealLight, + LightTolerance = LightTolerance, + ToxinsTolerance = ToxinsTolerance, + LowPressureTolerance = LowPressureTolerance, + HighPressureTolerance = HighPressureTolerance, + PestTolerance = PestTolerance, + WeedTolerance = WeedTolerance, + + Endurance = Endurance, + Yield = Yield, + Lifespan = Lifespan, + Maturation = Maturation, + Production = Production, + GrowthStages = other.GrowthStages, + HarvestRepeat = HarvestRepeat, + Potency = Potency, + + 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. + Unique = true, + }; + + // Adding the new chemicals from the new species. + foreach (var otherChem in other.Chemicals) + { + Chemicals.TryAdd(otherChem.Key, otherChem.Value); + } + + // Removing the inherent chemicals from the old species. Leaving mutated/crossbread ones intact. + foreach (var originalChem in Chemicals) + { + if (!other.Chemicals.ContainsKey(originalChem.Key) && originalChem.Value.Inherent) + { + Chemicals.Remove(originalChem.Key); + } + } + + return newSeed; + } } diff --git a/Content.Server/Botany/Systems/MutationSystem.cs b/Content.Server/Botany/Systems/MutationSystem.cs index 13ef8e3781..94a450ebef 100644 --- a/Content.Server/Botany/Systems/MutationSystem.cs +++ b/Content.Server/Botany/Systems/MutationSystem.cs @@ -3,6 +3,7 @@ using Robust.Shared.Random; using Content.Shared.Chemistry.Reagent; using System.Linq; using Content.Shared.Atmos; +using FastAccessors; namespace Content.Server.Botany; @@ -269,6 +270,7 @@ public sealed class MutationSystem : EntitySystem { seedChemQuantity.Min = 1; seedChemQuantity.Max = 1 + amount; + seedChemQuantity.Inherent = false; } int potencyDivisor = (int) Math.Ceiling(100.0f / seedChemQuantity.Max); seedChemQuantity.PotencyDivisor = potencyDivisor; @@ -295,10 +297,7 @@ public sealed class MutationSystem : EntitySystem return; } - var oldSeed = seed.Clone(); - seed = protoSeed.Clone(); - seed.Potency = oldSeed.Potency; - seed.Yield = oldSeed.Yield; + seed = seed.SpeciesChange(protoSeed); } private Color RandomColor(Color color, int bits, int totalbits, float mult) @@ -330,12 +329,14 @@ public sealed class MutationSystem : EntitySystem { val[otherChem.Key] = Random(0.5f) ? otherChem.Value : val[otherChem.Key]; } - // if target plant doesn't have this chemical, has 50% chance to add it. + // if target plant doesn't have this chemical, has 50% chance to add it. else { if (Random(0.5f)) { - val.Add(otherChem.Key, otherChem.Value); + var fixedChem = otherChem.Value; + fixedChem.Inherent = false; + val.Add(otherChem.Key, fixedChem); } } }