]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Show paradox clones in deadchat (#35940)
authorslarticodefast <161409025+slarticodefast@users.noreply.github.com>
Wed, 26 Mar 2025 15:30:14 +0000 (16:30 +0100)
committerGitHub <noreply@github.com>
Wed, 26 Mar 2025 15:30:14 +0000 (16:30 +0100)
show clones in deadchat

Content.Server/Ghost/GhostSystem.cs
Content.Server/Roles/ParadoxCloneRoleComponent.cs
Content.Server/Roles/ParadoxCloneRoleSystem.cs [new file with mode: 0644]
Content.Shared/Mind/SharedMindSystem.Relay.cs [new file with mode: 0644]
Content.Shared/Mind/SharedMindSystem.cs
Resources/Locale/en-US/paradox-clone/role.ftl

index 1ca96889cf783a55f5311d7369db27111a56b493..e7125ee4f24d11f58f837c19ccf917b20f2646bb 100644 (file)
@@ -24,6 +24,7 @@ using Content.Shared.Mobs.Components;
 using Content.Shared.Mobs.Systems;
 using Content.Shared.Movement.Events;
 using Content.Shared.Movement.Systems;
+using Content.Shared.NameModifier.EntitySystems;
 using Content.Shared.Popups;
 using Content.Shared.Storage.Components;
 using Content.Shared.Tag;
@@ -66,6 +67,7 @@ namespace Content.Server.Ghost
         [Dependency] private readonly SharedPopupSystem _popup = default!;
         [Dependency] private readonly IRobustRandom _random = default!;
         [Dependency] private readonly TagSystem _tag = default!;
+        [Dependency] private readonly NameModifierSystem _nameMod = default!;
 
         private EntityQuery<GhostComponent> _ghostQuery;
         private EntityQuery<PhysicsComponent> _physicsQuery;
@@ -495,6 +497,10 @@ namespace Content.Server.Ghost
             else
                 _minds.TransferTo(mind.Owner, ghost, mind: mind.Comp);
             Log.Debug($"Spawned ghost \"{ToPrettyString(ghost)}\" for {mind.Comp.CharacterName}.");
+
+            // we changed the entity name above
+            // we have to call this after the mind has been transferred since some mind roles modify the ghost's name
+            _nameMod.RefreshNameModifiers(ghost);
             return ghost;
         }
 
index d55cd34da4e354a4046b4b011dd7553d94b36122..32ebb2fe2da39bf1eb44b319a9c78fdc954b4346 100644 (file)
@@ -6,4 +6,12 @@ namespace Content.Server.Roles;
 ///     Added to mind role entities to tag that they are a paradox clone.
 /// </summary>
 [RegisterComponent]
