diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 3875f51b9e..1936b28a5c 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -17,6 +17,7 @@ using Content.Server.MobState; using Content.Shared.Chemistry.Components; using Content.Server.Fluids.EntitySystems; using Content.Server.Chat.Systems; +using Content.Server.Construction; using Content.Server.Construction.Components; using Content.Server.Materials; using Content.Server.Stack; @@ -31,7 +32,6 @@ using Robust.Shared.Configuration; using Robust.Shared.Containers; using Robust.Shared.Physics.Components; - namespace Content.Server.Cloning.Systems { public sealed class CloningSystem : EntitySystem @@ -48,6 +48,7 @@ namespace Content.Server.Cloning.Systems [Dependency] private readonly IRobustRandom _robustRandom = default!; [Dependency] private readonly AtmosphereSystem _atmosphereSystem = default!; [Dependency] private readonly TransformSystem _transformSystem = default!; + [Dependency] private readonly SharedAppearanceSystem _appearance = default!; [Dependency] private readonly SharedStackSystem _stackSystem = default!; [Dependency] private readonly StackSystem _serverStackSystem = default!; [Dependency] private readonly SpillableSystem _spillableSystem = default!; @@ -63,6 +64,7 @@ namespace Content.Server.Cloning.Systems base.Initialize(); SubscribeLocalEvent(OnComponentInit); + SubscribeLocalEvent(OnPartsRefreshed); SubscribeLocalEvent(OnDeconstruct); SubscribeLocalEvent(Reset); SubscribeLocalEvent(HandleMindAdded); @@ -77,17 +79,20 @@ namespace Content.Server.Cloning.Systems _signalSystem.EnsureReceiverPorts(uid, CloningPodComponent.PodPort); } + private void OnPartsRefreshed(EntityUid uid, CloningPodComponent component, RefreshPartsEvent args) + { + var materialRating = args.PartRatings[component.MachinePartMaterialUse]; + var speedRating = args.PartRatings[component.MachinePartCloningSpeed]; + + component.BiomassRequirementMultiplier = MathF.Pow(component.PartRatingMaterialMultiplier, materialRating - 1); + component.CloningTime = component.BaseCloningTime * MathF.Pow(component.PartRatingSpeedMultiplier, speedRating - 1); + } + private void OnDeconstruct(EntityUid uid, CloningPodComponent component, MachineDeconstructedEvent args) { _serverStackSystem.SpawnMultiple(_material.GetMaterialAmount(uid, "Biomass"), 100, "Biomass", Transform(uid).Coordinates); } - private void UpdateAppearance(CloningPodComponent clonePod) - { - if (TryComp(clonePod.Owner, out var appearance)) - appearance.SetData(CloningPodVisuals.Status, clonePod.Status); - } - internal void TransferMindToClone(Mind.Mind mind) { if (!ClonesWaitingForMind.TryGetValue(mind, out var entity) || @@ -106,7 +111,7 @@ namespace Content.Server.Cloning.Systems if (clonedComponent.Parent == EntityUid.Invalid || !EntityManager.EntityExists(clonedComponent.Parent) || !TryComp(clonedComponent.Parent, out var cloningPodComponent) || - clonedComponent.Owner != cloningPodComponent.BodyContainer?.ContainedEntity) + clonedComponent.Owner != cloningPodComponent.BodyContainer.ContainedEntity) { EntityManager.RemoveComponent(clonedComponent.Owner); return; @@ -142,7 +147,7 @@ namespace Content.Server.Cloning.Systems public bool TryCloning(EntityUid uid, EntityUid bodyToClone, Mind.Mind mind, CloningPodComponent? clonePod) { - if (!Resolve(uid, ref clonePod) || bodyToClone == null) + if (!Resolve(uid, ref clonePod)) return false; if (HasComp(uid)) @@ -175,7 +180,7 @@ namespace Content.Server.Cloning.Systems if (!TryComp(bodyToClone, out var physics)) return false; - int cloningCost = (int) physics.FixturesMass; + var cloningCost = (int) Math.Round(physics.FixturesMass * clonePod.BiomassRequirementMultiplier); if (_configManager.GetCVar(CCVars.BiomassEasyMode)) cloningCost = (int) Math.Round(cloningCost * EasyModeCloningCost); @@ -221,7 +226,6 @@ namespace Content.Server.Cloning.Systems cloneMindReturn.Mind = mind; cloneMindReturn.Parent = clonePod.Owner; clonePod.BodyContainer.Insert(mob); - clonePod.CapturedMind = mind; ClonesWaitingForMind.Add(mind, mob); UpdateStatus(CloningPodStatus.NoMind, clonePod); _euiManager.OpenEui(new AcceptCloningEui(mind, this), client); @@ -235,7 +239,7 @@ namespace Content.Server.Cloning.Systems { foreach (var special in mind.CurrentJob.Prototype.Special) { - if (special.GetType() == typeof(AddComponentSpecial)) + if (special is AddComponentSpecial) special.AfterEquip(mob); } } @@ -246,7 +250,7 @@ namespace Content.Server.Cloning.Systems public void UpdateStatus(CloningPodStatus status, CloningPodComponent cloningPod) { cloningPod.Status = status; - UpdateAppearance(cloningPod); + _appearance.SetData(cloningPod.Owner, CloningPodVisuals.Status, cloningPod.Status); } public override void Update(float frameTime) @@ -280,7 +284,6 @@ namespace Content.Server.Cloning.Systems EntityManager.RemoveComponent(entity); clonePod.BodyContainer.Remove(entity); - clonePod.CapturedMind = null; clonePod.CloningProgress = 0f; clonePod.UsedBiomass = 0; UpdateStatus(CloningPodStatus.Idle, clonePod); diff --git a/Content.Server/Cloning/Components/CloningPodComponent.cs b/Content.Server/Cloning/Components/CloningPodComponent.cs index 8c8fe37ef2..7e7ccbcfb1 100644 --- a/Content.Server/Cloning/Components/CloningPodComponent.cs +++ b/Content.Server/Cloning/Components/CloningPodComponent.cs @@ -1,5 +1,7 @@ using Content.Shared.Cloning; +using Content.Shared.Construction.Prototypes; using Robust.Shared.Containers; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; namespace Content.Server.Cloning.Components { @@ -7,14 +9,69 @@ namespace Content.Server.Cloning.Components public sealed class CloningPodComponent : Component { public const string PodPort = "CloningPodReceiver"; - [ViewVariables] public ContainerSlot BodyContainer = default!; - [ViewVariables] public Mind.Mind? CapturedMind; - [ViewVariables] public float CloningProgress = 0; - [ViewVariables] public int UsedBiomass = 70; - [ViewVariables] public bool FailedClone = false; - [DataField("cloningTime")] - [ViewVariables] public float CloningTime = 30f; - [ViewVariables] public CloningPodStatus Status; + + [ViewVariables] + public ContainerSlot BodyContainer = default!; + + /// + /// How long the cloning has been going on for. + /// + [ViewVariables] + public float CloningProgress = 0; + + [ViewVariables] + public int UsedBiomass = 70; + + [ViewVariables] + public bool FailedClone = false; + + /// + /// The base amount of time it takes to clone a body + /// + [DataField("baseCloningTime")] + public float BaseCloningTime = 30f; + + /// + /// The multiplier for cloning duration + /// + [DataField("partRatingSpeedMultiplier")] + public float PartRatingSpeedMultiplier = 0.75f; + + /// + /// The machine part that affects cloning speed + /// + [DataField("machinePartCloningSpeed", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartCloningSpeed = "ScanningModule"; + + /// + /// The current amount of time it takes to clone a body + /// + [ViewVariables(VVAccess.ReadWrite)] + public float CloningTime = 30f; + + /// + /// The machine part that affects how much biomass is needed to clone a body. + /// + [DataField("partRatingMaterialMultiplier")] + public float PartRatingMaterialMultiplier = 0.85f; + + /// + /// The current multiplier on the body weight, which determines the + /// amount of biomass needed to clone. + /// + [ViewVariables(VVAccess.ReadWrite)] + public float BiomassRequirementMultiplier = 1; + + /// + /// The machine part that decreases the amount of material needed for cloning + /// + [DataField("machinePartMaterialUse", customTypeSerializer: typeof(PrototypeIdSerializer))] + public string MachinePartMaterialUse = "Manipulator"; + + [ViewVariables(VVAccess.ReadWrite)] + public CloningPodStatus Status; + + [ViewVariables] public EntityUid? ConnectedConsole; } }