From 6c46fe53078dba1b719c412d8c14d4ccd3367bcd Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Tue, 18 Mar 2025 06:21:56 +0100 Subject: [PATCH] Paradox Clones receive the implants the original has (#35906) * copy implants to paradox clones * Minor fixes --------- Co-authored-by: beck-thompson --- Content.Server/Cloning/CloningSystem.cs | 43 ++++++++++++++++++- .../Cloning/CloningSettingsPrototype.cs | 12 ++++++ .../Prototypes/Entities/Mobs/Player/clone.yml | 2 + 3 files changed, 56 insertions(+), 1 deletion(-) diff --git a/Content.Server/Cloning/CloningSystem.cs b/Content.Server/Cloning/CloningSystem.cs index 9a77c75f64..b8aff813d2 100644 --- a/Content.Server/Cloning/CloningSystem.cs +++ b/Content.Server/Cloning/CloningSystem.cs @@ -5,6 +5,8 @@ using Content.Shared.Cloning.Events; using Content.Shared.Database; using Content.Shared.Humanoid; using Content.Shared.Inventory; +using Content.Shared.Implants; +using Content.Shared.Implants.Components; using Content.Shared.NameModifier.Components; using Content.Shared.StatusEffect; using Content.Shared.Stacks; @@ -35,6 +37,7 @@ public sealed class CloningSystem : EntitySystem [Dependency] private readonly SharedContainerSystem _container = default!; [Dependency] private readonly SharedStorageSystem _storage = default!; [Dependency] private readonly SharedStackSystem _stack = default!; + [Dependency] private readonly SharedSubdermalImplantSystem _subdermalImplant = default!; /// /// Spawns a clone of the given humanoid mob at the specified location or in nullspace. @@ -90,7 +93,12 @@ public sealed class CloningSystem : EntitySystem // Copy storage on the mob itself as well. // This is needed for slime storage. - CopyStorage(original, clone.Value, settings.Whitelist, settings.Blacklist); + if (settings.CopyInternalStorage) + CopyStorage(original, clone.Value, settings.Whitelist, settings.Blacklist); + + // copy implants and their storage contents + if (settings.CopyImplants) + CopyImplants(original, clone.Value, settings.CopyInternalStorage, settings.Whitelist, settings.Blacklist); var originalName = Name(original); if (TryComp(original, out var nameModComp)) // if the originals name was modified, use the unmodified name @@ -196,4 +204,37 @@ public sealed class CloningSystem : EntitySystem _storage.InsertAt(target, copy.Value, itemLocation, out _, playSound: false); } } + + /// + /// Copies all implants from one mob to another. + /// Might result in duplicates if the target already has them. + /// Can copy the storage inside a storage implant according to a whitelist and blacklist. + /// + /// Entity to copy implants from. + /// Entity to copy implants to. + /// If true will copy storage of the implants (E.g storage implant) + /// Whitelist for the storage copy (If copyStorage is true) + /// Blacklist for the storage copy (If copyStorage is true) + public void CopyImplants(Entity original, EntityUid target, bool copyStorage = false, EntityWhitelist? whitelist = null, EntityWhitelist? blacklist = null) + { + if (!Resolve(original, ref original.Comp, false)) + return; // they don't have any implants to copy! + + foreach (var originalImplant in original.Comp.ImplantContainer.ContainedEntities) + { + if (!HasComp(originalImplant)) + continue; // not an implant (should only happen with admin shenanigans) + + var implantId = MetaData(originalImplant).EntityPrototype?.ID; + + if (implantId == null) + continue; + + var targetImplant = _subdermalImplant.AddImplant(target, implantId); + + if (copyStorage && targetImplant != null) + CopyStorage(originalImplant, targetImplant.Value, whitelist, blacklist); // only needed for storage implants + } + + } } diff --git a/Content.Shared/Cloning/CloningSettingsPrototype.cs b/Content.Shared/Cloning/CloningSettingsPrototype.cs index fa5f4a35d7..b5cfc0500d 100644 --- a/Content.Shared/Cloning/CloningSettingsPrototype.cs +++ b/Content.Shared/Cloning/CloningSettingsPrototype.cs @@ -36,6 +36,18 @@ public sealed partial class CloningSettingsPrototype : IPrototype, IInheritingPr [DataField] public SlotFlags? CopyEquipment = SlotFlags.All; + /// + /// Whether or not to copy slime storage and storage implant contents. + /// + [DataField] + public bool CopyInternalStorage = true; + + /// + /// Whether or not to copy implants. + /// + [DataField] + public bool CopyImplants = true; + /// /// Whitelist for the equipment allowed to be copied. /// diff --git a/Resources/Prototypes/Entities/Mobs/Player/clone.yml b/Resources/Prototypes/Entities/Mobs/Player/clone.yml index 8208c30095..38040f7cdf 100644 --- a/Resources/Prototypes/Entities/Mobs/Player/clone.yml +++ b/Resources/Prototypes/Entities/Mobs/Player/clone.yml @@ -73,6 +73,8 @@ parent: Antag forceCloning: false copyEquipment: null + copyInternalStorage: false + copyImplants: false # spawner