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);
}
}
}