Repository: space-wizards/space-station-14
Pull request #35794: Paradox Clone
Author: login: slarticodefast
Labels: name: Changes: Sprites
description: Changes: Might require knowledge of spriting or visual design.
name: S: Needs Review
description: Status: Requires additional reviews before being fully accepted. Not to be replaced by S: Approved.
name: S: Untriaged
description: Status: Indicates an item has not been triaged and doesn't have appropriate labels.
name: Changes: Audio
description: Changes: Might require knowledge of audio.
name: size/M
description: Denotes a PR that changes 100-999 lines.
Created: 2025-03-12T17:07:30Z | Merged: 2025-03-13T17:09:07Z

## About the PR
Design doc: https://github.com/space-wizards/docs/pull/323

The paradox clone is a perfect copy of a random crewmember. They have the objective to kill and replace their original to fix the space-time paradox and will gib on roundend if they fail.

Thanks to @ps3moira for the cool intro sound and the visual effect.

Todo list for future PRs:
- Better spawn point selection. Currently they spawn on a random station tile, but get a toolbox and insuls in case they are trapped somewhere. They should spawn somewhere in maints or at arrivals instead.
- Better equipment copying. Currently they get a copy of everything the original has in their item slots, but storage is not copied recursively yet. This will need a larger yaml cleanup for StorageFill and similar systems first.
- Copy implants.
- Copy mind roles and antag status, maybe also objectives.
- admin antag control verb

## Why / Balance
classic SS13 antag

## Technical details
Uses the cloning code refactored in https://github.com/space-wizards/space-station-14/pull/35555/ to spawn a copy of a random player.
Most of the code are just the usual game rule, event and mind role stuff.

I atomized some parts of this code into their own PRs:

https://github.com/space-wizards/space-station-14/pull/35795
https://github.com/space-wizards/space-station-14/pull/35796
https://github.com/space-wizards/space-station-14/pull/35802

## Media

gamerule and spawning

https://github.com/user-attachments/assets/2a3c0cd9-eb4a-4909-90c6-b52d43a274ac

gibbing on roundend with failed objective

https://github.com/user-attachments/assets/b5647392-953b-4faf-9e8e-01e90cfb61c0

successful objective

https://github.com/user-attachments/assets/94417110-1c3e-4ab8-8a68-5a8a019c3dc6



