using Content.Shared.Botany.Components; using Content.Shared.Cloning.Events; using Content.Shared.Damage.Systems; using JetBrains.Annotations; using Robust.Shared.Serialization.Manager; using Robust.Shared.Prototypes; namespace Content.Shared.Botany.Systems; /// /// API for runtime plant lifecycle state. /// public sealed partial class PlantHolderSystem : EntitySystem { [Dependency] private ISerializationManager _serialization = default!; [Dependency] private EntityQuery _plantQuery; public override void Initialize() { base.Initialize(); InitializeRelay(); } [SubscribeLocalEvent] private void OnCloning(Entity ent, ref CloningEvent args) { if (!args.Settings.EventComponents.Contains(Factory.GetRegistration(ent.Comp.GetType()).Name)) return; var cloneComp = EnsureComp(args.CloneUid); _serialization.CopyTo(ent.Comp, ref cloneComp, notNullableOverride: true); Dirty(args.CloneUid, cloneComp); } [SubscribeLocalEvent] private void OnDamageDealt(Entity ent, ref DamageDealtEvent args) { AdjustsHealth(ent.AsNullable(), -args.Damage.GetTotal().Float()); } /// /// Adjusts the health of the plant. /// [PublicAPI] public void AdjustsHealth(Entity ent, float amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; if (!_plantQuery.TryComp(ent.Owner, out var plant)) return; ent.Comp.Health += amount; ent.Comp.Health = MathHelper.Clamp(ent.Comp.Health, 0f, plant.Endurance); DirtyField(ent, nameof(ent.Comp.Health)); CheckHealth(ent); } /// /// Adjusts the mutation level of the plant. /// [PublicAPI] public void AdjustsMutationLevel(Entity ent, ProtoId mutationTableId, float amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; var mutationTable = ProtoMan.Index(mutationTableId); var current = ent.Comp.MutationLevels.GetValueOrDefault(mutationTableId); var adjustmentAmount = mutationTable.IgnoreMutationMod ? amount : amount * ent.Comp.MutationMod; ent.Comp.MutationLevels[mutationTableId] = MathHelper.Clamp(current + adjustmentAmount, 0f, ent.Comp.MaxMutationLevel); DirtyField(ent, nameof(ent.Comp.MutationLevels)); CheckHealth(ent); } /// /// Adjusts the mutation mod of the plant. /// [PublicAPI] public void AdjustsMutationMod(Entity ent, float amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; ent.Comp.MutationMod += amount; ent.Comp.MutationMod = MathHelper.Clamp(ent.Comp.MutationMod, 0f, ent.Comp.MaxMutationMod); DirtyField(ent, nameof(ent.Comp.MutationMod)); } /// /// Adjusts the age of the plant. /// [PublicAPI] public void AdjustsAge(Entity ent, int amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; ent.Comp.Age = Math.Max(0, ent.Comp.Age + amount); DirtyField(ent, nameof(ent.Comp.Age)); } /// /// Adjusts the yield mod of the plant. /// [PublicAPI] public void AdjustsYieldMod(Entity ent, int amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; ent.Comp.YieldMod += amount; ent.Comp.YieldMod = MathHelper.Clamp(ent.Comp.YieldMod, 1, ent.Comp.MaxYieldMod); DirtyField(ent, nameof(ent.Comp.YieldMod)); } /// /// Adjusts the skip aging of the plant. /// [PublicAPI] public void AdjustsSkipAging(Entity ent, int amount) { if (!Resolve(ent.Owner, ref ent.Comp)) return; ent.Comp.SkipAging = Math.Max(0, ent.Comp.SkipAging + amount); DirtyField(ent, nameof(ent.Comp.SkipAging)); } /// /// Checks if the plant is dead. /// [PublicAPI] public bool IsDead(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp)) return false; return ent.Comp.Dead; } /// /// Checks if the plant is dead. /// [PublicAPI] public void CheckHealth(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp)) return; if (ent.Comp.Health <= 0) KillPlant(ent); } /// /// Kills the plant. /// [PublicAPI] public void KillPlant(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp)) return; ent.Comp.Dead = true; ent.Comp.Health = Math.Max(0, ent.Comp.Health); DirtyFields(ent, null, nameof(ent.Comp.Dead), nameof(ent.Comp.Health)); } /// /// Checks whether the plant's health is at or below half its endurance. /// [PublicAPI] public bool GetHealthThreshold(Entity ent) { if (!Resolve(ent.Owner, ref ent.Comp, false) || !_plantQuery.TryComp(ent.Owner, out var plant)) return false; return ent.Comp.Health <= plant.Endurance * 0.5f; } }