Add paradox clone to admin antag control (#36105)
* make paradox clone receive the original's objectives * antag control verb * rename verb
This commit is contained in:
@@ -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<EntityPrototype>]
|
||||
private const string DefaultTraitorRule = "Traitor";
|
||||
@@ -36,6 +39,8 @@ public sealed partial class AdminVerbSystem
|
||||
[ValidatePrototypeId<StartingGearPrototype>]
|
||||
private const string PirateGearId = "PirateGear";
|
||||
|
||||
private readonly EntProtoId _paradoxCloneRuleId = "ParadoxCloneSpawn";
|
||||
|
||||
// All antag verbs have names so invokeverb works.
|
||||
private void AddAntagVerbs(GetVerbsEvent<Verb> 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<ParadoxCloneRuleComponent>(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<HumanoidAppearanceComponent>(args.Target)) // only humanoids can be cloned
|
||||
args.Verbs.Add(paradox);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,12 +22,19 @@ public sealed partial class ParadoxCloneRuleComponent : Component
|
||||
[DataField]
|
||||
public EntProtoId GibProto = "MobParadoxTimed";
|
||||
|
||||
/// <summary>
|
||||
/// Entity of the original player.
|
||||
/// Gets randomly chosen from all alive players if not specified.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityUid? OriginalBody;
|
||||
|
||||
/// <summary>
|
||||
/// Mind entity of the original player.
|
||||
/// Gets assigned when cloning.
|
||||
/// </summary>
|
||||
[DataField]
|
||||
public EntityUid? Original;
|
||||
public EntityUid? OriginalMind;
|
||||
|
||||
/// <summary>
|
||||
/// Whitelist for Objectives to be copied to the clone.
|
||||
|
||||
@@ -47,28 +47,42 @@ public sealed class ParadoxCloneRuleSystem : GameRuleSystem<ParadoxCloneRuleComp
|
||||
if (args.Session?.AttachedEntity is not { } spawner)
|
||||
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)
|
||||
if (ent.Comp.OriginalBody != null) // target was overridden, for example by admin antag control
|
||||
{
|
||||
Log.Warning("Could not find any alive players to create a paradox clone from!");
|
||||
return;
|
||||
if (Deleted(ent.Comp.OriginalBody.Value) || !_mind.TryGetMind(ent.Comp.OriginalBody.Value, out var originalMindId, out var _))
|
||||
{
|
||||
Log.Warning("Could not find mind of target player to paradox clone!");
|
||||
return;
|
||||
}
|
||||
ent.Comp.OriginalMind = originalMindId;
|
||||
}
|
||||
else
|
||||
{
|
||||
// get possible targets
|
||||
var allAliveHumanoids = _mind.GetAliveHumans();
|
||||
|
||||
// we already checked when starting the gamerule, but someone might have died since then.
|
||||
if (allAliveHumanoids.Count == 0)
|
||||
{
|
||||
Log.Warning("Could not find any alive players to create a paradox clone from!");
|
||||
return;
|
||||
}
|
||||
|
||||
// pick a random player
|
||||
var randomHumanoidMind = _random.Pick(allAliveHumanoids);
|
||||
ent.Comp.OriginalMind = randomHumanoidMind;
|
||||
ent.Comp.OriginalBody = randomHumanoidMind.Comp.OwnedEntity;
|
||||
|
||||
}
|
||||
|
||||
// pick a random player
|
||||
var playerToClone = _random.Pick(allHumans);
|
||||
var bodyToClone = playerToClone.Comp.OwnedEntity;
|
||||
|
||||
if (bodyToClone == null || !_cloning.TryCloning(bodyToClone.Value, _transform.GetMapCoordinates(spawner), ent.Comp.Settings, out var clone))
|
||||
if (ent.Comp.OriginalBody == null || !_cloning.TryCloning(ent.Comp.OriginalBody.Value, _transform.GetMapCoordinates(spawner), ent.Comp.Settings, out var clone))
|
||||
{
|
||||
Log.Error($"Unable to make a paradox clone of entity {ToPrettyString(bodyToClone)}");
|
||||
Log.Error($"Unable to make a paradox clone of entity {ToPrettyString(ent.Comp.OriginalBody)}");
|
||||
return;
|
||||
}
|
||||
|
||||
var targetComp = EnsureComp<TargetOverrideComponent>(clone.Value);
|
||||
targetComp.Target = playerToClone.Owner; // set the kill target
|
||||
targetComp.Target = ent.Comp.OriginalMind; // set the kill target
|
||||
|
||||
var gibComp = EnsureComp<GibOnRoundEndComponent>(clone.Value);
|
||||
gibComp.SpawnProto = ent.Comp.GibProto;
|
||||
@@ -78,17 +92,16 @@ public sealed class ParadoxCloneRuleSystem : GameRuleSystem<ParadoxCloneRuleComp
|
||||
_sensor.SetAllSensors(clone.Value, SuitSensorMode.SensorOff);
|
||||
|
||||
args.Entity = clone;
|
||||
ent.Comp.Original = playerToClone.Owner;
|
||||
}
|
||||
|
||||
private void AfterAntagEntitySelected(Entity<ParadoxCloneRuleComponent> 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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
BIN
Resources/Textures/Interface/Misc/job_icons.rsi/ParadoxClone.png
Normal file
BIN
Resources/Textures/Interface/Misc/job_icons.rsi/ParadoxClone.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1.6 KiB |
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/e71d6c4fba5a51f99b81c295dcaec4fc2f58fb19/icons/mob/screen1.dmi | Brigmedic icon made by PuroSlavKing (Github) | Zombie icon made by RamZ | Zookeper by netwy (discort) | Rev and Head Rev icon taken from https://tgstation13.org/wiki/HUD and edited by coolmankid12345 (Discord) | Mindshield icon taken from https://github.com/tgstation/tgstation/blob/ce6beb8a4d61235d9a597a7126c407160ed674ea/icons/mob/huds/hud.dmi | Admin recolored from MedicalIntern by TsjipTsjip | StationAi resprite to 8x8 size by lunarcomets | Service Worker resprite by anno_midi (Discord) and spanky-spanky (Github) | service icons darkened by frobnic8 (Discord and Github)",
|
||||
"copyright": "Taken from https://github.com/vgstation-coders/vgstation13/blob/e71d6c4fba5a51f99b81c295dcaec4fc2f58fb19/icons/mob/screen1.dmi | Brigmedic icon made by PuroSlavKing (Github) | Zombie icon made by RamZ | Zookeper by netwy (discort) | Rev and Head Rev icon taken from https://tgstation13.org/wiki/HUD and edited by coolmankid12345 (Discord) | Mindshield icon taken from https://github.com/tgstation/tgstation/blob/ce6beb8a4d61235d9a597a7126c407160ed674ea/icons/mob/huds/hud.dmi | Admin recolored from MedicalIntern by TsjipTsjip | StationAi resprite to 8x8 size by lunarcomets | Service Worker resprite by anno_midi (Discord) and spanky-spanky (Github) | service icons darkened by frobnic8 (Discord and Github) | paradoxClone taken from tg station at commit https://github.com/tgstation/tgstation/commit/d0db1ff267557017ae7bde68e6490e70cbb6e42f and modifed by slarticodefast (Github)",
|
||||
|
||||
"size": {
|
||||
"x": 8,
|
||||
@@ -191,6 +191,9 @@
|
||||
},
|
||||
{
|
||||
"name": "Admin"
|
||||
},
|
||||
{
|
||||
"name": "ParadoxClone"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user