## Requirements
<!-- Confirm the following by placing an X in the brackets [X]: -->
- [x] I have read and am following the [Pull Request and Changelog Guidelines](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
- [x] I have added media to this PR or it does not require an ingame showcase.
<!-- You should understand that not following the above may get your PR closed at maintainer’s discretion -->

## Breaking changes
moved the `paradox_clone.rsi` folder

Info for forks:
To have custom traits and accents properly copied to clones, you have to whitelist the corresponding component in the cloning settings in `clone.yml`.

**Changelog**
:cl: slarticodefast, ps3moira
- add: Added the paradox clone as a ghostrole antagonist.



Diff:
diff --git a/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs
new file mode 100644
index 0000000000000..a6ffb4e66993b
--- /dev/null
+++ b/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs
@@ -0,0 +1,23 @@
+using Content.Shared.Cloning;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.GameTicking.Rules.Components;
+
+/// <summary>
+///     Gamerule component for spawning a paradox clone antagonist.
+/// </summary>
+[RegisterComponent]
+public sealed partial class ParadoxCloneRuleComponent : Component
+{
+    /// <summary>
+    ///     Cloning settings to be used.
+    /// </summary>
+    [DataField]
+    public ProtoId<CloningSettingsPrototype> Settings = "BaseClone";
+
+    /// <summary>
+    ///     Visual effect spawned when gibbing at round end.
+    /// </summary>
+    [DataField]
+    public EntProtoId GibProto = "MobParadoxTimed";
+}
diff --git a/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs b/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs
new file mode 100644
index 0000000000000..80fad7d2ef379
--- /dev/null
+++ b/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs
@@ -0,0 +1,83 @@
+using Content.Server.Antag;
+using Content.Server.Cloning;
+using Content.Server.GameTicking.Rules.Components;
+using Content.Server.Objectives.Components;
+using Content.Shared.GameTicking.Components;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Random;
+
+namespace Content.Server.GameTicking.Rules;
+
+public sealed class ParadoxCloneRuleSystem : GameRuleSystem<ParadoxCloneRuleComponent>
+{
+    [Dependency] private readonly SharedTransformSystem _transform = default!;
+    [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly IRobustRandom _random = default!;
+    [Dependency] private readonly CloningSystem _cloning = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ParadoxCloneRuleComponent, AntagSelectEntityEvent>(OnAntagSelectEntity);
+    }
+
+    protected override void Started(EntityUid uid, ParadoxCloneRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
+    {
+        base.Started(uid, component, gameRule, args);
+
+        // check if we got enough potential cloning targets, otherwise cancel the gamerule so that the ghost role does not show up
+        var allHumans = _mind.GetAliveHumans();
+
+        if (allHumans.Count == 0)
+        {
+            Log.Info("Could not find any alive players to create a paradox clone from! Ending gamerule.");
+            ForceEndSelf(uid, gameRule);
+        }
+    }
+
+    // we have to do the spawning here so we can transfer the mind to the correct entity and can assign the objectives correctly
+    private void OnAntagSelectEntity(Entity<ParadoxCloneRuleComponent> ent, ref AntagSelectEntityEvent args)
+    {
+        if (args.Session?.AttachedEntity is not { } spawner)
+            return;
+
+        if (!_prototypeManager.TryIndex(ent.Comp.Settings, out var settings))
+        {
+            Log.Error($"Used invalid cloning settings {ent.Comp.Settings} for ParadoxCloneRule");
+            return;
+        }
+
+        // get possible targets
+        var allHumans = _mind.GetAliveHumans();
+
+        // we already checked when starting the gamerule, but someone might have died since then.
+        if (allHumans.Count == 0)
+        {
+            Log.Warning("Could not find any alive players to create a paradox clone from!");
+            return;
+        }
+
+        // pick a random player
+        var playerToClone = _random.Pick(allHumans);
+        var bodyToClone = playerToClone.Comp.OwnedEntity;
+
+        if (bodyToClone == null || !_cloning.TryCloning(bodyToClone.Value, _transform.GetMapCoordinates(spawner), settings, out var clone))
+        {
+            Log.Error($"Unable to make a paradox clone of entity {ToPrettyString(bodyToClone)}");
+            return;
+        }
+
+        var targetComp = EnsureComp<TargetOverrideComponent>(clone.Value);
+        targetComp.Target = playerToClone.Owner; // set the kill target
+
+        var gibComp = EnsureComp<GibOnRoundEndComponent>(clone.Value);
+        gibComp.SpawnProto = ent.Comp.GibProto;
+        gibComp.PreventGibbingObjectives = new() { "ParadoxCloneKillObjective" }; // don't gib them if they killed the original.
+
+        args.Entity = clone;
+    }
+}
diff --git a/Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs b/Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
new file mode 100644
index 0000000000000..d23832984f806
--- /dev/null
+++ b/Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
@@ -0,0 +1,55 @@
+﻿using Content.Shared.GameTicking;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Systems;
+using Content.Server.Body.Systems;
+
+namespace Content.Server.Gibbing.Systems;
+public sealed class GibOnRoundEndSystem : EntitySystem
+{
+    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        // this is raised after RoundEndTextAppendEvent, so they can successfully greentext before we gib them
+        SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
+    }
+
+    private void OnRoundEnd(RoundEndMessageEvent args)
+    {
+        var gibQuery = EntityQueryEnumerator<GibOnRoundEndComponent>();
+
+        // gib everyone with the component
+        while (gibQuery.MoveNext(out var uid, out var gibComp))
+        {
+            var gib = false;
+            // if they fulfill all objectives given in the component they are not gibbed
+            if (_mind.TryGetMind(uid, out var mindId, out var mindComp))
+            {
+                foreach (var objectiveId in gibComp.PreventGibbingObjectives)
+                {
+                    if (!_mind.TryFindObjective((mindId, mindComp), objectiveId, out var objective)
+                        || !_objectives.IsCompleted(objective.Value, (mindId, mindComp)))
+                    {
+                        gib = true;
+                        break;
+                    }
+                }
+            }
+            else
+                gib = true;
+
+            if (!gib)
+                continue;
+
+            if (gibComp.SpawnProto != null)
+                SpawnAtPosition(gibComp.SpawnProto, Transform(uid).Coordinates);
+
+            _body.GibBody(uid, splatModifier: 5f);
+        }
+    }
+}
diff --git a/Content.Server/Roles/ParadoxCloneRoleComponent.cs b/Content.Server/Roles/ParadoxCloneRoleComponent.cs
new file mode 100644
index 0000000000000..d55cd34da4e35
--- /dev/null
+++ b/Content.Server/Roles/ParadoxCloneRoleComponent.cs
@@ -0,0 +1,9 @@
+using Content.Shared.Roles;
+
+namespace Content.Server.Roles;
+
+/// <summary>
+///     Added to mind role entities to tag that they are a paradox clone.
+/// </summary>
+[RegisterComponent]
+public sealed partial class ParadoxCloneRoleComponent : BaseMindRoleComponent;
diff --git a/Content.Shared/Gibbing/Components/GibOnRoundEndComponent.cs b/Content.Shared/Gibbing/Components/GibOnRoundEndComponent.cs
new file mode 100644
index 0000000000000..5ce8edbd25dc6
--- /dev/null
+++ b/Content.Shared/Gibbing/Components/GibOnRoundEndComponent.cs
@@ -0,0 +1,22 @@
+﻿using Robust.Shared.Prototypes;
+
+namespace Content.Shared.Gibbing.Components;
+
+/// <summary>
+/// Gibs an entity on round end.
+/// </summary>
+[RegisterComponent]
+public sealed partial class GibOnRoundEndComponent : Component
+{
+    /// <summary>
+    /// If the entity has all these objectives fulfilled they won't be gibbed.
+    /// </summary>
+    [DataField]
+    public HashSet<EntProtoId> PreventGibbingObjectives = new();
+
+    /// <summary>
+    /// Entity to spawn when gibbed. Can be used for effects.
+    /// </summary>
+    [DataField]
+    public EntProtoId? SpawnProto;
+}
diff --git a/Resources/Audio/Misc/attributions.yml b/Resources/Audio/Misc/attributions.yml
index a7349a445be63..67daaff404203 100644
--- a/Resources/Audio/Misc/attributions.yml
+++ b/Resources/Audio/Misc/attributions.yml
@@ -8,6 +8,11 @@
   copyright: "Created by Chillyconmor"
   source: "https://github.com/space-wizards/space-station-14/blob/master/Resources/Audio/Misc/ninja_greeting.ogg"
 
+- files: ["nparadox_clone_greeting.ogg"]
+  license: "CC-BY-SA-3.0"
+  copyright: "Created by ps3moira"
+  source: "https://github.com/space-wizards/space-station-14/blob/master/Resources/Audio/Misc/ninja_greeting.ogg"
+
 - files: ["thief_greeting.ogg"]
   license: "CC-BY-NC-4.0"
   copyright: "Taken from SergeQuadrado via freesound.org, edit and mono by TheShuEd"
diff --git a/Resources/Audio/Misc/paradox_clone_greeting.ogg b/Resources/Audio/Misc/paradox_clone_greeting.ogg
new file mode 100644
index 0000000000000..deffca12e6d09
Binary files /dev/null and b/Resources/Audio/Misc/paradox_clone_greeting.ogg differ
diff --git a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
index b2f0932787676..3e89f912a9971 100644
--- a/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
+++ b/Resources/Locale/en-US/ghost/roles/ghost-role-component.ftl
@@ -211,6 +211,9 @@ ghost-role-information-BreadDog-description = You are the chef's favorite child.
 ghost-role-information-space-ninja-name = Space Ninja
 ghost-role-information-space-ninja-description = Use stealth and deception to sabotage the station.
 
+ghost-role-information-paradox-clone-name = Paradox Clone
+ghost-role-information-paradox-clone-description = A freak space-time anomaly has teleported you into another reality! Now you have to find your counterpart and kill and replace them.
+
 ghost-role-information-syndicate-reinforcement-name = Syndicate Agent
 ghost-role-information-syndicate-reinforcement-description = Someone needs reinforcements. You, the first person the syndicate could find, will help them.
 ghost-role-information-syndicate-reinforcement-rules = You are a [color=red][bold]Team Antagonist[/bold][/color] with the agent who summoned you.
diff --git a/Resources/Locale/en-US/paradox-clone/role.ftl b/Resources/Locale/en-US/paradox-clone/role.ftl
new file mode 100644
index 0000000000000..0a73ab4c3bacb
--- /dev/null
+++ b/Resources/Locale/en-US/paradox-clone/role.ftl
@@ -0,0 +1,5 @@
+paradox-clone-round-end-agent-name = paradox clone
+
+objective-issuer-paradox = [color=lightblue]Paradox[/color]
+
+paradox-clone-role-greeting = A freak space-time anomaly has teleported you into another reality! Now you have to find your counterpart and kill and replace them. Only one of you two can survive.
diff --git a/Resources/Locale/en-US/prototypes/roles/antags.ftl b/Resources/Locale/en-US/prototypes/roles/antags.ftl
index ba43d4ff85bc5..ada25a4a0ac57 100644
--- a/Resources/Locale/en-US/prototypes/roles/antags.ftl
+++ b/Resources/Locale/en-US/prototypes/roles/antags.ftl
@@ -31,6 +31,9 @@ roles-antag-subverted-silicon-objective = Follow your new laws and do bad unto t
 roles-antag-space-ninja-name = Space Ninja
 roles-antag-space-ninja-objective = Use your stealth to sabotage the station, nom on electrical wires.
 
+roles-antag-paradox-clone-name = Paradox Clone
+roles-antag-paradox-clone-objective = A freak space-time anomaly has teleported you into another reality! Now you have to find your counterpart and kill and replace them.
+
 roles-antag-thief-name = Thief
 roles-antag-thief-objective = Add some NT property to your personal collection without using violence.
 
diff --git a/Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml b/Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml
index ac9ab4deaa615..a4813fe41a4a8 100644
--- a/Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml
+++ b/Resources/Prototypes/Catalog/Fills/Items/toolboxes.yml
@@ -22,7 +22,7 @@
         prob: 0.15
       - id: HarmonicaInstrument
         prob: 0.15
- 
+
 - type: entity
   id: ToolboxElectricalFilled
   name: electrical toolbox
@@ -82,7 +82,7 @@
     - id: MysteryFigureBox
       prob: 0.5
     - id: BookRandom
-      amount: 2 
+      amount: 2
     - id: CrayonMime
     - id: CrayonRainbow
 
@@ -105,6 +105,21 @@
       - id: ClothingHeadHatHardhatBlue
         prob: 0.5
 
+- type: entity
+  id: ToolboxMechanicalFilledAllTools
+  name: mechanical toolbox
+  suffix: Filled, all tools
+  parent: ToolboxMechanical
+  components:
+  - type: StorageFill
+    contents:
+    - id: Crowbar
+    - id: Wrench
+    - id: Screwdriver
+    - id: Wirecutter
+    - id: Welder
+    - id: Multitool
+
 - type: entity
   parent: ToolboxSyndicate
   id: ToolboxSyndicateFilled
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
index bd3c76cd84c5e..c78686f5efe11 100644
--- a/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
+++ b/Resources/Prototypes/Entities/Markers/Spawners/ghost_roles.yml
@@ -191,6 +191,26 @@
     - sprite: Objects/Weapons/Melee/energykatana.rsi
       state: icon
 
+- type: entity
+  categories: [ HideSpawnMenu, Spawner ]
+  parent: BaseAntagSpawner
+  id: SpawnPointGhostParadoxClone
+  components:
+  - type: GhostRole
+    name: ghost-role-information-paradox-clone-name
+    description: ghost-role-information-paradox-clone-description
+    rules: ghost-role-information-antagonist-rules
+    mindRoles:
+    - MindRoleGhostRoleSoloAntagonist
+    raffle:
+      settings: default
+  - type: Sprite
+    layers:
+    - sprite: Markers/jobs.rsi
+      state: green
+    - sprite: Mobs/Aliens/paradox_clone.rsi
+      state: preview
+
 - type: entity
   categories: [ HideSpawnMenu, Spawner ]
   parent: BaseAntagSpawner
diff --git a/Resources/Prototypes/Entities/Mobs/Player/clone.yml b/Resources/Prototypes/Entities/Mobs/Player/clone.yml
index 64ae4f9ad8109..b7bd8a0d549ac 100644
--- a/Resources/Prototypes/Entities/Mobs/Player/clone.yml
+++ b/Resources/Prototypes/Entities/Mobs/Player/clone.yml
@@ -56,6 +56,7 @@
   blacklist:
     components:
     - AttachedClothing # helmets, which are part of the suit
+    - VirtualItem
 
 - type: cloningSettings
   id: Antag
@@ -78,7 +79,7 @@
   suffix: Non-Antag
   components:
   - type: Sprite
-    sprite: Markers/paradox_clone.rsi
+    sprite: Mobs/Aliens/paradox_clone.rsi
     state: preview
   - type: RandomCloneSpawner
     settings: BaseClone
diff --git a/Resources/Prototypes/Entities/Mobs/Player/paradox_clone.yml b/Resources/Prototypes/Entities/Mobs/Player/paradox_clone.yml
new file mode 100644
index 0000000000000..1516843379050
--- /dev/null
+++ b/Resources/Prototypes/Entities/Mobs/Player/paradox_clone.yml
@@ -0,0 +1,37 @@
+# Mob
+- type: entity
+  parent: BaseMob
+  id: MobParadox
+  name: space-time paradox
+  description: A big ball of wibbly wobbly, timey wimey stuff.
+  components:
+  - type: Sprite
+    drawdepth: Mobs
+    layers:
+    - sprite: Mobs/Aliens/paradox_clone.rsi
+      state: paradox
+      shader: unshaded
+  - type: RotationVisuals
+    horizontalRotation: 90
+  - type: Pullable
+  - type: Tag
+    tags:
+    - DoorBumpOpener
+
+- type: entity
+  parent: MobParadox
+  id: MobParadoxTimed # visual effect when gibbing on round end
+  components:
+  - type: TimedDespawn
+    lifetime: 10
+
+# guidebook dummy
+
+- type: entity
+  id: ParadoxCloneDummy
+  categories: [ HideSpawnMenu ]
+  name: Paradox Clone
+  components:
+  - type: Sprite
+    sprite: Mobs/Aliens/paradox_clone.rsi
+    state: preview
diff --git a/Resources/Prototypes/GameRules/events.yml b/Resources/Prototypes/GameRules/events.yml
index cda13e45268eb..953a7ad1beca8 100644
--- a/Resources/Prototypes/GameRules/events.yml
+++ b/Resources/Prototypes/GameRules/events.yml
@@ -232,6 +232,39 @@
       mindRoles:
       - MindRoleNinja
 
+- type: entity
+  parent: BaseGameRule
+  id: ParadoxCloneSpawn
+  components:
+  - type: StationEvent
+    weight: 4 # should not happen every round
+    duration: null
+    earliestStart: 30
+    reoccurrenceDelay: 20
+    minimumPlayers: 15
+  - type: ParadoxCloneRule
+  - type: AntagObjectives
+    objectives:
+    - ParadoxCloneKillObjective
+    - ParadoxCloneLivingObjective
+  - type: AntagRandomSpawn # TODO: improve spawning so they only start in maints
+  - type: AntagSelection
+    agentName: paradox-clone-round-end-agent-name
+    definitions:
+    - spawnerPrototype: SpawnPointGhostParadoxClone
+      min: 1
+      max: 1
+      pickPlayer: false
+      startingGear: ParadoxCloneGear
+      roleLoadout:
+      - RoleSurvivalStandard # give vox something to breath in case they don't get a copy
+      briefing:
+        text: paradox-clone-role-greeting
+        color: lightblue
+        sound: /Audio/Misc/paradox_clone_greeting.ogg
+      mindRoles:
+      - MindRoleParadoxClone
+
 - type: entity
   parent: BaseGameRule
   id: RevenantSpawn
diff --git a/Resources/Prototypes/Objectives/paradoxClone.yml b/Resources/Prototypes/Objectives/paradoxClone.yml
new file mode 100644
index 0000000000000..80aa4f15df370
--- /dev/null
+++ b/Resources/Prototypes/Objectives/paradoxClone.yml
@@ -0,0 +1,38 @@
+﻿- type: entity
+  abstract: true
+  parent: BaseObjective
+  id: BaseParadoxCloneObjective
+  components:
+  - type: Objective
+    # required but not used
+    difficulty: 1
+    issuer: objective-issuer-paradox
+  - type: RoleRequirement
+    roles:
+      mindRoles:
+      - ParadoxCloneRole
+
+- type: entity
+  parent: [BaseParadoxCloneObjective, BaseLivingObjective]
+  id: ParadoxCloneLivingObjective
+  name: Escape to centcomm alive and unrestrained.
+  description: Return to your old life.
+  components:
+  - type: Objective
+    icon:
+      sprite: Structures/Furniture/chairs.rsi
+      state: shuttle
+  - type: EscapeShuttleCondition
+
+- type: entity
+  parent: [BaseParadoxCloneObjective, BaseKillObjective]
+  id: ParadoxCloneKillObjective
+  name: Fix the space-time paradox.
+  description: Replace your original to fix the paradox. Remember, your mission is to blend in, do not kill anyone else unless you have to!
+  components:
+  - type: PickSpecificPerson
+  - type: KillPersonCondition
+    requireDead: true # don't count missing evac as killing
+  - type: TargetObjective
+    title: objective-condition-kill-head-title # kill <name>, <job>
+
diff --git a/Resources/Prototypes/Roles/Antags/paradoxClone.yml b/Resources/Prototypes/Roles/Antags/paradoxClone.yml
new file mode 100644
index 0000000000000..6e8daf16b4467
--- /dev/null
+++ b/Resources/Prototypes/Roles/Antags/paradoxClone.yml
@@ -0,0 +1,16 @@
+- type: antag
+  id: ParadoxClone
+  name: roles-antag-paradox-clone-name
+  antagonist: true
+  objective: roles-antag-paradox-clone-objective
+  setPreference: false
+
+# they need to be able to espace when spawning inside a locked room
+# TODO: remove this once we got a better spawning loacation selection
+- type: startingGear
+  id: ParadoxCloneGear
+  inhand:
+  - ToolboxMechanicalFilledAllTools
+  storage:
+    back:
+    - ClothingHandsGlovesColorYellow
diff --git a/Resources/Prototypes/Roles/MindRoles/mind_roles.yml b/Resources/Prototypes/Roles/MindRoles/mind_roles.yml
index ea6780eb50742..a690ab0c0db3e 100644
--- a/Resources/Prototypes/Roles/MindRoles/mind_roles.yml
+++ b/Resources/Prototypes/Roles/MindRoles/mind_roles.yml
@@ -143,6 +143,17 @@
     exclusiveAntag: true
   - type: NinjaRole
 
+# Paradox Clone
+- type: entity
+  parent: BaseMindRoleAntag
+  id: MindRoleParadoxClone
+  name: Paradox Clone Role
+  components:
+  - type: MindRole
+    antagPrototype: ParadoxClone
+    roleType: SoloAntagonist
+  - type: ParadoxCloneRole
+
 # Nukies
 - type: entity
   parent: BaseMindRoleAntag
diff --git a/Resources/ServerInfo/Guidebook/Antagonist/MinorAntagonists.xml b/Resources/ServerInfo/Guidebook/Antagonist/MinorAntagonists.xml
index 97574c4021538..a938cc4040c36 100644
--- a/Resources/ServerInfo/Guidebook/Antagonist/MinorAntagonists.xml
+++ b/Resources/ServerInfo/Guidebook/Antagonist/MinorAntagonists.xml
@@ -3,6 +3,14 @@
 
   Most if not all Minor Antagonists are ghost-controlled roles that gives dead people new ways to cause chaos around the station. They are spawned by random events.
 
+  # Paradox Clone
+
+  <Box>
+    <GuideEntityEmbed Entity="ParadoxCloneDummy"/>
+  </Box>
+
+  A perfect copy of a random crewmember that was thrown into our universe by a space-time anomaly. To fix the paradox and survive they have to find and kill their original counterpart. They have no special abilities, but are have identical appearance, DNA, fingerprints, clothing, equipment and IDs, making it hard to figure out who is the orginal and who is the clone, unless you know your fellow crewmembers well.
+
   # Revenant
 
   <Box>
diff --git a/Resources/Textures/Markers/paradox_clone.rsi/meta.json b/Resources/Textures/Markers/paradox_clone.rsi/meta.json
deleted file mode 100644
index e58634703115c..0000000000000
--- a/Resources/Textures/Markers/paradox_clone.rsi/meta.json
+++ /dev/null
@@ -1,14 +0,0 @@
-{
-  "version": 1,
-  "license": "CC-BY-SA-3.0",
-  "copyright": "preview combined from Mobs/Species/Human/parts.rsi, Clothing/Uniforms/Jumpsuit/janitor.rsi, Clothing/Shoes/Specific/galoshes.rsi, Clothing/Belt/janitor.rsi, Clothing/Hands/Gloves/janitor.rsi and Clothing/Head/Soft/purplesoft.rsi by slarticodefast",
-  "size": {
-    "x": 32,
-    "y": 32
-  },
-  "states": [
-    {
-      "name": "preview"
-    }
-  ]
-}
\ No newline at end of file
diff --git a/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/meta.json b/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/meta.json
new file mode 100644
index 0000000000000..942900ec3ea07
--- /dev/null
+++ b/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/meta.json
@@ -0,0 +1,108 @@
+{
+  "version": 1,
+  "license": "CC-BY-SA-3.0",
+  "copyright": "preview combined from Mobs/Species/Human/parts.rsi, Clothing/Uniforms/Jumpsuit/janitor.rsi, Clothing/Shoes/Specific/galoshes.rsi, Clothing/Belt/janitor.rsi, Clothing/Hands/Gloves/janitor.rsi and Clothing/Head/Soft/purplesoft.rsi by slarticodefast, paradox made by ps3moira (github)",
+  "size": {
+    "x": 32,
+    "y": 32
+  },
+  "states": [
+    {
+      "name": "preview"
+    },
+    {
+      "name": "paradox",
+      "directions": 4,
+      "delays": [
+        [
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1
+        ],
+        [
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1
+        ],
+        [
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1
+        ],
+        [
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1,
+          0.1
+        ]
+      ]
+    }
+  ]
+}
diff --git a/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/paradox.png b/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/paradox.png
new file mode 100644
index 0000000000000..f1cb35df5988b
Binary files /dev/null and b/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/paradox.png differ
diff --git a/Resources/Textures/Markers/paradox_clone.rsi/preview.png b/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/preview.png
similarity index 100%
rename from Resources/Textures/Markers/paradox_clone.rsi/preview.png
rename to Resources/Textures/Mobs/Aliens/paradox_clone.rsi/preview.png


Reviews:
user: login: ScarKy0
state: APPROVED
author_association: CONTRIBUTOR
submitted_at: 2025-03-12T18:44:59Z
user: login: slarticodefast
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T18:46:08Z
user: login: slarticodefast
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-12T23:51:13Z
user: login: metalgearsloth
state: DISMISSED
author_association: CONTRIBUTOR
submitted_at: 2025-03-13T09:29:46Z
user: login: slarticodefast
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-13T13:22:37Z
user: login: slarticodefast
state: COMMENTED
author_association: MEMBER
submitted_at: 2025-03-13T13:39:15Z
user: login: beck-thompson
body: :partying_face: this will be fun!
state: APPROVED
author_association: MEMBER
submitted_at: 2025-03-13T17:08:25Z

Review comments:
diff_hunk: @@ -232,6 +232,39 @@
       mindRoles:
       - MindRoleNinja
 
+- type: entity
+  parent: BaseGameRule
+  id: ParadoxCloneSpawn
+  components:
+  - type: StationEvent
+    weight: 3 # should not happen every round
+    duration: null
+    earliestStart: 30
+    reoccurrenceDelay: 20
+    minimumPlayers: 15
+  - type: ParadoxCloneRule
+  - type: AntagObjectives
+    objectives:
+    - ParadoxCloneKillObjective
+    - ParadoxCloneLivingObjective
+  - type: AntagRandomSpawn # TODO: improve spawning so they only start in maints
+  - type: AntagSelection
+    agentName: paradox-clone-round-end-agent-name
+    definitions:
+    - spawnerPrototype: SpawnPointGhostParadoxClone
+      min: 1
+      max: 1
+      pickPlayer: false
+      startingGear: ParadoxCloneGear
+      roleLoadout:
+      - RoleSurvivalStandard # give vox something to breath in case they don't get a copy
+      briefing:
+        text: paradox-clone-role-greeting
+        color: lightblue
+        sound: /Audio/Misc/paradox_clone_greeting.ogg
+      mindRoles:
path: Resources/Prototypes/GameRules/events.yml
user: login: ScarKy0
body: For some reason I don't hear the audio in-game, maybe just a me thing?
created_at: 2025-03-12T18:44:53Z
author_association: CONTRIBUTOR
diff_hunk: @@ -232,6 +232,39 @@
       mindRoles:
       - MindRoleNinja
 
+- type: entity
+  parent: BaseGameRule
+  id: ParadoxCloneSpawn
+  components:
+  - type: StationEvent
+    weight: 3 # should not happen every round
+    duration: null
+    earliestStart: 30
+    reoccurrenceDelay: 20
+    minimumPlayers: 15
+  - type: ParadoxCloneRule
+  - type: AntagObjectives
+    objectives:
+    - ParadoxCloneKillObjective
+    - ParadoxCloneLivingObjective
+  - type: AntagRandomSpawn # TODO: improve spawning so they only start in maints
+  - type: AntagSelection
+    agentName: paradox-clone-round-end-agent-name
+    definitions:
+    - spawnerPrototype: SpawnPointGhostParadoxClone
+      min: 1
+      max: 1
+      pickPlayer: false
+      startingGear: ParadoxCloneGear
+      roleLoadout:
+      - RoleSurvivalStandard # give vox something to breath in case they don't get a copy
+      briefing:
+        text: paradox-clone-role-greeting
+        color: lightblue
+        sound: /Audio/Misc/paradox_clone_greeting.ogg
+      mindRoles:
path: Resources/Prototypes/GameRules/events.yml
user: login: slarticodefast
body: Tested again and it's broken.
I need to fix that first.
created_at: 2025-03-12T18:46:08Z
author_association: MEMBER
diff_hunk: @@ -3,6 +3,14 @@
 
   Most if not all Minor Antagonists are ghost-controlled roles that gives dead people new ways to cause chaos around the station. They are spawned by random events.
 
+  # Paradox Clone
+
+  <Box>
+    <GuideEntityEmbed Entity="ParadoxCloneDummy"/>
+  </Box>
+
+  A perfect copy of a random crewmember that was thrown into our universe by a space-time anomaly. To fix the paradox and survive they have to find and kill their original counterpart. They have no special abilities, but are have identical appearance, DNA, fingerprints, clothing, equipment and IDs, making it hard to know who is the orginal and who is the clone, unless you know your fellow crewmembers well.
path: Resources/ServerInfo/Guidebook/Antagonist/MinorAntagonists.xml
user: login: slarticodefast
body: ```suggestion
  A perfect copy of a random crewmember that was thrown into our universe by a space-time anomaly. To fix the paradox and survive they have to find and kill their original counterpart. They have no special abilities, but are have identical appearance, DNA, fingerprints, clothing, equipment and IDs, making it hard to figure out who is the orginal and who is the clone, unless you know your fellow crewmembers well.
```
created_at: 2025-03-12T23:51:13Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,55 @@
+﻿using Content.Shared.GameTicking;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Systems;
+using Content.Server.Body.Systems;
+
+namespace Content.Server.Gibbing.Systems;
+public sealed class GibOnRoundEndSystem : EntitySystem
+{
+    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        // this is raised after RoundEndTextAppendEvent, so they can successfully greentext before we gib them
+        SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
+    }
+
+    private void OnRoundEnd(RoundEndMessageEvent args)
+    {
+        var gibQuery = EntityQueryEnumerator<GibOnRoundEndComponent>();
+
+        // gib everyone with the component
+        while (gibQuery.MoveNext(out var uid, out var gibComp))
+        {
+            var gib = false;
+            // if they fulfill all objectives given in the component they are not gibbed
+            if (_mind.TryGetMind(uid, out var mindId, out var mindComp))
+            {
+                foreach (var objectiveId in gibComp.PreventGibbingObjectives)
+                {
+                    if (!_mind.TryFindObjective((mindId, mindComp), objectiveId, out var objective)
+                        || !_objectives.IsCompleted(objective.Value, (mindId, mindComp)))
+                    {
+                        gib = true;
+                        break;
+                    }
+                }
+            }
+            else
+                gib = true;
+
+            if (!gib)
+                return;
+
+            if (gibComp.SpawnProto != null)
+                Spawn(gibComp.SpawnProto, Transform(uid).Coordinates);
path: Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
user: login: metalgearsloth
body: Use one of the helper methods, I think it's placeat that also handles containers properly.
created_at: 2025-03-13T09:29:07Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,55 @@
+﻿using Content.Shared.GameTicking;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Systems;
+using Content.Server.Body.Systems;
+
+namespace Content.Server.Gibbing.Systems;
+public sealed class GibOnRoundEndSystem : EntitySystem
+{
+    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        // this is raised after RoundEndTextAppendEvent, so they can successfully greentext before we gib them
+        SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
+    }
+
+    private void OnRoundEnd(RoundEndMessageEvent args)
+    {
+        var gibQuery = EntityQueryEnumerator<GibOnRoundEndComponent>();
+
+        // gib everyone with the component
+        while (gibQuery.MoveNext(out var uid, out var gibComp))
+        {
+            var gib = false;
+            // if they fulfill all objectives given in the component they are not gibbed
+            if (_mind.TryGetMind(uid, out var mindId, out var mindComp))
+            {
+                foreach (var objectiveId in gibComp.PreventGibbingObjectives)
+                {
+                    if (!_mind.TryFindObjective((mindId, mindComp), objectiveId, out var objective)
+                        || !_objectives.IsCompleted(objective.Value, (mindId, mindComp)))
+                    {
+                        gib = true;
+                        break;
+                    }
+                }
+            }
+            else
+                gib = true;
+
+            if (!gib)
+                return;
path: Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
user: login: metalgearsloth
body: Should this be a continue?
created_at: 2025-03-13T09:29:15Z
author_association: CONTRIBUTOR
diff_hunk: @@ -0,0 +1,55 @@
+﻿using Content.Shared.GameTicking;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Systems;
+using Content.Server.Body.Systems;
+
+namespace Content.Server.Gibbing.Systems;
+public sealed class GibOnRoundEndSystem : EntitySystem
+{
+    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        // this is raised after RoundEndTextAppendEvent, so they can successfully greentext before we gib them
+        SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
+    }
+
+    private void OnRoundEnd(RoundEndMessageEvent args)
+    {
+        var gibQuery = EntityQueryEnumerator<GibOnRoundEndComponent>();
+
+        // gib everyone with the component
+        while (gibQuery.MoveNext(out var uid, out var gibComp))
+        {
+            var gib = false;
+            // if they fulfill all objectives given in the component they are not gibbed
+            if (_mind.TryGetMind(uid, out var mindId, out var mindComp))
+            {
+                foreach (var objectiveId in gibComp.PreventGibbingObjectives)
+                {
+                    if (!_mind.TryFindObjective((mindId, mindComp), objectiveId, out var objective)
+                        || !_objectives.IsCompleted(objective.Value, (mindId, mindComp)))
+                    {
+                        gib = true;
+                        break;
+                    }
+                }
+            }
+            else
+                gib = true;
+
+            if (!gib)
+                return;
path: Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
user: login: slarticodefast
body: yep, good catch!
created_at: 2025-03-13T13:22:37Z
author_association: MEMBER
diff_hunk: @@ -0,0 +1,55 @@
+﻿using Content.Shared.GameTicking;
+using Content.Shared.Gibbing.Components;
+using Content.Shared.Mind;
+using Content.Shared.Objectives.Systems;
+using Content.Server.Body.Systems;
+
+namespace Content.Server.Gibbing.Systems;
+public sealed class GibOnRoundEndSystem : EntitySystem
+{
+    [Dependency] private readonly BodySystem _body = default!;
+    [Dependency] private readonly SharedMindSystem _mind = default!;
+    [Dependency] private readonly SharedObjectivesSystem _objectives = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        // this is raised after RoundEndTextAppendEvent, so they can successfully greentext before we gib them
+        SubscribeLocalEvent<RoundEndMessageEvent>(OnRoundEnd);
+    }
+
+    private void OnRoundEnd(RoundEndMessageEvent args)
+    {
+        var gibQuery = EntityQueryEnumerator<GibOnRoundEndComponent>();
+
+        // gib everyone with the component
+        while (gibQuery.MoveNext(out var uid, out var gibComp))
+        {
+            var gib = false;
+            // if they fulfill all objectives given in the component they are not gibbed
+            if (_mind.TryGetMind(uid, out var mindId, out var mindComp))
+            {
+                foreach (var objectiveId in gibComp.PreventGibbingObjectives)
+                {
+                    if (!_mind.TryFindObjective((mindId, mindComp), objectiveId, out var objective)
+                        || !_objectives.IsCompleted(objective.Value, (mindId, mindComp)))
+                    {
+                        gib = true;
+                        break;
+                    }
+                }
+            }
+            else
+                gib = true;
+
+            if (!gib)
+                return;
+
+            if (gibComp.SpawnProto != null)
+                Spawn(gibComp.SpawnProto, Transform(uid).Coordinates);
path: Content.Server/Gibbing/Systems/GibOnRoundEndSystem.cs
user: login: slarticodefast
body: I'm using `SpawnAtPosition` now since I don't want it attached to the parent, since we are gibbing that one anyways.
created_at: 2025-03-13T13:39:15Z
author_association: MEMBER

PR comments:
user: login: github-actions[bot]
created_at: 2025-03-12T17:08:07Z
body: RSI Diff Bot; head commit 40ebec8ec0b90930f3945ca94460966083db20e5 merging into 48a4aa39292e8a6b0ca461396e75e0227367e941
This PR makes changes to 1 or more RSIs. Here is a summary of all changes:

<details><summary>Resources/Textures/Mobs/Aliens/paradox_clone.rsi</summary>
<p>

| State | Old | New | Status
| --- | --- | --- | --- |
| paradox | ![]() | ![](https://raw.githubusercontent.com/slarticodefast/space-station-14/40ebec8ec0b90930f3945ca94460966083db20e5/Resources/Textures/Mobs/Aliens/paradox_clone.rsi/paradox.png) | Added


</p>
</details>
Edit: diff updated after 40ebec8ec0b90930f3945ca94460966083db20e5
author_association: CONTRIBUTOR
user: login: slarticodefast
created_at: 2025-03-12T19:51:35Z
body: I had to remove the polymorph visual effect on spawn for multiple reasons:
- If polymorphing before objective assignment it was breaking the round end text because it changed the entity the objectives were assigned to
- If polymorphed after instead then it broke the greeting sound because it was detaching you from the mob that received the greeting
- Gameplay-wise the flashy effect made you extremely valid on spawn, which is bad for a stealth focused antagonist. It's a shame because the sprite fit the intro sound so well, but it is still used when being gibbed on round end.
author_association: MEMBER
user: login: slarticodefast
created_at: 2025-03-12T22:11:09Z
body: I cleaned up the objective assignment components and systems a little so they are less confusing. If it looks good to the other maintainers I will atomize that change into a separate PR that should be merged before this one.
author_association: MEMBER
user: login: Dead-Wasp
created_at: 2025-03-12T22:24:44Z
body: Honestly, although I don't like that such scope for role-playing situations is locked in exclusively murder one framework. I don't really understand how this will affect the round. You kill one and replace him to do the same as he did. Who cares who was killed and replaced there? I understand that the main goal of the antag is for the original and the clone to stand next to each other and prove who the original is. But there is no punishment for a mistake. Why not make it so that if the clone survives and lives for about 5 minutes, something unpleasant happens. For example, 2 more clones of other crew members spawn, this will be a punishment for the crew for insufficient attentiveness. Each of them, when the same conditions are met, spawns 2 more clones, and so on. On the 4th-5th cycle, it will be impossible to tell who you are talking to. The original or the clone that replaced him. Successful clones will make the round unusual. A whole new mode is obtained. At the same time, there will always be ghost roles and no one will have to wait. It sounds interesting, but it all falls apart when you use randomly generated clothes from the wardrobe.
author_association: NONE
user: login: TiniestShark
created_at: 2025-03-12T22:43:16Z
body: yesyesyesyesyes! can't wait for the "which one do i shoot" scenarios.
author_association: CONTRIBUTOR
user: login: ArcaneOcto
created_at: 2025-03-12T23:56:34Z
body: > Honestly, although I don't like that such scope for role-playing situations is locked in exclusively murder one framework. I don't really understand how this will affect the round. You kill one and replace him to do the same as he did. Who cares who was killed and replaced there? I understand that the main goal of the antag is for the original and the clone to stand next to each other and prove who the original is. But there is no punishment for a mistake. Why not make it so that if the clone survives and lives for about 5 minutes, something unpleasant happens. For example, 2 more clones of other crew members spawn, this will be a punishment for the crew for insufficient attentiveness. Each of them, when the same conditions are met, spawns 2 more clones, and so on. On the 4th-5th cycle, it will be impossible to tell who you are talking to. The original or the clone that replaced him. Successful clones will make the round unusual. A whole new mode is obtained. At the same time, there will always be ghost roles and no one will have to wait. It sounds interesting, but it all falls apart when you use randomly generated clothes from the wardrobe.

This sounds awesome. Though maybe this would be best as a future PR that builds on this one? What you're proposing here could be considered a major antag, based on the fact that eventually the entire station could be replaced.
author_association: NONE
user: login: Ratonero500
created_at: 2025-03-13T00:59:11Z
body: > Honestly, although I don't like that such scope for role-playing situations is locked in exclusively murder one framework. I don't really understand how this will affect the round. You kill one and replace him to do the same as he did. Who cares who was killed and replaced there? I understand that the main goal of the antag is for the original and the clone to stand next to each other and prove who the original is. But there is no punishment for a mistake. Why not make it so that if the clone survives and lives for about 5 minutes, something unpleasant happens. For example, 2 more clones of other crew members spawn, this will be a punishment for the crew for insufficient attentiveness. Each of them, when the same conditions are met, spawns 2 more clones, and so on. On the 4th-5th cycle, it will be impossible to tell who you are talking to. The original or the clone that replaced him. Successful clones will make the round unusual. A whole new mode is obtained. At the same time, there will always be ghost roles and no one will have to wait. It sounds interesting, but it all falls apart when you use randomly generated clothes from the wardrobe.



Good idea, but i dont think every antag should be round ending threats, i think its good that some antag only affect a few people or even a single one.
author_association: NONE
user: login: K-Dynamic
created_at: 2025-03-13T01:36:13Z
body: Could be fun but that's really dependent on how the clone plays, and fact some players will probably friendly with them.

I'd encourage players to roleplay facing a clone rather than immediately run into the armoury. It doesn't help at least one of them HAS to die.
author_association: CONTRIBUTOR
user: login: Dead-Wasp
created_at: 2025-03-13T05:14:44Z
body: > Could be fun but that's really dependent on how the clone plays, and fact some players will probably friendly with them.
> 
> I'd encourage players to roleplay facing a clone rather than immediately run into the armoury. It doesn't help at least one of them HAS to die.

If it were a free antagonist like a skeleton. You can be a friend of the station, kill your original, or you can just break a lot of laws, leaving a lot of evidence so that the one you're copying will be imprisoned. It would be better for a role-playing game. In the current state, everyone will immediately run to the brig and send an SEC squad at the sight of their clone. But i am will be happy if i wrong. It would also be cool if they could create a clone. For example, as a reaction of a cosmic artifact. I love going into SS13, playing xenobiologist, and creating my own clones. I had 7 clones once. It was fun.
author_association: NONE
user: login: YoungThugSS14
created_at: 2025-03-13T09:15:52Z
body: Someone speed merge this!
author_association: NONE
user: login: ScarKy0
created_at: 2025-03-13T09:25:57Z
body: > Someone speed merge this!

Hand itches to press the merge button.........
author_association: CONTRIBUTOR
user: login: YoungThugSS14
created_at: 2025-03-13T09:28:26Z
body: > > Someone speed merge this!
> 
> Hand itches to press the merge button.........



> > Someone speed merge this!
> 
> Hand itches to press the merge button.........

Quick, when nobody’s looking!
author_association: NONE
user: login: Warpzoned
created_at: 2025-03-13T17:25:36Z
body: > Honestly, although I don't like that such scope for role-playing situations is locked in exclusively murder one framework. I don't really understand how this will affect the round. You kill one and replace him to do the same as he did. Who cares who was killed and replaced there? I understand that the main goal of the antag is for the original and the clone to stand next to each other and prove who the original is. But there is no punishment for a mistake. Why not make it so that if the clone survives and lives for about 5 minutes, something unpleasant happens. For example, 2 more clones of other crew members spawn, this will be a punishment for the crew for insufficient attentiveness. Each of them, when the same conditions are met, spawns 2 more clones, and so on. On the 4th-5th cycle, it will be impossible to tell who you are talking to. The original or the clone that replaced him. Successful clones will make the round unusual. A whole new mode is obtained. At the same time, there will always be ghost roles and no one will have to wait. It sounds interesting, but it all falls apart when you use randomly generated clothes from the wardrobe.

Honestly, given that this is somewhat of a spatiotemporal anomaly I think it'd be better (And somewhat more in-scope for a future PR) to make it so the longer both copies (Original & clone) are present the more frequently anomalies (Sci's) spawn, effectively working either as a "We'll get more points this way! Don't bother with these who's who shenanigans too much" type scenario, where there being a clone is somewhat dismissible given that them being present benefits the station in some way, or a "We've let the clone straddle around for too long! There's too many anomalies!!" type one, which would in contrast incentivize they try and eliminate it
author_association: NONE
user: login: TurboTrackerss14
created_at: 2025-03-13T22:15:46Z
body: Only current contention (lol to late merged) is the wording of some of this code being "Humans" not "humanoids" but this is a larger issue from MindSystem as a whole. 

This should probably adjusted considering we use it for things like "HumanoidAppearance" 
author_association: CONTRIBUTOR
user: login: slarticodefast
created_at: 2025-03-14T20:37:36Z
body: ToDo list for future improvements in case anyone wants to help out:
https://github.com/space-wizards/space-station-14/issues/35831
author_association: MEMBER