Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ADD: DNA Copy Implant for Uplink #2601

Merged
merged 5 commits into from
Feb 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 62 additions & 0 deletions Content.Client/SS220/PenScrambler/ClientPenScramblerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
using Content.Shared.SS220.PenScrambler;
using Robust.Client.GameObjects;

namespace Content.Client.SS220.PenScrambler;

public sealed class ClientPenScramblerSystem : EntitySystem
{
[Dependency] private readonly SpriteSystem _sprite = default!;

public override void Initialize()
{
SubscribeNetworkEvent<SetScaleFromTargetEvent>(OnSetScaleFromTarget);
}

public override void Update(float frameTime)
{
base.Update(frameTime);

var query = EntityManager.EntityQueryEnumerator<SetScaleFromTargetComponent>();

while (query.MoveNext(out var uid, out var comp))
{
if (comp is { Target: not null, IsUpdated: false })
{
TryUpdateSprite((uid, comp));
}
}
}

private void OnSetScaleFromTarget(SetScaleFromTargetEvent args)
{
var owner = GetEntity(args.Owner);

if (!TryComp<SetScaleFromTargetComponent>(owner, out var comp))
return;

comp.Target = args.Target;
Dirty(owner, comp);

TryUpdateSprite((owner, comp));
}

private void TryUpdateSprite(Entity<SetScaleFromTargetComponent> ent)
{
if (!ent.Comp.Target.HasValue)
return;

if (!EntityManager.TryGetEntity(ent.Comp.Target.Value, out var target))
return;

if (!TryComp<SpriteComponent>(ent.Owner, out var spriteUser))
return;

if (!TryComp<SpriteComponent>(target, out var spriteTarget))
return;

spriteUser.Scale = spriteTarget.Scale;
ent.Comp.IsUpdated = true;

_sprite.QueueUpdateInert(ent.Owner, spriteUser);
}
}
63 changes: 63 additions & 0 deletions Content.Server/Implants/SubdermalImplantSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,14 @@
using Content.Shared.Movement.Pulling.Systems;
using Content.Server.IdentityManagement;
using Content.Server.DetailExaminable;
using Content.Server.Polymorph.Systems;
using Content.Server.SS220.PenScrambler;
using Content.Shared.Store.Components;
using Robust.Shared.Collections;
using Robust.Shared.Map.Components;
using Content.Shared.DoAfter;
using Content.Shared.Polymorph;
using Content.Shared.SS220.PenScrambler;
using Content.Shared.SS220.Store;

namespace Content.Server.Implants;
Expand All @@ -53,6 +57,7 @@ public sealed class SubdermalImplantSystem : SharedSubdermalImplantSystem
[Dependency] private readonly SharedMapSystem _mapSystem = default!;
[Dependency] private readonly IdentitySystem _identity = default!;
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!; //SS220-insert-currency-doafter
[Dependency] private readonly PolymorphSystem _polymorph = default!; //ss220 add dna copy implant

private EntityQuery<PhysicsComponent> _physicsQuery;
private HashSet<Entity<MapGridComponent>> _targetGrids = [];
Expand All @@ -70,6 +75,7 @@ public override void Initialize()
SubscribeLocalEvent<SubdermalImplantComponent, UseScramImplantEvent>(OnScramImplant);
SubscribeLocalEvent<SubdermalImplantComponent, UseDnaScramblerImplantEvent>(OnDnaScramblerImplant);

SubscribeLocalEvent<SubdermalImplantComponent, UseDnaCopyImplantEvent>(OnDnaCopyImplant); //ss220 dna copy implant add
}

// SS220 - chemical-implants start
Expand Down Expand Up @@ -285,4 +291,61 @@ private void OnDnaScramblerImplant(EntityUid uid, SubdermalImplantComponent comp
args.Handled = true;
QueueDel(uid);
}

