ParadoxCloneRuleSystem.cs 3.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. using Content.Server.Antag;
  2. using Content.Server.Cloning;
  3. using Content.Server.GameTicking.Rules.Components;
  4. using Content.Server.Medical.SuitSensors;
  5. using Content.Server.Objectives.Components;
  6. using Content.Shared.GameTicking.Components;
  7. using Content.Shared.Gibbing.Components;
  8. using Content.Shared.Medical.SuitSensor;
  9. using Content.Shared.Mind;
  10. using Robust.Shared.Random;
  11. namespace Content.Server.GameTicking.Rules;
  12. public sealed class ParadoxCloneRuleSystem : GameRuleSystem<ParadoxCloneRuleComponent>
  13. {
  14. [Dependency] private readonly SharedTransformSystem _transform = default!;
  15. [Dependency] private readonly SharedMindSystem _mind = default!;
  16. [Dependency] private readonly IRobustRandom _random = default!;
  17. [Dependency] private readonly CloningSystem _cloning = default!;
  18. [Dependency] private readonly SuitSensorSystem _sensor = default!;
  19. public override void Initialize()
  20. {
  21. base.Initialize();
  22. SubscribeLocalEvent<ParadoxCloneRuleComponent, AntagSelectEntityEvent>(OnAntagSelectEntity);
  23. SubscribeLocalEvent<ParadoxCloneRuleComponent, AfterAntagEntitySelectedEvent>(AfterAntagEntitySelected);
  24. }
  25. protected override void Started(EntityUid uid, ParadoxCloneRuleComponent component, GameRuleComponent gameRule, GameRuleStartedEvent args)
  26. {
  27. base.Started(uid, component, gameRule, args);
  28. // check if we got enough potential cloning targets, otherwise cancel the gamerule so that the ghost role does not show up
  29. var allHumans = _mind.GetAliveHumans();
  30. if (allHumans.Count == 0)
  31. {
  32. Log.Info("Could not find any alive players to create a paradox clone from! Ending gamerule.");
  33. ForceEndSelf(uid, gameRule);
  34. }
  35. }
  36. // we have to do the spawning here so we can transfer the mind to the correct entity and can assign the objectives correctly
  37. private void OnAntagSelectEntity(Entity<ParadoxCloneRuleComponent> ent, ref AntagSelectEntityEvent args)
  38. {
  39. if (args.Session?.AttachedEntity is not { } spawner)
  40. return;
  41. // get possible targets
  42. var allHumans = _mind.GetAliveHumans();
  43. // we already checked when starting the gamerule, but someone might have died since then.
  44. if (allHumans.Count == 0)
  45. {
  46. Log.Warning("Could not find any alive players to create a paradox clone from!");
  47. return;
  48. }
  49. // pick a random player
  50. var playerToClone = _random.Pick(allHumans);
  51. var bodyToClone = playerToClone.Comp.OwnedEntity;
  52. if (bodyToClone == null || !_cloning.TryCloning(bodyToClone.Value, _transform.GetMapCoordinates(spawner), ent.Comp.Settings, out var clone))
  53. {
  54. Log.Error($"Unable to make a paradox clone of entity {ToPrettyString(bodyToClone)}");
  55. return;
  56. }
  57. var targetComp = EnsureComp<TargetOverrideComponent>(clone.Value);
  58. targetComp.Target = playerToClone.Owner; // set the kill target
  59. var gibComp = EnsureComp<GibOnRoundEndComponent>(clone.Value);
  60. gibComp.SpawnProto = ent.Comp.GibProto;
  61. gibComp.PreventGibbingObjectives = new() { "ParadoxCloneKillObjective" }; // don't gib them if they killed the original.
  62. // turn their suit sensors off so they don't immediately get noticed
  63. _sensor.SetAllSensors(clone.Value, SuitSensorMode.SensorOff);
  64. args.Entity = clone;
  65. ent.Comp.Original = playerToClone.Owner;
  66. }
  67. private void AfterAntagEntitySelected(Entity<ParadoxCloneRuleComponent> ent, ref AfterAntagEntitySelectedEvent args)
  68. {
  69. if (ent.Comp.Original == null)
  70. return;
  71. if (!_mind.TryGetMind(args.EntityUid, out var cloneMindId, out var cloneMindComp))
  72. return;
  73. _mind.CopyObjectives(ent.Comp.Original.Value, (cloneMindId, cloneMindComp), ent.Comp.ObjectiveWhitelist, ent.Comp.ObjectiveBlacklist);
  74. }
  75. }