BodyPartEffectSystem.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. // SPDX-FileCopyrightText: 2024 gluesniffler <159397573+gluesniffler@users.noreply.github.com>
  2. // SPDX-FileCopyrightText: 2025 Aiden <28298836+Aidenkrz@users.noreply.github.com>
  3. //
  4. // SPDX-License-Identifier: AGPL-3.0-or-later
  5. using Content.Shared._Shitmed.Body.Events;
  6. using Content.Shared.Body.Part;
  7. using Robust.Shared.Prototypes;
  8. using Robust.Shared.Serialization.Manager;
  9. using Robust.Shared.Timing;
  10. using System.Linq;
  11. namespace Content.Shared._Shitmed.BodyEffects;
  12. public partial class BodyPartEffectSystem : EntitySystem
  13. {
  14. [Dependency] private readonly IComponentFactory _compFactory = default!;
  15. [Dependency] private readonly ISerializationManager _serManager = default!;
  16. [Dependency] private readonly IGameTiming _gameTiming = default!;
  17. public override void Initialize()
  18. {
  19. base.Initialize();
  20. SubscribeLocalEvent<BodyPartComponent, BodyPartComponentsModifyEvent>(OnPartComponentsModify);
  21. }
  22. // While I would love to kill this function, problem is that if we happen to have two parts that add the same
  23. // effect, removing one will remove both of them, since we cant tell what the source of a Component is.
  24. public override void Update(float frameTime)
  25. {
  26. base.Update(frameTime);
  27. var query = EntityQueryEnumerator<BodyPartEffectComponent, BodyPartComponent>();
  28. var now = _gameTiming.CurTime;
  29. while (query.MoveNext(out var uid, out var comp, out var part))
  30. {
  31. if (now < comp.NextUpdate || !comp.Active.Any() || part.Body is not { } body)
  32. continue;
  33. comp.NextUpdate = now + comp.Delay;
  34. AddComponents(body, uid, comp.Active);
  35. }
  36. }
  37. private void OnPartComponentsModify(Entity<BodyPartComponent> partEnt,
  38. ref BodyPartComponentsModifyEvent ev)
  39. {
  40. if (partEnt.Comp.OnAdd != null)
  41. {
  42. if (ev.Add)
  43. AddComponents(ev.Body, partEnt, partEnt.Comp.OnAdd);
  44. else
  45. RemoveComponents(ev.Body, partEnt, partEnt.Comp.OnAdd);
  46. }
  47. if (partEnt.Comp.OnRemove != null)
  48. {
  49. if (ev.Add)
  50. AddComponents(ev.Body, partEnt, partEnt.Comp.OnRemove);
  51. else
  52. RemoveComponents(ev.Body, partEnt, partEnt.Comp.OnRemove);
  53. }
  54. Dirty(partEnt, partEnt.Comp);
  55. }
  56. private void AddComponents(EntityUid body,
  57. EntityUid part,
  58. ComponentRegistry reg,
  59. BodyPartEffectComponent? effectComp = null)
  60. {
  61. if (!Resolve(part, ref effectComp, logMissing: false))
  62. return;
  63. foreach (var (key, comp) in reg)
  64. {
  65. var compType = comp.Component.GetType();
  66. if (HasComp(body, compType))
  67. continue;
  68. var newComp = (Component) _serManager.CreateCopy(comp.Component, notNullableOverride: true);
  69. EntityManager.AddComponent(body, newComp, true);
  70. effectComp.Active[key] = comp;
  71. }
  72. }
  73. private void RemoveComponents(EntityUid body,
  74. EntityUid part,
  75. ComponentRegistry reg,
  76. BodyPartEffectComponent? effectComp = null)
  77. {
  78. if (!Resolve(part, ref effectComp, logMissing: false))
  79. return;
  80. foreach (var (key, comp) in reg)
  81. {
  82. RemComp(body, comp.Component.GetType());
  83. effectComp.Active.Remove(key);
  84. }
  85. }
  86. }