//ss220 dna copy implant add start
private void OnDnaCopyImplant(Entity<SubdermalImplantComponent> ent, ref UseDnaCopyImplantEvent args)
{
if (!TryComp<TransferIdentityComponent>(ent.Owner, out var transferIdentityComponent))
return;

var target = transferIdentityComponent.Target;

if (target == null)
{
QueueDel(ent);
return;
}

if (ent.Comp.ImplantedEntity is not { } user)
return;

if (TryComp<HumanoidAppearanceComponent>(user, out var humanoidAppearanceComponent))
{
if (transferIdentityComponent.AppearanceComponent == null)
return;

_humanoidAppearance.CloneAppearance(target.Value, user, transferIdentityComponent.AppearanceComponent, humanoidAppearanceComponent);

_metaData.SetEntityName(user, MetaData(target.Value).EntityName, raiseEvents: false);

if (TryComp<DnaComponent>(user, out var dna)
&& TryComp<DnaComponent>(target.Value, out var dnaTarget))
{
dna.DNA = dnaTarget.DNA;
var ev = new GenerateDnaEvent { Owner = user, DNA = dna.DNA };
RaiseLocalEvent(ent, ref ev);
}

if (TryComp<FingerprintComponent>(user, out var fingerprint)
&& TryComp<FingerprintComponent>(target.Value, out var fingerprintTarget))
{
fingerprint.Fingerprint = fingerprintTarget.Fingerprint;
}

var setScale = EnsureComp<SetScaleFromTargetComponent>(user);
setScale.Target = GetNetEntity(target);

Dirty(user, setScale);

var evEvent = new SetScaleFromTargetEvent(GetNetEntity(user), setScale.Target);
RaiseNetworkEvent(evEvent);

_identity.QueueIdentityUpdate(user);

_popup.PopupEntity(Loc.GetString("pen-scrambler-success-convert-to-identity", ("identity", MetaData(target.Value).EntityName)), user, user);
}

QueueDel(ent);
}
//ss220 dna copy implant add end
}
19 changes: 19 additions & 0 deletions Content.Server/SS220/PenScrambler/PenScramblerComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
using Content.Shared.Humanoid;

namespace Content.Server.SS220.PenScrambler;

[RegisterComponent]
public sealed partial class PenScramblerComponent : Component
{
[DataField]
public EntityUid? Target;

[DataField]
public HumanoidAppearanceComponent? AppearanceComponent;

[DataField]
public bool HaveDna = false;

public TimeSpan DelayForExtractDna = TimeSpan.FromSeconds(5);
public TimeSpan DelayForTransferToImplant = TimeSpan.FromSeconds(3);
}
81 changes: 81 additions & 0 deletions Content.Server/SS220/PenScrambler/PenScramblerSystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using Content.Shared.DoAfter;
using Content.Shared.Humanoid;
using Content.Shared.Implants.Components;
using Content.Shared.Interaction;
using Content.Shared.Popups;
using Content.Shared.SS220.PenScrambler;

namespace Content.Server.SS220.PenScrambler;

public sealed class PenScramblerSystem : EntitySystem
{
[Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;

public override void Initialize()
{
SubscribeLocalEvent<PenScramblerComponent, AfterInteractEvent>(OnInteract);
SubscribeLocalEvent<PenScramblerComponent, CopyDnaToPenEvent>(OnCopyIdentity);
}

private void OnInteract(Entity<PenScramblerComponent> ent, ref AfterInteractEvent args)
{
if (!args.CanReach || args.Target == null)
return;

if (HasComp<HumanoidAppearanceComponent>(args.Target) && !ent.Comp.HaveDna)
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
args.User,
ent.Comp.DelayForExtractDna,
new CopyDnaToPenEvent(),
ent.Owner,
args.Target)
{
Hidden = true,
BreakOnMove = true,
BreakOnDamage = true,
BreakOnHandChange = true,
BreakOnDropItem = true,
DuplicateCondition = DuplicateConditions.None,
});
}

if (!TryComp<ImplanterComponent>(args.Target, out var implanterComponent))
return;

var implantEntity = implanterComponent.ImplanterSlot.ContainerSlot?.ContainedEntity;

if (HasComp<TransferIdentityComponent>(implantEntity) && ent.Comp.HaveDna)
{
_doAfter.TryStartDoAfter(new DoAfterArgs(EntityManager,
args.User,
ent.Comp.DelayForTransferToImplant,
new CopyDnaFromPenToImplantEvent(),
implantEntity,
ent.Owner)
{
BreakOnMove = true,
BreakOnDamage = true,
BreakOnHandChange = true,
BreakOnDropItem = true,
DuplicateCondition = DuplicateConditions.None,
});
}
}

