CursedMaskSystem.cs 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. using Content.Server.Administration.Logs;
  2. using Content.Server.Ghost;
  3. using Content.Server.Mind;
  4. using Content.Server.NPC;
  5. using Content.Server.NPC.HTN;
  6. using Content.Server.NPC.Systems;
  7. using Content.Server.Popups;
  8. using Content.Shared.Clothing;
  9. using Content.Shared.Clothing.Components;
  10. using Content.Shared.Database;
  11. using Content.Shared.NPC.Components;
  12. using Content.Shared.NPC.Systems;
  13. using Content.Shared.Players;
  14. using Content.Shared.Popups;
  15. using Robust.Shared.Player;
  16. using Robust.Shared.Prototypes;
  17. namespace Content.Server.Clothing.Systems;
  18. /// <inheritdoc/>
  19. public sealed class CursedMaskSystem : SharedCursedMaskSystem
  20. {
  21. [Dependency] private readonly IAdminLogManager _adminLog = default!;
  22. [Dependency] private readonly GhostSystem _ghostSystem = default!;
  23. [Dependency] private readonly HTNSystem _htn = default!;
  24. [Dependency] private readonly MindSystem _mind = default!;
  25. [Dependency] private readonly NPCSystem _npc = default!;
  26. [Dependency] private readonly NpcFactionSystem _npcFaction = default!;
  27. [Dependency] private readonly PopupSystem _popup = default!;
  28. // We can't store this info on the component easily
  29. private static readonly ProtoId<HTNCompoundPrototype> TakeoverRootTask = "SimpleHostileCompound";
  30. protected override void TryTakeover(Entity<CursedMaskComponent> ent, EntityUid wearer)
  31. {
  32. if (ent.Comp.CurrentState != CursedMaskExpression.Anger)
  33. return;
  34. if (TryComp<ActorComponent>(wearer, out var actor) && actor.PlayerSession.GetMind() is { } mind)
  35. {
  36. var session = actor.PlayerSession;
  37. if (!_ghostSystem.OnGhostAttempt(mind, false))
  38. return;
  39. ent.Comp.StolenMind = mind;
  40. _popup.PopupEntity(Loc.GetString("cursed-mask-takeover-popup"), wearer, session, PopupType.LargeCaution);
  41. _adminLog.Add(LogType.Action,
  42. LogImpact.Extreme,
  43. $"{ToPrettyString(wearer):player} had their body taken over and turned into an enemy through the cursed mask {ToPrettyString(ent):entity}");
  44. }
  45. var npcFaction = EnsureComp<NpcFactionMemberComponent>(wearer);
  46. ent.Comp.OldFactions.Clear();
  47. ent.Comp.OldFactions.UnionWith(npcFaction.Factions);
  48. _npcFaction.ClearFactions((wearer, npcFaction), false);
  49. _npcFaction.AddFaction((wearer, npcFaction), ent.Comp.CursedMaskFaction);
  50. ent.Comp.HasNpc = !EnsureComp<HTNComponent>(wearer, out var htn);
  51. htn.RootTask = new HTNCompoundTask { Task = TakeoverRootTask };
  52. htn.Blackboard.SetValue(NPCBlackboard.Owner, wearer);
  53. _npc.WakeNPC(wearer, htn);
  54. _htn.Replan(htn);
  55. }
  56. protected override void OnClothingUnequip(Entity<CursedMaskComponent> ent, ref ClothingGotUnequippedEvent args)
  57. {
  58. // If we are taking off the cursed mask
  59. if (ent.Comp.CurrentState == CursedMaskExpression.Anger)
  60. {
  61. if (ent.Comp.HasNpc)
  62. RemComp<HTNComponent>(args.Wearer);
  63. var npcFaction = EnsureComp<NpcFactionMemberComponent>(args.Wearer);
  64. _npcFaction.RemoveFaction((args.Wearer, npcFaction), ent.Comp.CursedMaskFaction, false);
  65. _npcFaction.AddFactions((args.Wearer, npcFaction), ent.Comp.OldFactions);
  66. ent.Comp.HasNpc = false;
  67. ent.Comp.OldFactions.Clear();
  68. if (Exists(ent.Comp.StolenMind))
  69. {
  70. _mind.TransferTo(ent.Comp.StolenMind.Value, args.Wearer);
  71. _adminLog.Add(LogType.Action,
  72. LogImpact.Extreme,
  73. $"{ToPrettyString(args.Wearer):player} was restored to their body after the removal of {ToPrettyString(ent):entity}.");
  74. ent.Comp.StolenMind = null;
  75. }
  76. }
  77. RandomizeCursedMask(ent, args.Wearer);
  78. }
  79. }