RadiationSystem.Blockers.cs 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. using Content.Server.Radiation.Components;
  2. using Content.Shared.Doors;
  3. using Content.Shared.Doors.Components;
  4. using Robust.Shared.Map.Components;
  5. namespace Content.Server.Radiation.Systems;
  6. // create and update map of radiation blockers
  7. public partial class RadiationSystem
  8. {
  9. private void InitRadBlocking()
  10. {
  11. SubscribeLocalEvent<RadiationBlockerComponent, ComponentInit>(OnInit);
  12. SubscribeLocalEvent<RadiationBlockerComponent, ComponentShutdown>(OnShutdown);
  13. SubscribeLocalEvent<RadiationBlockerComponent, AnchorStateChangedEvent>(OnAnchorChanged);
  14. SubscribeLocalEvent<RadiationBlockerComponent, ReAnchorEvent>(OnReAnchor);
  15. SubscribeLocalEvent<RadiationBlockerComponent, DoorStateChangedEvent>(OnDoorChanged);
  16. SubscribeLocalEvent<RadiationGridResistanceComponent, EntityTerminatingEvent>(OnGridRemoved);
  17. }
  18. private void OnInit(EntityUid uid, RadiationBlockerComponent component, ComponentInit args)
  19. {
  20. if (!component.Enabled)
  21. return;
  22. AddTile(uid, component);
  23. }
  24. private void OnShutdown(EntityUid uid, RadiationBlockerComponent component, ComponentShutdown args)
  25. {
  26. if (component.Enabled)
  27. return;
  28. RemoveTile(uid, component);
  29. }
  30. private void OnAnchorChanged(EntityUid uid, RadiationBlockerComponent component, ref AnchorStateChangedEvent args)
  31. {
  32. if (args.Anchored)
  33. {
  34. AddTile(uid, component);
  35. }
  36. else
  37. {
  38. RemoveTile(uid, component);
  39. }
  40. }
  41. private void OnReAnchor(EntityUid uid, RadiationBlockerComponent component, ref ReAnchorEvent args)
  42. {
  43. // probably grid was split
  44. // we need to remove entity from old resistance map
  45. RemoveTile(uid, component);
  46. // and move it to the new one
  47. AddTile(uid, component);
  48. }
  49. private void OnDoorChanged(EntityUid uid, RadiationBlockerComponent component, DoorStateChangedEvent args)
  50. {
  51. switch (args.State)
  52. {
  53. case DoorState.Open:
  54. SetEnabled(uid, false, component);
  55. break;
  56. case DoorState.Closed:
  57. SetEnabled(uid, true, component);
  58. break;
  59. }
  60. }
  61. private void OnGridRemoved(EntityUid uid, RadiationGridResistanceComponent component, ref EntityTerminatingEvent args)
  62. {
  63. // grid is about to be removed - lets delete grid component first
  64. // this should save a bit performance when blockers will be deleted
  65. RemComp(uid, component);
  66. }
  67. public void SetEnabled(EntityUid uid, bool isEnabled, RadiationBlockerComponent? component = null)
  68. {
  69. if (!Resolve(uid, ref component))
  70. return;
  71. if (isEnabled == component.Enabled)
  72. return;
  73. component.Enabled = isEnabled;
  74. if (!component.Enabled)
  75. RemoveTile(uid, component);
  76. else
  77. AddTile(uid, component);
  78. }
  79. private void AddTile(EntityUid uid, RadiationBlockerComponent component)
  80. {
  81. // check that last position was removed
  82. if (component.CurrentPosition != null)
  83. {
  84. RemoveTile(uid, component);
  85. }
  86. // check if entity even provide some rad protection
  87. if (!component.Enabled || component.RadResistance <= 0)
  88. return;
  89. // check if it's on a grid
  90. var trs = Transform(uid);
  91. if (!trs.Anchored || !TryComp(trs.GridUid, out MapGridComponent? grid))
  92. return;
  93. // save resistance into rad protection grid
  94. var gridId = trs.GridUid.Value;
  95. var tilePos = grid.TileIndicesFor(trs.Coordinates);
  96. AddToTile(gridId, tilePos, component.RadResistance);
  97. // and remember it as last valid position
  98. component.CurrentPosition = (gridId, tilePos);
  99. }
  100. private void RemoveTile(EntityUid uid, RadiationBlockerComponent component)
  101. {
  102. // check if blocker was placed on grid before component was removed
  103. if (component.CurrentPosition == null)
  104. return;
  105. var (gridId, tilePos) = component.CurrentPosition.Value;
  106. // try to remove
  107. RemoveFromTile(gridId, tilePos, component.RadResistance);
  108. component.CurrentPosition = null;
  109. }
  110. private void AddToTile(EntityUid gridUid, Vector2i tilePos, float radResistance)
  111. {
  112. // get existing rad resistance grid or create it if it doesn't exist
  113. var resistance = EnsureComp<RadiationGridResistanceComponent>(gridUid);
  114. var grid = resistance.ResistancePerTile;
  115. // add to existing cell more rad resistance
  116. var newResistance = radResistance;
  117. if (grid.TryGetValue(tilePos, out var existingResistance))
  118. {
  119. newResistance += existingResistance;
  120. }
  121. grid[tilePos] = newResistance;
  122. }
  123. private void RemoveFromTile(EntityUid gridUid, Vector2i tilePos, float radResistance)
  124. {
  125. // get grid
  126. if (!TryComp(gridUid, out RadiationGridResistanceComponent? resistance))
  127. return;
  128. var grid = resistance.ResistancePerTile;
  129. // subtract resistance from tile
  130. if (!grid.TryGetValue(tilePos, out var existingResistance))
  131. return;
  132. existingResistance -= radResistance;
  133. // remove tile from grid if no resistance left
  134. if (existingResistance > 0)
  135. grid[tilePos] = existingResistance;
  136. else
  137. {
  138. grid.Remove(tilePos);
  139. if (grid.Count == 0)
  140. RemComp(gridUid, resistance);
  141. }
  142. }
  143. }