private void OnCopyIdentity(Entity<PenScramblerComponent> ent, ref CopyDnaToPenEvent args)
{
if (args.Cancelled)
return;

if (!TryComp<HumanoidAppearanceComponent>(args.Target, out var humanoidAppearanceComponent))
return;

ent.Comp.AppearanceComponent = humanoidAppearanceComponent;
ent.Comp.Target = args.Target;
ent.Comp.HaveDna = true;

_popup.PopupEntity(Loc.GetString("pen-scrambler-success-copy", ("identity", MetaData(args.Target.Value).EntityName)), args.User, args.User);
}
}
13 changes: 13 additions & 0 deletions Content.Server/SS220/PenScrambler/TransferIdentityComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using Content.Shared.Humanoid;

namespace Content.Server.SS220.PenScrambler;

[RegisterComponent]
public sealed partial class TransferIdentityComponent : Component
{
[DataField]
public EntityUid? Target;

[DataField]
public HumanoidAppearanceComponent? AppearanceComponent;
}
35 changes: 35 additions & 0 deletions Content.Server/SS220/PenScrambler/TransferIdentitySystem.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Content.Shared.Popups;
using Content.Shared.SS220.PenScrambler;

namespace Content.Server.SS220.PenScrambler;

public sealed class TransferIdentitySystem : EntitySystem
{
[Dependency] private readonly SharedPopupSystem _popup = default!;

public override void Initialize()
{
SubscribeLocalEvent<TransferIdentityComponent, CopyDnaFromPenToImplantEvent>(OnCopyIdentityToImplant);
}

private void OnCopyIdentityToImplant(Entity<TransferIdentityComponent> ent, ref CopyDnaFromPenToImplantEvent args)
{
if (args.Cancelled || args.Target == null)
return;

if (!TryComp<PenScramblerComponent>(args.Target, out var penComponent))
return;

if (penComponent.Target == null)
return;

ent.Comp.Target = penComponent.Target.Value;
ent.Comp.AppearanceComponent = penComponent.AppearanceComponent;

_popup.PopupEntity(Loc.GetString("pen-scrambler-success-transfer-to-implant",
("identity", MetaData(penComponent.Target.Value).EntityName)), args.User, args.User);

Dirty(ent);
QueueDel(args.Target);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,10 @@ public sealed partial class UseDnaScramblerImplantEvent : InstantActionEvent
{

}

//ss220 add dna copy implant start
public sealed partial class UseDnaCopyImplantEvent : InstantActionEvent
{

}
//ss220 add dna copy implant end
31 changes: 31 additions & 0 deletions Content.Shared/SS220/PenScrambler/SetScaleFromTargetComponent.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
using System.Numerics;
using Robust.Shared.GameStates;
using Robust.Shared.Serialization;

namespace Content.Shared.SS220.PenScrambler;

[RegisterComponent]
[NetworkedComponent]
[AutoGenerateComponentState]
public sealed partial class SetScaleFromTargetComponent : Component
{
[DataField]
[AutoNetworkedField]
public NetEntity? Target;

[DataField]
public bool IsUpdated;
}

[Serializable, NetSerializable]
public sealed class SetScaleFromTargetEvent : EntityEventArgs
{
public NetEntity Owner { get; }
public NetEntity? Target { get; }

public SetScaleFromTargetEvent(NetEntity owner, NetEntity? target)
{
Owner = owner;
Target = target;
}
}
18 changes: 18 additions & 0 deletions Content.Shared/SS220/PenScrambler/SharedPenScramblerEvents.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
using Content.Shared.DoAfter;
using Robust.Shared.Serialization;

namespace Content.Shared.SS220.PenScrambler;

[Serializable]
[NetSerializable]
public sealed partial class CopyDnaToPenEvent : DoAfterEvent
{
public override DoAfterEvent Clone() => this;
}

[Serializable]
[NetSerializable]
public sealed partial class CopyDnaFromPenToImplantEvent : DoAfterEvent
{
public override DoAfterEvent Clone() => this;
}
Loading
Loading