diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs index 25378bb3ede..61d36f98b96 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerComponent.cs @@ -15,7 +15,7 @@ public sealed partial class BiomassReclaimerComponent : Component /// /// The interval for . /// - [ViewVariables(VVAccess.ReadWrite), DataField("randomMessInterval")] + [ViewVariables(VVAccess.ReadWrite), DataField] public TimeSpan RandomMessInterval = TimeSpan.FromSeconds(5); /// @@ -28,9 +28,10 @@ public sealed partial class BiomassReclaimerComponent : Component /// /// Amount of biomass that the mob being processed will yield. /// This is calculated from the YieldPerUnitMass. + /// Also stores non-integer leftovers. /// [ViewVariables] - public int CurrentExpectedYield = default; + public float CurrentExpectedYield = 0f; /// /// The reagent that will be spilled while processing a mob. @@ -49,6 +50,18 @@ public sealed partial class BiomassReclaimerComponent : Component [DataField, ViewVariables(VVAccess.ReadWrite)] public float YieldPerUnitMass = 0.4f; + /// + /// How many seconds to take to insert an entity per unit of its mass. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float BaseInsertionDelay = 0.1f; + + /// + /// How much to multiply biomass yield from botany produce. + /// + [DataField, ViewVariables(VVAccess.ReadWrite)] + public float ProduceYieldMultiplier = 0.25f; + /// /// The time it takes to process a mob, per mass. /// @@ -58,7 +71,7 @@ public sealed partial class BiomassReclaimerComponent : Component /// /// Will this refuse to gib a living mob? /// - [ViewVariables(VVAccess.ReadWrite), DataField("safetyEnabled")] + [ViewVariables(VVAccess.ReadWrite), DataField] public bool SafetyEnabled = true; } } diff --git a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs index b126c74a10a..d07858aec5c 100644 --- a/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs +++ b/Content.Server/Medical/BiomassReclaimer/BiomassReclaimerSystem.cs @@ -1,5 +1,6 @@ using System.Numerics; using Content.Server.Body.Components; +using Content.Server.Botany.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Materials; using Content.Server.Power.Components; @@ -17,6 +18,7 @@ using Content.Shared.Jittering; using Content.Shared.Medical; using Content.Shared.Mind; +using Content.Shared.Materials; using Content.Shared.Mobs.Components; using Content.Shared.Mobs.Systems; using Content.Shared.Nutrition.Components; @@ -26,6 +28,7 @@ using Robust.Shared.Audio.Systems; using Robust.Shared.Configuration; using Robust.Shared.Physics.Components; +using Robust.Shared.Prototypes; using Robust.Shared.Random; namespace Content.Server.Medical.BiomassReclaimer @@ -47,6 +50,9 @@ public sealed class BiomassReclaimerSystem : EntitySystem [Dependency] private readonly MaterialStorageSystem _material = default!; [Dependency] private readonly SharedMindSystem _minds = default!; + [ValidatePrototypeId] + public const string BiomassPrototype = "Biomass"; + public override void Update(float frameTime) { base.Update(frameTime); @@ -79,7 +85,9 @@ public override void Update(float frameTime) continue; } - _material.SpawnMultipleFromMaterial(reclaimer.CurrentExpectedYield, "Biomass", Transform(uid).Coordinates); + var actualYield = (int) (reclaimer.CurrentExpectedYield); // can only have integer biomass + reclaimer.CurrentExpectedYield = reclaimer.CurrentExpectedYield - actualYield; // store non-integer leftovers + _material.SpawnMultipleFromMaterial(actualYield, BiomassPrototype, Transform(uid).Coordinates); reclaimer.BloodReagent = null; reclaimer.SpawnedEntities.Clear(); @@ -148,10 +156,14 @@ private void OnAfterInteractUsing(Entity reclaimer, r if (!args.CanReach || args.Target == null) return; - if (!HasComp(args.Used) || !CanGib(reclaimer, args.Used)) + if (!CanGib(reclaimer, args.Used)) + return; + + if (!TryComp(args.Used, out var physics)) return; - _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, 7f, new ReclaimerDoAfterEvent(), reclaimer, target: args.Target, used: args.Used) + var delay = reclaimer.Comp.BaseInsertionDelay * physics.FixturesMass; + _doAfterSystem.TryStartDoAfter(new DoAfterArgs(EntityManager, args.User, delay, new ReclaimerDoAfterEvent(), reclaimer, target: args.Target, used: args.Used) { BreakOnTargetMove = true, BreakOnUserMove = true, @@ -174,11 +186,14 @@ private void OnClimbedOn(Entity reclaimer, ref Climbe private void OnDoAfter(Entity reclaimer, ref ReclaimerDoAfterEvent args) { - if (args.Handled || args.Cancelled || args.Args.Target == null || HasComp(args.Args.Target.Value)) + if (args.Handled || args.Cancelled) + return; + + if (args.Args.Used == null || args.Args.Target == null || !HasComp(args.Args.Target.Value)) return; _adminLogger.Add(LogType.Action, LogImpact.Extreme, $"{ToPrettyString(args.Args.User):player} used a biomass reclaimer to gib {ToPrettyString(args.Args.Target.Value):target} in {ToPrettyString(reclaimer):reclaimer}"); - StartProcessing(args.Args.Target.Value, reclaimer); + StartProcessing(args.Args.Used.Value, reclaimer); args.Handled = true; } @@ -200,8 +215,13 @@ private void StartProcessing(EntityUid toProcess, Entity(toProcess)) + expectedYield *= component.ProduceYieldMultiplier; + component.CurrentExpectedYield += expectedYield; + component.ProcessingTimer = physics.FixturesMass * component.ProcessingTimePerUnitMass; + QueueDel(toProcess); } @@ -210,7 +230,8 @@ private bool CanGib(Entity reclaimer, EntityUid dragg if (HasComp(reclaimer)) return false; - if (!HasComp(dragged)) + bool isPlant = HasComp(dragged); + if (!isPlant && !HasComp(dragged)) return false; if (!Transform(reclaimer).Anchored) @@ -219,7 +240,7 @@ private bool CanGib(Entity reclaimer, EntityUid dragg if (TryComp(reclaimer, out var power) && !power.Powered) return false; - if (reclaimer.Comp.SafetyEnabled && !_mobState.IsDead(dragged)) + if (!isPlant && reclaimer.Comp.SafetyEnabled && !_mobState.IsDead(dragged)) return false; // Reject souled bodies in easy mode.