Improve paradox clone item copying (#35993)
* even better item copying for the paradox clone * copy paper * fix * blacklist implanter * string.Empty --------- Co-authored-by: ScarKy0 <scarky0@onet.eu>
This commit is contained in:
@@ -15,10 +15,18 @@ public sealed class PaperVisualizerSystem : VisualizerSystem<PaperVisualsCompone
|
||||
args.Sprite.LayerSetVisible(PaperVisualLayers.Writing, writingStatus == PaperStatus.Written);
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(uid, PaperVisuals.Stamp, out var stampState, args.Component))
|
||||
{
|
||||
if (stampState != string.Empty)
|
||||
{
|
||||
args.Sprite.LayerSetState(PaperVisualLayers.Stamp, stampState);
|
||||
args.Sprite.LayerSetVisible(PaperVisualLayers.Stamp, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetVisible(PaperVisualLayers.Stamp, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
83
Content.Server/Cloning/CloningSystem.Subscriptions.cs
Normal file
83
Content.Server/Cloning/CloningSystem.Subscriptions.cs
Normal file
@@ -0,0 +1,83 @@
|
||||
using Content.Server.Forensics;
|
||||
using Content.Shared.Cloning.Events;
|
||||
using Content.Shared.Clothing.Components;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Content.Shared.Labels.Components;
|
||||
using Content.Shared.Labels.EntitySystems;
|
||||
using Content.Shared.Paper;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Store;
|
||||
using Content.Shared.Store.Components;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server.Cloning;
|
||||
|
||||
/// <summary>
|
||||
/// The part of item cloning responsible for copying over important components.
|
||||
/// This is used for <see cref="CopyItem"/>.
|
||||
/// Anything not copied over here gets reverted to the values the item had in its prototype.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// This method of copying items is of course not perfect as we cannot clone every single component, which would be pretty much impossible with our ECS.
|
||||
/// We only consider the most important components so the paradox clone gets similar equipment.
|
||||
/// This method of using subscriptions was chosen to make it easy for forks to add their own custom components that need to be copied.
|
||||
/// </remarks>
|
||||
public sealed partial class CloningSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedStackSystem _stack = default!;
|
||||
[Dependency] private readonly SharedLabelSystem _label = default!;
|
||||
[Dependency] private readonly ForensicsSystem _forensics = default!;
|
||||
[Dependency] private readonly PaperSystem _paper = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<StackComponent, CloningItemEvent>(OnCloneStack);
|
||||
SubscribeLocalEvent<LabelComponent, CloningItemEvent>(OnCloneLabel);
|
||||
SubscribeLocalEvent<PaperComponent, CloningItemEvent>(OnClonePaper);
|
||||
SubscribeLocalEvent<ForensicsComponent, CloningItemEvent>(OnCloneForensics);
|
||||
SubscribeLocalEvent<StoreComponent, CloningItemEvent>(OnCloneStore);
|
||||
}
|
||||
|
||||
private void OnCloneStack(Entity<StackComponent> ent, ref CloningItemEvent args)
|
||||
{
|
||||
// if the clone is a stack as well, adjust the count of the copy
|
||||
if (TryComp<StackComponent>(args.CloneUid, out var cloneStackComp))
|
||||
_stack.SetCount(args.CloneUid, ent.Comp.Count, cloneStackComp);
|
||||
}
|
||||
|
||||
private void OnCloneLabel(Entity<LabelComponent> ent, ref CloningItemEvent args)
|
||||
{
|
||||
// copy the label
|
||||
_label.Label(args.CloneUid, ent.Comp.CurrentLabel);
|
||||
}
|
||||
|
||||
private void OnClonePaper(Entity<PaperComponent> ent, ref CloningItemEvent args)
|
||||
{
|
||||
// copy the text and any stamps
|
||||
if (TryComp<PaperComponent>(args.CloneUid, out var clonePaperComp))
|
||||
{
|
||||
_paper.SetContent((args.CloneUid, clonePaperComp), ent.Comp.Content);
|
||||
_paper.CopyStamps(ent.AsNullable(), (args.CloneUid, clonePaperComp));
|
||||
}
|
||||
}
|
||||
|
||||
private void OnCloneForensics(Entity<ForensicsComponent> ent, ref CloningItemEvent args)
|
||||
{
|
||||
// copy any forensics to the cloned item
|
||||
_forensics.CopyForensicsFrom(ent.Comp, args.CloneUid);
|
||||
}
|
||||
|
||||
private void OnCloneStore(Entity<StoreComponent> ent, ref CloningItemEvent args)
|
||||
{
|
||||
// copy the current amount of currency in the store
|
||||
// at the moment this takes care of uplink implants and the portable nukie uplinks
|
||||
// turning a copied pda into an uplink will need some refactoring first
|
||||
if (TryComp<StoreComponent>(args.CloneUid, out var cloneStoreComp))
|
||||
{
|
||||
cloneStoreComp.Balance = new Dictionary<ProtoId<CurrencyPrototype>, FixedPoint2>(ent.Comp.Balance);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,7 +9,6 @@ using Content.Shared.Implants;
|
||||
using Content.Shared.Implants.Components;
|
||||
using Content.Shared.NameModifier.Components;
|
||||
using Content.Shared.StatusEffect;
|
||||
using Content.Shared.Stacks;
|
||||
using Content.Shared.Storage;
|
||||
using Content.Shared.Storage.EntitySystems;
|
||||
using Content.Shared.Whitelist;
|
||||
@@ -25,7 +24,7 @@ namespace Content.Server.Cloning;
|
||||
/// System responsible for making a copy of a humanoid's body.
|
||||
/// For the cloning machines themselves look at CloningPodSystem, CloningConsoleSystem and MedicalScannerSystem instead.
|
||||
/// </summary>
|
||||
public sealed class CloningSystem : EntitySystem
|
||||
public sealed partial class CloningSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IComponentFactory _componentFactory = default!;
|
||||
[Dependency] private readonly HumanoidAppearanceSystem _humanoidSystem = default!;
|
||||
@@ -36,7 +35,6 @@ public sealed class CloningSystem : EntitySystem
|
||||
[Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
|
||||
[Dependency] private readonly SharedContainerSystem _container = default!;
|
||||
[Dependency] private readonly SharedStorageSystem _storage = default!;
|
||||
[Dependency] private readonly SharedStackSystem _stack = default!;
|
||||
[Dependency] private readonly SharedSubdermalImplantSystem _subdermalImplant = default!;
|
||||
|
||||
/// <summary>
|
||||
@@ -157,9 +155,9 @@ public sealed class CloningSystem : EntitySystem
|
||||
|
||||
var spawned = EntityManager.SpawnAtPosition(prototype, coords);
|
||||
|
||||
// if the original is a stack, adjust the count of the copy
|
||||
if (TryComp<StackComponent>(original, out var originalStack) && TryComp<StackComponent>(spawned, out var spawnedStack))
|
||||
_stack.SetCount(spawned, originalStack.Count, spawnedStack);
|
||||
// copy over important component data
|
||||
var ev = new CloningItemEvent(spawned);
|
||||
RaiseLocalEvent(original, ref ev);
|
||||
|
||||
// if the original has items inside its storage, copy those as well
|
||||
if (TryComp<StorageComponent>(original, out var originalStorage) && TryComp<StorageComponent>(spawned, out var spawnedStorage))
|
||||
@@ -232,7 +230,14 @@ public sealed class CloningSystem : EntitySystem
|
||||
|
||||
var targetImplant = _subdermalImplant.AddImplant(target, implantId);
|
||||
|
||||
if (copyStorage && targetImplant != null)
|
||||
if (targetImplant == null)
|
||||
continue;
|
||||
|
||||
// copy over important component data
|
||||
var ev = new CloningItemEvent(targetImplant.Value);
|
||||
RaiseLocalEvent(originalImplant, ref ev);
|
||||
|
||||
if (copyStorage)
|
||||
CopyStorage(originalImplant, targetImplant.Value, whitelist, blacklist); // only needed for storage implants
|
||||
}
|
||||
|
||||
|
||||
@@ -138,6 +138,11 @@ namespace Content.Server.Forensics
|
||||
{
|
||||
dest.Fingerprints.Add(print);
|
||||
}
|
||||
|
||||
foreach (var residue in src.Residues)
|
||||
{
|
||||
dest.Residues.Add(residue);
|
||||
}
|
||||
}
|
||||
|
||||
public List<string> GetSolutionsDNA(EntityUid uid)
|
||||
|
||||
@@ -2,12 +2,21 @@ namespace Content.Shared.Cloning.Events;
|
||||
|
||||
/// <summary>
|
||||
/// Raised before a mob is cloned. Cancel to prevent cloning.
|
||||
/// This is raised on the original mob.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct CloningAttemptEvent(CloningSettingsPrototype Settings, bool Cancelled = false);
|
||||
|
||||
/// <summary>
|
||||
/// Raised after a new mob got spawned when cloning a humanoid.
|
||||
/// Raised after a new mob was spawned when cloning a humanoid.
|
||||
/// This is raised on the original mob.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct CloningEvent(CloningSettingsPrototype Settings, EntityUid CloneUid);
|
||||
|
||||
/// <summary>
|
||||
/// Raised after a new item was spawned when cloning an item.
|
||||
/// This is raised on the original item.
|
||||
/// </summary>
|
||||
[ByRefEvent]
|
||||
public record struct CloningItemEvent(EntityUid CloneUid);
|
||||
|
||||
@@ -224,6 +224,26 @@ public sealed class PaperSystem : EntitySystem
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Copy any stamp information from one piece of paper to another.
|
||||
/// </summary>
|
||||
public void CopyStamps(Entity<PaperComponent?> source, Entity<PaperComponent?> target)
|
||||
{
|
||||
if (!Resolve(source, ref source.Comp) || !Resolve(target, ref target.Comp))
|
||||
return;
|
||||
|
||||
target.Comp.StampedBy = new List<StampDisplayInfo>(source.Comp.StampedBy);
|
||||
target.Comp.StampState = source.Comp.StampState;
|
||||
Dirty(target);
|
||||
|
||||
if (TryComp<AppearanceComponent>(target, out var appearance))
|
||||
{
|
||||
// delete any stamps if the stamp state is null
|
||||
_appearance.SetData(target, PaperVisuals.Stamp, target.Comp.StampState ?? "", appearance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public void SetContent(Entity<PaperComponent> entity, string content)
|
||||
{
|
||||
entity.Comp.Content = content;
|
||||
|
||||
@@ -61,6 +61,7 @@
|
||||
components:
|
||||
- AttachedClothing # helmets, which are part of the suit
|
||||
- HumanoidAppearance # will cause problems for downstream felinids getting cloned as Urists
|
||||
- Implanter # they will spawn full again, but you already get the implant. And we can't do item slot copying yet
|
||||
- VirtualItem
|
||||
|
||||
# all antagonist roles
|
||||
|
||||
Reference in New Issue
Block a user