-public sealed partial class ParadoxCloneRoleComponent : BaseMindRoleComponent;
+public sealed partial class ParadoxCloneRoleComponent : BaseMindRoleComponent
+{
+    /// <summary>
+    ///     Name modifer applied to the player when they turn into a ghost.
+    ///     Needed to be able to keep the original and the clone apart in dead chat.
+    /// </summary>
+    [DataField]
+    public LocId? NameModifier = "paradox-clone-ghost-name-modifier";
+}
diff --git a/Content.Server/Roles/ParadoxCloneRoleSystem.cs b/Content.Server/Roles/ParadoxCloneRoleSystem.cs
new file mode 100644 (file)
index 0000000..83e23fe
--- /dev/null
@@ -0,0 +1,32 @@
+using Content.Shared.Ghost;
+using Content.Shared.Mind;
+using Content.Shared.NameModifier.EntitySystems;
+using Content.Shared.Roles;
+
+namespace Content.Server.Roles;
+
+/// <summary>
+///     System responsible for giving a ghost of a paradox clone a name modifier.
+/// </summary>
+public sealed class ParadoxCloneRoleSystem : EntitySystem
+{
+    public override void Initialize()
+    {
+        base.Initialize();
+
+        SubscribeLocalEvent<ParadoxCloneRoleComponent, MindRelayedEvent<RefreshNameModifiersEvent>>(OnRefreshNameModifiers);
+    }
+
+    private void OnRefreshNameModifiers(Entity<ParadoxCloneRoleComponent> ent, ref MindRelayedEvent<RefreshNameModifiersEvent> args)
+    {
+        if (!TryComp<MindRoleComponent>(ent.Owner, out var roleComp))
+            return;
+
+        // only show for ghosts
+        if (!HasComp<GhostComponent>(roleComp.Mind.Comp.OwnedEntity))
+            return;
+
+        if (ent.Comp.NameModifier != null)
+            args.Args.AddModifier(ent.Comp.NameModifier.Value, 50);
+    }
+}
diff --git a/Content.Shared/Mind/SharedMindSystem.Relay.cs b/Content.Shared/Mind/SharedMindSystem.Relay.cs
new file mode 100644 (file)
index 0000000..60ad2fc
--- /dev/null
@@ -0,0 +1,48 @@
+using Content.Shared.NameModifier.EntitySystems;
+using Content.Shared.Mind.Components;
+
+namespace Content.Shared.Mind;
+
+/// <summary>
+///     Relays events raised on a mobs body to its mind and mind role entities.
+///     Useful for events that should be raised both on the body and the mind.
+/// </summary>
+public abstract partial class SharedMindSystem : EntitySystem
+{
+    public void InitializeRelay()
+    {
+        // for name modifiers that depend on certain mind roles
+        SubscribeLocalEvent<MindContainerComponent, RefreshNameModifiersEvent>(RelayRefToMind);
+    }
+
+    protected void RelayToMind<T>(EntityUid uid, MindContainerComponent component, T args) where T : class
+    {
+        var ev = new MindRelayedEvent<T>(args);
+
+        if (TryGetMind(uid, out var mindId, out var mindComp, component))
+        {
+            RaiseLocalEvent(mindId, ref ev);
+
+            foreach (var role in mindComp.MindRoles)
+                RaiseLocalEvent(role, ref ev);
+        }
+    }
+
+    protected void RelayRefToMind<T>(EntityUid uid, MindContainerComponent component, ref T args) where T : class
+    {
+        var ev = new MindRelayedEvent<T>(args);
+
+        if (TryGetMind(uid, out var mindId, out var mindComp, component))
+        {
+            RaiseLocalEvent(mindId, ref ev);
+
+            foreach (var role in mindComp.MindRoles)
+                RaiseLocalEvent(role, ref ev);
+        }
+
+        args = ev.Args;
+    }
+}
+
+[ByRefEvent]
+public record struct MindRelayedEvent<TEvent>(TEvent Args);
index fc1be3f1ba0328427fa06a565184319b833383be..b2e053f5f1d00f84f45ec40a259aafb72f2362d2 100644 (file)
@@ -19,7 +19,7 @@ using Robust.Shared.Utility;
 
 namespace Content.Shared.Mind;
 
-public abstract class SharedMindSystem : EntitySystem
+public abstract partial class SharedMindSystem : EntitySystem
 {
     [Dependency] private readonly ISharedAdminLogManager _adminLogger = default!;
     [Dependency] private readonly INetManager _net = default!;
@@ -42,6 +42,8 @@ public abstract class SharedMindSystem : EntitySystem
         SubscribeLocalEvent<RoundRestartCleanupEvent>(OnReset);
         SubscribeLocalEvent<MindComponent, ComponentStartup>(OnMindStartup);
         SubscribeLocalEvent<MindComponent, EntityRenamedEvent>(OnRenamed);
+
+        InitializeRelay();
     }
 
     public override void Shutdown()
index 0a73ab4c3bacbfc2d7d73004f2fd226da925b34e..869cd5e7d2a691b6c8d9850db66a4f2d8e963214 100644 (file)
@@ -3,3 +3,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.
+
+paradox-clone-ghost-name-modifier = {$baseName} (clone)