-using System.ComponentModel;
using Content.Server.Botany.Components;
using Content.Server.Botany.Systems;
using Content.Shared.Atmos;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Utility;
+using Robust.Shared.Audio;
namespace Content.Server.Botany;
-
-
[Prototype("seed")]
public sealed class SeedPrototype : SeedData, IPrototype
{
[DataField("weedTolerance")] public float WeedTolerance = 5f;
+ [DataField("weedHighLevelThreshold")] public float WeedHighLevelThreshold = 10f;
+
#endregion
#region General traits
[DataField("maturation")] public float Maturation;
[DataField("production")] public float Production;
[DataField("growthStages")] public int GrowthStages = 6;
+
+ [ViewVariables(VVAccess.ReadWrite)]
[DataField("harvestRepeat")] public HarvestType HarvestRepeat = HarvestType.NoRepeat;
[DataField("potency")] public float Potency = 1f;
[DataField("plantIconState")] public string PlantIconState { get; set; } = "produce";
- [DataField("bioluminescent")] public bool Bioluminescent;
+ [DataField("screamSound")]
+ public SoundSpecifier ScreamSound = new SoundPathSpecifier("/Audio/Voice/Human/malescream_1.ogg");
+
+ [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<EntityPrototype>))] public string KudzuPrototype = "WeakKudzu";
+
+ [DataField("turnIntoKudzu")] public bool TurnIntoKudzu;
[DataField("splatPrototype")] public string? SplatPrototype { get; set; }
#endregion
PlantRsi = PlantRsi,
PlantIconState = PlantIconState,
Bioluminescent = Bioluminescent,
+ CanScream = CanScream,
+ TurnIntoKudzu = TurnIntoKudzu,
BioluminescentColor = BioluminescentColor,
SplatPrototype = SplatPrototype,
using Content.Server.Botany.Components;
-using Content.Shared.Chemistry.Components;
using Content.Shared.FixedPoint;
using Robust.Server.GameObjects;
sprite.LayerSetState(0, seed.PlantIconState);
}
- Solution.ReagentQuantity[] reagents = new Solution.ReagentQuantity[seed.Chemicals.Count];
- int i = 0;
+ var solutionContainer = _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName);
+
+ solutionContainer.RemoveAllSolution();
foreach (var (chem, quantity) in seed.Chemicals)
{
var amount = FixedPoint2.New(quantity.Min);
if (quantity.PotencyDivisor > 0 && seed.Potency > 0)
amount += FixedPoint2.New(seed.Potency / quantity.PotencyDivisor);
amount = FixedPoint2.New((int) MathHelper.Clamp(amount.Float(), quantity.Min, quantity.Max));
- reagents[i++] = new(chem, amount);
+ solutionContainer.MaxVolume += amount;
+ solutionContainer.AddReagent(chem, amount);
}
-
- _solutionContainerSystem.EnsureSolution(uid, produce.SolutionName, reagents);
}
}
public void MutateSeed(SeedData seed, float severity)
{
// Add up everything in the bits column and put the number here.
- const int totalbits = 215;
+ const int totalbits = 245;
// Tolerances (55)
MutateFloat(ref seed.NutrientConsumption , 0.05f , 1.2f , 5 , totalbits , severity);
// Kill the plant (30)
MutateBool(ref seed.Viable , false , 30 , totalbits , severity);
- // Fun (70)
+ // Fun (90)
MutateBool(ref seed.Seedless , true , 10 , totalbits , severity);
MutateBool(ref seed.Slip , true , 10 , totalbits , severity);
MutateBool(ref seed.Sentient , true , 10 , 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);
+ // ConstantUpgade (10)
+ MutateHarvestType(ref seed.HarvestRepeat , 10 , totalbits , severity);
}
public SeedData Cross(SeedData a, SeedData b)
CrossBool(ref result.Sentient, a.Sentient);
CrossBool(ref result.Ligneous, a.Ligneous);
CrossBool(ref result.Bioluminescent, a.Bioluminescent);
+ CrossBool(ref result.TurnIntoKudzu, a.TurnIntoKudzu);
+ CrossBool(ref result.CanScream, a.CanScream);
result.BioluminescentColor = random(0.5f) ? a.BioluminescentColor : result.BioluminescentColor;
// Hybrids have a high chance of being seedless. Balances very
val = polarity;
}
+ private void MutateHarvestType(ref HarvestType val, int bits, int totalbits, float mult)
+ {
+ float p = mult * bits/totalbits;
+ if (!random(p))
+ return;
+
+ if (val == HarvestType.NoRepeat)
+ val = HarvestType.Repeat;
+
+ else if (val == HarvestType.Repeat)
+ val = HarvestType.SelfHarvest;
+ }
+
private Color RandomColor(Color color, int bits, int totalbits, float mult)
{
float p = mult*bits/totalbits;
using Robust.Shared.Audio;
using Robust.Shared.Prototypes;
using Robust.Shared.Random;
+using Content.Server.Coordinates.Helpers;
namespace Content.Server.Botany.Systems
{
[Dependency] private readonly IPrototypeManager _prototype = default!;
[Dependency] private readonly MutationSystem _mutation = default!;
[Dependency] private readonly AppearanceSystem _appearance = default!;
- [Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly PopupSystem _popupSystem = default!;
[Dependency] private readonly IGameTiming _gameTiming = default!;
[Dependency] private readonly TagSystem _tagSystem = default!;
{
var displayName = Loc.GetString(component.Seed.DisplayName);
args.PushMarkup(Loc.GetString("plant-holder-component-something-already-growing-message",
- ("seedName", displayName),
- ("toBeForm", displayName.EndsWith('s') ? "are" : "is")));
+ ("seedName", displayName),
+ ("toBeForm", displayName.EndsWith('s') ? "are" : "is")));
if (component.Health <= component.Seed.Endurance / 2)
{
if (component.Seed == null)
{
if (!_botanySystem.TryGetSeed(seeds, out var seed))
- return ;
+ return;
var name = Loc.GetString(seed.Name);
var noun = Loc.GetString(seed.Noun);
_audio.PlayPvs(spray.SpraySound, args.Used, AudioParams.Default.WithVariation(0.125f));
- var split =_solutionSystem.Drain(solutionEntity, solution, amount);
+ var split = _solutionSystem.Drain(solutionEntity, solution, amount);
if (split.Volume == 0)
{
("owner", uid),
("amount", split.Volume)), args.User, PopupType.Medium);
- _solutionSystem.TryAddSolution(targetEntity, targetSolution, split);
+ _solutionSystem.TryAddSolution(targetEntity, targetSolution, split);
ForceUpdateByExternalCause(uid, component);
("seedName", displayName)), args.User);
component.Health -= (_random.Next(3, 5) * 10);
+ if (component.Seed != null && component.Seed.CanScream)
+ {
+ _audio.PlayPvs(component.Seed.ScreamSound, uid, AudioParams.Default.WithVolume(-2));
+ }
+
if (_random.Prob(0.3f))
component.Sampled = true;
if (_solutionSystem.TryGetSolution(args.Used, produce.SolutionName, out var solution2))
{
// This deliberately discards overfill.
- _solutionSystem.TryAddSolution(args.Used, solution2,
- _solutionSystem.SplitSolution(args.Used, solution2, solution2.Volume));
+ _solutionSystem.TryAddSolution(args.Used, solution2,
+ _solutionSystem.SplitSolution(args.Used, solution2, solution2.Volume));
ForceUpdateByExternalCause(uid, component);
}
// TODO
}
+
public void Update(EntityUid uid, PlantHolderComponent? component = null)
{
if (!Resolve(uid, ref component))
}
// Weeds like water and nutrients! They may appear even if there's not a seed planted.
- if (component.WaterLevel > 10 && component.NutritionLevel > 2 && _random.Prob(component.Seed == null ? 0.05f : 0.01f))
+ if (component.WaterLevel > 10 && component.NutritionLevel > 2)
{
- component.WeedLevel += 1 * HydroponicsSpeedMultiplier * component.WeedCoefficient;
+ var chance = 0f;
+ if (component.Seed == null)
+ chance = 0.05f;
+ else if (component.Seed.TurnIntoKudzu)
+ chance = 1f;
+ else
+ chance = 0.01f;
+
+ if (_random.Prob(chance))
+ component.WeedLevel += 1 + HydroponicsSpeedMultiplier * component.WeedCoefficient;
if (component.DrawWarnings)
component.UpdateSpriteAfterUpdate = true;
}
+ if (component.Seed != null && component.Seed.TurnIntoKudzu
+ && component.WeedLevel >= component.Seed.WeedHighLevelThreshold)
+ {
+ Spawn(component.Seed.KudzuPrototype, Transform(uid).Coordinates.SnapToGrid(EntityManager));
+ component.Seed.TurnIntoKudzu = false;
+ component.Health = 0;
+ }
+
// There's a chance for a weed explosion to happen if weeds take over.
// Plants that are themselves weeds (WeedTolerance > 8) are unaffected.
if (component.WeedLevel >= 10 && _random.Prob(0.1f))
if (!component.Seed.Viable)
{
AffectGrowth(uid, -1, component);
- component.Health -= 6*healthMod;
+ component.Health -= 6 * healthMod;
}
// Make sure the plant is not starving.
if (component.DrawWarnings)
component.UpdateSpriteAfterUpdate = true;
}
+
var environment = _atmosphere.GetContainingMixture(uid, true, true) ?? GasMixture.SpaceGas;
if (component.Seed.ConsumeGasses.Count > 0)
component.Harvest = false;
component.LastProduce = component.Age;
+ if (component.Seed != null && component.Seed.CanScream)
+ _audio.PlayPvs(component.Seed.ScreamSound, uid, AudioParams.Default.WithVolume(-2));
+
if (component.Seed?.HarvestRepeat == HarvestType.NoRepeat)
RemovePlant(uid, component);
{
if (component.DrawWarnings)
{
- _appearance.SetData(uid, PlantHolderVisuals.HealthLight,
- component.Health <= component.Seed.Endurance / 2f);
+ _appearance.SetData(uid, PlantHolderVisuals.HealthLight, component.Health <= component.Seed.Endurance / 2f);
}
if (component.Dead)
walkSpeedModifier: 0.2
sprintSpeedModifier: 0.2
+- type: entity
+ id: WeakKudzu
+ parent: Kudzu
+ components:
+ - type: Spreader
+ growthResult: WeakKudzu
+ chance: 0.3
+
- type: entity
id: FleshKudzu
name: tendons