2022-02-06 13:14:41 -07:00
using Content.Server.Botany.Components ;
using Content.Server.Botany.Systems ;
using Content.Shared.Atmos ;
2022-08-08 01:51:41 -07:00
using Content.Shared.Chemistry.Reagent ;
2022-02-06 13:14:41 -07:00
using Robust.Shared.Prototypes ;
2022-04-16 17:32:35 +12:00
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype ;
2022-02-06 13:14:41 -07:00
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List ;
using Robust.Shared.Utility ;
2023-03-06 04:11:13 +03:00
using Robust.Shared.Audio ;
2022-02-06 13:14:41 -07:00
namespace Content.Server.Botany ;
2022-04-16 17:32:35 +12:00
[Prototype("seed")]
public sealed class SeedPrototype : SeedData , IPrototype
{
[IdDataField] public string ID { get ; private init ; } = default ! ;
}
2022-02-06 13:14:41 -07:00
public enum HarvestType : byte
{
NoRepeat ,
Repeat ,
SelfHarvest
}
/ *
public enum PlantSpread : byte
{
NoSpread ,
Creepers ,
Vines ,
}
public enum PlantMutation : byte
{
NoMutation ,
Mutable ,
HighlyMutable ,
}
public enum PlantCarnivorous : byte
{
NotCarnivorous ,
EatPests ,
EatLivingBeings ,
}
public enum PlantJuicy : byte
{
NotJuicy ,
Juicy ,
Slippery ,
}
* /
[DataDefinition]
2023-08-22 18:14:33 -07:00
public partial struct SeedChemQuantity
2022-02-06 13:14:41 -07:00
{
2023-10-01 20:52:45 +03:00
/// <summary>
/// Minimum amount of chemical that is added to produce, regardless of the potency
/// </summary>
2022-02-06 13:14:41 -07:00
[DataField("Min")] public int Min ;
2023-10-01 20:52:45 +03:00
/// <summary>
/// Maximum amount of chemical that can be produced after taking plant potency into account.
/// </summary>
2022-02-06 13:14:41 -07:00
[DataField("Max")] public int Max ;
2023-10-01 20:52:45 +03:00
/// <summary>
/// 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.
/// </summary>
2022-02-06 13:14:41 -07:00
[DataField("PotencyDivisor")] public int PotencyDivisor ;
2023-10-01 20:52:45 +03:00
/// <summary>
/// Inherent chemical is one that is NOT result of mutation or crossbreeding. These chemicals are removed if species mutation is executed.
/// </summary>
[DataField("Inherent")] public bool Inherent = true ;
2022-02-06 13:14:41 -07:00
}
2022-04-16 17:32:35 +12:00
// TODO reduce the number of friends to a reasonable level. Requires ECS-ing things like plant holder component.
[Virtual, DataDefinition]
2022-10-15 23:25:41 -07:00
[Access(typeof(BotanySystem), typeof(PlantHolderSystem), typeof(SeedExtractorSystem), typeof(PlantHolderComponent), typeof(ReagentEffect), typeof(MutationSystem))]
2023-08-22 18:14:33 -07:00
public partial class SeedData
2022-02-06 13:14:41 -07:00
{
2022-04-16 17:32:35 +12:00
#region Tracking
2022-12-20 23:25:34 +01:00
2022-02-06 13:14:41 -07:00
/// <summary>
2022-04-16 17:32:35 +12:00
/// The name of this seed. Determines the name of seed packets.
2022-02-06 13:14:41 -07:00
/// </summary>
2022-09-26 22:44:28 +03:00
[DataField("name")]
2022-12-20 23:25:34 +01:00
public string Name { get ; private set ; } = "" ;
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
/// <summary>
/// The noun for this type of seeds. E.g. for fungi this should probably be "spores" instead of "seeds". Also
/// used to determine the name of seed packets.
/// </summary>
2022-09-26 22:44:28 +03:00
[DataField("noun")]
2022-12-20 23:25:34 +01:00
public string Noun { get ; private set ; } = "" ;
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
/// <summary>
/// Name displayed when examining the hydroponics tray. Describes the actual plant, not the seed itself.
/// </summary>
2022-09-26 22:44:28 +03:00
[DataField("displayName")]
2022-12-20 23:25:34 +01:00
public string DisplayName { get ; private set ; } = "" ;
2022-02-06 13:14:41 -07:00
[DataField("mysterious")] public bool Mysterious ;
2022-04-16 17:32:35 +12:00
/// <summary>
/// If true, the properties of this seed cannot be modified.
/// </summary>
2022-02-06 13:14:41 -07:00
[DataField("immutable")] public bool Immutable ;
2022-04-16 17:32:35 +12:00
/// <summary>
/// If true, there is only a single reference to this seed and it's properties can be directly modified without
/// needing to clone the seed.
/// </summary>
[ViewVariables]
public bool Unique = false ; // seed-prototypes or yaml-defined seeds for entity prototypes will not generally be unique.
2022-02-06 13:14:41 -07:00
#endregion
#region Output
2022-04-16 17:32:35 +12:00
/// <summary>
/// The entity prototype that is spawned when this type of seed is extracted from produce using a seed extractor.
/// </summary>
[DataField("packetPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))]
public string PacketPrototype = "SeedBase" ;
2022-02-06 13:14:41 -07:00
2022-04-16 17:32:35 +12:00
/// <summary>
/// The entity prototype this seed spawns when it gets harvested.
/// </summary>
2022-02-06 13:14:41 -07:00
[DataField("productPrototypes", customTypeSerializer: typeof(PrototypeIdListSerializer<EntityPrototype>))]
public List < string > ProductPrototypes = new ( ) ;
[DataField("chemicals")] public Dictionary < string , SeedChemQuantity > Chemicals = new ( ) ;
[DataField("consumeGasses")] public Dictionary < Gas , float > ConsumeGasses = new ( ) ;
[DataField("exudeGasses")] public Dictionary < Gas , float > ExudeGasses = new ( ) ;
#endregion
#region Tolerances
2023-08-13 10:10:22 +03:00
[DataField("nutrientConsumption")] public float NutrientConsumption = 0.75f ;
2022-02-06 13:14:41 -07:00
2023-08-08 03:29:59 +03:00
[DataField("waterConsumption")] public float WaterConsumption = 0.5f ;
2022-02-06 13:14:41 -07:00
[DataField("idealHeat")] public float IdealHeat = 293f ;
2022-10-15 23:25:41 -07:00
[DataField("heatTolerance")] public float HeatTolerance = 10f ;
2022-02-06 13:14:41 -07:00
[DataField("idealLight")] public float IdealLight = 7f ;
2022-10-15 23:25:41 -07:00
[DataField("lightTolerance")] public float LightTolerance = 3f ;
2022-02-06 13:14:41 -07:00
[DataField("toxinsTolerance")] public float ToxinsTolerance = 4f ;
2022-10-15 23:25:41 -07:00
[DataField("lowPressureTolerance")] public float LowPressureTolerance = 81f ;
2022-02-06 13:14:41 -07:00
2022-10-15 23:25:41 -07:00
[DataField("highPressureTolerance")] public float HighPressureTolerance = 121f ;
2022-02-06 13:14:41 -07:00
[DataField("pestTolerance")] public float PestTolerance = 5f ;
[DataField("weedTolerance")] public float WeedTolerance = 5f ;
2023-03-06 04:11:13 +03:00
[DataField("weedHighLevelThreshold")] public float WeedHighLevelThreshold = 10f ;
2022-02-06 13:14:41 -07:00
#endregion
#region General traits
[DataField("endurance")] 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 ;
2023-03-06 04:11:13 +03:00
[ViewVariables(VVAccess.ReadWrite)]
2022-02-06 13:14:41 -07:00
[DataField("harvestRepeat")] public HarvestType HarvestRepeat = HarvestType . NoRepeat ;
[DataField("potency")] public float Potency = 1f ;
2022-10-15 23:25:41 -07:00
/// <summary>
/// If true, cannot be harvested for seeds. Balances hybrids and
/// mutations.
/// </summary>
[DataField("seedless")] public bool Seedless = false ;
/// <summary>
2023-09-14 07:56:24 +03:00
/// If false, rapidly decrease health while growing. Used to kill off
2022-10-15 23:25:41 -07:00
/// plants with "bad" mutations.
/// </summary>
[DataField("viable")] public bool Viable = true ;
/// <summary>
/// If true, fruit slips players.
/// </summary>
[DataField("slip")] public bool Slip = false ;
/// <summary>
/// If true, fruits are sentient.
/// </summary>
[DataField("sentient")] public bool Sentient = false ;
2022-04-16 17:32:35 +12:00
/// <summary>
/// If true, a sharp tool is required to harvest this plant.
/// </summary>
[DataField("ligneous")] public bool Ligneous ;
2022-02-06 13:14:41 -07:00
// No, I'm not removing these.
2022-04-16 17:32:35 +12:00
// if you re-add these, make sure that they get cloned.
2022-02-06 13:14:41 -07:00
//public PlantSpread Spread { get; set; }
//public PlantMutation Mutation { get; set; }
//public float AlterTemperature { get; set; }
//public PlantCarnivorous Carnivorous { get; set; }
//public bool Parasite { get; set; }
//public bool Hematophage { get; set; }
//public bool Thorny { get; set; }
//public bool Stinging { get; set; }
// public bool Teleporting { get; set; }
// public PlantJuicy Juicy { get; set; }
#endregion
#region Cosmetics
[DataField("plantRsi", required: true)]
2023-04-20 20:16:01 +10:00
public ResPath PlantRsi { get ; set ; } = default ! ;
2022-02-06 13:14:41 -07:00
[DataField("plantIconState")] public string PlantIconState { get ; set ; } = "produce" ;
2023-03-06 04:11:13 +03:00
[DataField("screamSound")]
public SoundSpecifier ScreamSound = new SoundPathSpecifier ( "/Audio/Voice/Human/malescream_1.ogg" ) ;
2022-02-06 13:14:41 -07:00
2023-03-06 04:11:13 +03:00
[DataField("screaming")] public bool CanScream ;
[DataField("bioluminescent")] public bool Bioluminescent ;
2022-02-06 13:14:41 -07:00
[DataField("bioluminescentColor")] public Color BioluminescentColor { get ; set ; } = Color . White ;
2022-10-15 23:25:41 -07:00
public float BioluminescentRadius = 2f ;
2023-03-06 04:11:13 +03:00
[DataField("kudzuPrototype", customTypeSerializer: typeof(PrototypeIdSerializer<EntityPrototype>))] public string KudzuPrototype = "WeakKudzu" ;
[DataField("turnIntoKudzu")] public bool TurnIntoKudzu ;
2022-02-06 13:14:41 -07:00
[DataField("splatPrototype")] public string? SplatPrototype { get ; set ; }
#endregion
2023-09-14 07:56:24 +03:00
/// <summary>
/// The seed prototypes this seed may mutate into when prompted to.
/// </summary>
[DataField("mutationPrototypes", customTypeSerializer: typeof(PrototypeIdListSerializer<SeedPrototype>))]
public List < string > MutationPrototypes = new ( ) ;
2022-04-16 17:32:35 +12:00
public SeedData Clone ( )
2022-02-06 13:14:41 -07:00
{
2022-04-16 17:32:35 +12:00
DebugTools . Assert ( ! Immutable , "There should be no need to clone an immutable seed." ) ;
var newSeed = new SeedData
2022-02-06 13:14:41 -07:00
{
Name = Name ,
2022-04-16 17:32:35 +12:00
Noun = Noun ,
DisplayName = DisplayName ,
2022-02-06 13:14:41 -07:00
Mysterious = Mysterious ,
2022-04-16 17:32:35 +12:00
PacketPrototype = PacketPrototype ,
2022-02-06 13:14:41 -07:00
ProductPrototypes = new List < string > ( ProductPrototypes ) ,
2023-09-14 07:56:24 +03:00
MutationPrototypes = new List < string > ( MutationPrototypes ) ,
2022-02-06 13:14:41 -07:00
Chemicals = new Dictionary < string , SeedChemQuantity > ( Chemicals ) ,
ConsumeGasses = new Dictionary < Gas , float > ( ConsumeGasses ) ,
ExudeGasses = new Dictionary < Gas , float > ( 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 = GrowthStages ,
HarvestRepeat = HarvestRepeat ,
Potency = Potency ,
2022-10-15 23:25:41 -07:00
Seedless = Seedless ,
Viable = Viable ,
Slip = Slip ,
Sentient = Sentient ,
Ligneous = Ligneous ,
2022-02-06 13:14:41 -07:00
PlantRsi = PlantRsi ,
PlantIconState = PlantIconState ,
Bioluminescent = Bioluminescent ,
2023-03-06 04:11:13 +03:00
CanScream = CanScream ,
TurnIntoKudzu = TurnIntoKudzu ,
2022-02-06 13:14:41 -07:00
BioluminescentColor = BioluminescentColor ,
2022-04-16 17:32:35 +12:00
SplatPrototype = SplatPrototype ,
// Newly cloned seed is unique. No need to unnecessarily clone if repeatedly modified.
Unique = true ,
2022-02-06 13:14:41 -07:00
} ;
return newSeed ;
}
2023-10-01 20:52:45 +03:00
/// <summary>
/// Handles copying most species defining data from 'other' to this seed while keeping the accumulated mutations intact.
/// </summary>
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 < string > ( other . ProductPrototypes ) ,
MutationPrototypes = new List < string > ( other . MutationPrototypes ) ,
Chemicals = new Dictionary < string , SeedChemQuantity > ( Chemicals ) ,
ConsumeGasses = new Dictionary < Gas , float > ( ConsumeGasses ) ,
ExudeGasses = new Dictionary < Gas , float > ( 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 )
{
2023-10-04 02:07:29 +03:00
newSeed . Chemicals . TryAdd ( otherChem . Key , otherChem . Value ) ;
2023-10-01 20:52:45 +03:00
}
// Removing the inherent chemicals from the old species. Leaving mutated/crossbread ones intact.
2023-10-04 02:07:29 +03:00
foreach ( var originalChem in newSeed . Chemicals )
2023-10-01 20:52:45 +03:00
{
if ( ! other . Chemicals . ContainsKey ( originalChem . Key ) & & originalChem . Value . Inherent )
{
2023-10-04 02:07:29 +03:00
newSeed . Chemicals . Remove ( originalChem . Key ) ;
2023-10-01 20:52:45 +03:00
}
}
return newSeed ;
}
2022-02-06 13:14:41 -07:00
}