From 7c44038f637a55fc4593cafc2697aa7f4378f974 Mon Sep 17 00:00:00 2001 From: slarticodefast <161409025+slarticodefast@users.noreply.github.com> Date: Thu, 27 Mar 2025 18:04:25 +0100 Subject: [PATCH] Add paradox clone to admin antag control (#36105) * make paradox clone receive the original's objectives * antag control verb * rename verb --- .../Systems/AdminVerbSystem.Antags.cs | 29 +++++++++++ .../Components/ParadoxCloneRuleComponent.cs | 9 +++- .../Rules/ParadoxCloneRuleSystem.cs | 45 +++++++++++------- .../Locale/en-US/administration/antag.ftl | 2 + .../Misc/job_icons.rsi/ParadoxClone.png | Bin 0 -> 1670 bytes .../Interface/Misc/job_icons.rsi/meta.json | 5 +- 6 files changed, 72 insertions(+), 18 deletions(-) create mode 100644 Resources/Textures/Interface/Misc/job_icons.rsi/ParadoxClone.png diff --git a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs index b8a05c3e8f..79c5c86fe1 100644 --- a/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs +++ b/Content.Server/Administration/Systems/AdminVerbSystem.Antags.cs @@ -1,9 +1,11 @@ using Content.Server.Administration.Commands; using Content.Server.Antag; +using Content.Server.GameTicking; using Content.Server.GameTicking.Rules.Components; using Content.Server.Zombies; using Content.Shared.Administration; using Content.Shared.Database; +using Content.Shared.Humanoid; using Content.Shared.Mind.Components; using Content.Shared.Roles; using Content.Shared.Verbs; @@ -17,6 +19,7 @@ public sealed partial class AdminVerbSystem { [Dependency] private readonly AntagSelectionSystem _antag = default!; [Dependency] private readonly ZombieSystem _zombie = default!; + [Dependency] private readonly GameTicker _gameTicker = default!; [ValidatePrototypeId] private const string DefaultTraitorRule = "Traitor"; @@ -36,6 +39,8 @@ public sealed partial class AdminVerbSystem [ValidatePrototypeId] private const string PirateGearId = "PirateGear"; + private readonly EntProtoId _paradoxCloneRuleId = "ParadoxCloneSpawn"; + // All antag verbs have names so invokeverb works. private void AddAntagVerbs(GetVerbsEvent args) { @@ -157,5 +162,29 @@ public sealed partial class AdminVerbSystem Message = string.Join(": ", thiefName, Loc.GetString("admin-verb-make-thief")), }; args.Verbs.Add(thief); + + var paradoxCloneName = Loc.GetString("admin-verb-text-make-paradox-clone"); + Verb paradox = new() + { + Text = paradoxCloneName, + Category = VerbCategory.Antag, + Icon = new SpriteSpecifier.Rsi(new("/Textures/Interface/Misc/job_icons.rsi"), "ParadoxClone"), + Act = () => + { + var ruleEnt = _gameTicker.AddGameRule(_paradoxCloneRuleId); + + if (!TryComp(ruleEnt, out var paradoxCloneRuleComp)) + return; + + paradoxCloneRuleComp.OriginalBody = args.Target; // override the target player + + _gameTicker.StartGameRule(ruleEnt); + }, + Impact = LogImpact.High, + Message = string.Join(": ", paradoxCloneName, Loc.GetString("admin-verb-make-paradox-clone")), + }; + + if (HasComp(args.Target)) // only humanoids can be cloned + args.Verbs.Add(paradox); } } diff --git a/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs b/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs index 143659748a..e28a0bc35f 100644 --- a/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs +++ b/Content.Server/GameTicking/Rules/Components/ParadoxCloneRuleComponent.cs @@ -22,12 +22,19 @@ public sealed partial class ParadoxCloneRuleComponent : Component [DataField] public EntProtoId GibProto = "MobParadoxTimed"; + /// + /// Entity of the original player. + /// Gets randomly chosen from all alive players if not specified. + /// + [DataField] + public EntityUid? OriginalBody; + /// /// Mind entity of the original player. /// Gets assigned when cloning. /// [DataField] - public EntityUid? Original; + public EntityUid? OriginalMind; /// /// Whitelist for Objectives to be copied to the clone. diff --git a/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs b/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs index 8a5cab85b8..ab8864caaa 100644 --- a/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs +++ b/Content.Server/GameTicking/Rules/ParadoxCloneRuleSystem.cs @@ -47,28 +47,42 @@ public sealed class ParadoxCloneRuleSystem : GameRuleSystem(clone.Value); - targetComp.Target = playerToClone.Owner; // set the kill target + targetComp.Target = ent.Comp.OriginalMind; // set the kill target var gibComp = EnsureComp(clone.Value); gibComp.SpawnProto = ent.Comp.GibProto; @@ -78,17 +92,16 @@ public sealed class ParadoxCloneRuleSystem : GameRuleSystem ent, ref AfterAntagEntitySelectedEvent args) { - if (ent.Comp.Original == null) + if (ent.Comp.OriginalMind == null) return; if (!_mind.TryGetMind(args.EntityUid, out var cloneMindId, out var cloneMindComp)) return; - _mind.CopyObjectives(ent.Comp.Original.Value, (cloneMindId, cloneMindComp), ent.Comp.ObjectiveWhitelist, ent.Comp.ObjectiveBlacklist); + _mind.CopyObjectives(ent.Comp.OriginalMind.Value, (cloneMindId, cloneMindComp), ent.Comp.ObjectiveWhitelist, ent.Comp.ObjectiveBlacklist); } } diff --git a/Resources/Locale/en-US/administration/antag.ftl b/Resources/Locale/en-US/administration/antag.ftl index ef4ad98c7c..1433cc1dc4 100644 --- a/Resources/Locale/en-US/administration/antag.ftl +++ b/Resources/Locale/en-US/administration/antag.ftl @@ -6,6 +6,7 @@ admin-verb-make-nuclear-operative = Make target into a lone Nuclear Operative. admin-verb-make-pirate = Make the target into a pirate. Note this doesn't configure the game rule. admin-verb-make-head-rev = Make the target into a Head Revolutionary. admin-verb-make-thief = Make the target into a thief. +admin-verb-make-paradox-clone = Create a Paradox Clone ghost role of the target. admin-verb-text-make-traitor = Make Traitor admin-verb-text-make-initial-infected = Make Initial Infected @@ -14,5 +15,6 @@ admin-verb-text-make-nuclear-operative = Make Nuclear Operative admin-verb-text-make-pirate = Make Pirate admin-verb-text-make-head-rev = Make Head Rev admin-verb-text-make-thief = Make Thief +admin-verb-text-make-paradox-clone = Create Paradox Clone admin-overlay-antag-classic = ANTAG diff --git a/Resources/Textures/Interface/Misc/job_icons.rsi/ParadoxClone.png b/Resources/Textures/Interface/Misc/job_icons.rsi/ParadoxClone.png new file mode 100644 index 0000000000000000000000000000000000000000..6d1add3d210018ee4bbe74fd982a51743342f2df GIT binary patch literal 1670 zcmbVNO>f*p7&Z#6no2EPkU}|NxvErD#vXs}dKxz*yJ@omhbUdC=`G{&c-P9>=LD7tUWg zFGxIOFp;P< z6aiPqNd{<1T3#7vl}2)zbJAXddeN!$9~r0{dnUj=eLhGyXxuLRh zLtY*eAV_#g<#94d3o`bU2`_b}7tf)tm!C2Kq4oXR#;ID8q&88M>j&V*EFh<% zi|%2@wQXLAVb1va0m!^ud6SV=&S@#~t`LKHqPFIeWkXjD`RbiG4aKN<@7M<3rX}|j z$eN9?iFB)Ln8a!lY+l1U!FUSwMHokiC!ls0<0`=?pinX)E$K_aAtRB<6ABK;3GHz$ zOM8l3hmo|zK;&Q;)S1WUJFV7ME~0n<3&r-WHMz6ia&*^mkfG`mxxP<2X;IRY@lM-Q zAUJ9qha_+trX55svM}e!YFI9EEjK_Bjttv%LrSA?zP~NluquIS|MWD3f&s^W@@O+M zZDzR0j&utJx@99bvI0bPBM1VQ>9)z{Y#-+_97sAi&RVGofsqAaGq6|_MGj?%29}8^ zvt7u96GlzQOCvO^vY%8E*@z3s@!{+s-RAqV(IA#5#X~5o4uz+%sv0=>Go6l4iN`Bh zp6ws?Igq}fN~UHC5tSpF^VJ^2?xj_zJx_c=4_++&)lxatbVB;GRr`OW&%(m`H0^Qd zu$odiqgB0VniTD1z9wtO`qmr{&9EBQT^K&$|MB1^bolF?_G)+OZT9%d zla