ImmovableRodSystem.cs 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. using Content.Server.Body.Systems;
  2. using Content.Server.Polymorph.Components;
  3. using Content.Server.Popups;
  4. using Content.Shared.Body.Components;
  5. using Content.Shared.Damage;
  6. using Content.Shared.Examine;
  7. using Content.Shared.Popups;
  8. using Robust.Shared.Audio.Systems;
  9. using Robust.Shared.Map;
  10. using Robust.Shared.Map.Components;
  11. using Robust.Shared.Physics.Components;
  12. using Robust.Shared.Physics.Events;
  13. using Robust.Shared.Physics.Systems;
  14. using Robust.Shared.Random;
  15. namespace Content.Server.ImmovableRod;
  16. public sealed class ImmovableRodSystem : EntitySystem
  17. {
  18. [Dependency] private readonly IRobustRandom _random = default!;
  19. [Dependency] private readonly BodySystem _bodySystem = default!;
  20. [Dependency] private readonly PopupSystem _popup = default!;
  21. [Dependency] private readonly SharedPhysicsSystem _physics = default!;
  22. [Dependency] private readonly SharedAudioSystem _audio = default!;
  23. [Dependency] private readonly DamageableSystem _damageable = default!;
  24. [Dependency] private readonly SharedTransformSystem _transform = default!;
  25. [Dependency] private readonly SharedMapSystem _map = default!;
  26. public override void Update(float frameTime)
  27. {
  28. base.Update(frameTime);
  29. // we are deliberately including paused entities. rod hungers for all
  30. foreach (var (rod, trans) in EntityManager.EntityQuery<ImmovableRodComponent, TransformComponent>(true))
  31. {
  32. if (!rod.DestroyTiles)
  33. continue;
  34. if (!TryComp<MapGridComponent>(trans.GridUid, out var grid))
  35. continue;
  36. _map.SetTile(trans.GridUid.Value, grid, trans.Coordinates, Tile.Empty);
  37. }
  38. }
  39. public override void Initialize()
  40. {
  41. base.Initialize();
  42. SubscribeLocalEvent<ImmovableRodComponent, StartCollideEvent>(OnCollide);
  43. SubscribeLocalEvent<ImmovableRodComponent, MapInitEvent>(OnMapInit);
  44. SubscribeLocalEvent<ImmovableRodComponent, ExaminedEvent>(OnExamined);
  45. }
  46. private void OnMapInit(EntityUid uid, ImmovableRodComponent component, MapInitEvent args)
  47. {
  48. if (EntityManager.TryGetComponent(uid, out PhysicsComponent? phys))
  49. {
  50. _physics.SetLinearDamping(uid, phys, 0f);
  51. _physics.SetFriction(uid, phys, 0f);
  52. _physics.SetBodyStatus(uid, phys, BodyStatus.InAir);
  53. var xform = Transform(uid);
  54. var (worldPos, worldRot) = _transform.GetWorldPositionRotation(uid);
  55. var vel = worldRot.ToWorldVec() * component.MaxSpeed;
  56. if (component.RandomizeVelocity)
  57. {
  58. vel = component.DirectionOverride.Degrees switch
  59. {
  60. 0f => _random.NextVector2(component.MinSpeed, component.MaxSpeed),
  61. _ => worldRot.RotateVec(component.DirectionOverride.ToVec()) * _random.NextFloat(component.MinSpeed, component.MaxSpeed)
  62. };
  63. }
  64. _physics.ApplyLinearImpulse(uid, vel, body: phys);
  65. xform.LocalRotation = (vel - worldPos).ToWorldAngle() + MathHelper.PiOver2;
  66. }
  67. }
  68. private void OnCollide(EntityUid uid, ImmovableRodComponent component, ref StartCollideEvent args)
  69. {
  70. var ent = args.OtherEntity;
  71. if (_random.Prob(component.HitSoundProbability))
  72. {
  73. _audio.PlayPvs(component.Sound, uid);
  74. }
  75. if (HasComp<ImmovableRodComponent>(ent))
  76. {
  77. // oh god.
  78. var coords = Transform(uid).Coordinates;
  79. _popup.PopupCoordinates(Loc.GetString("immovable-rod-collided-rod-not-good"), coords, PopupType.LargeCaution);
  80. Del(uid);
  81. Del(ent);
  82. Spawn("Singularity", coords);
  83. return;
  84. }
  85. // dont delete/hurt self if polymoprhed into a rod
  86. if (TryComp<PolymorphedEntityComponent>(uid, out var polymorphed))
  87. {
  88. if (polymorphed.Parent == ent)
  89. return;
  90. }
  91. // gib or damage em
  92. if (TryComp<BodyComponent>(ent, out var body))
  93. {
  94. component.MobCount++;
  95. _popup.PopupEntity(Loc.GetString("immovable-rod-penetrated-mob", ("rod", uid), ("mob", ent)), uid, PopupType.LargeCaution);
  96. if (!component.ShouldGib)
  97. {
  98. if (component.Damage == null)
  99. return;
  100. _damageable.TryChangeDamage(ent, component.Damage, ignoreResistances: true);
  101. return;
  102. }
  103. _bodySystem.GibBody(ent, body: body);
  104. return;
  105. }
  106. QueueDel(ent);
  107. }
  108. private void OnExamined(EntityUid uid, ImmovableRodComponent component, ExaminedEvent args)
  109. {
  110. if (component.MobCount == 0)
  111. {
  112. args.PushText(Loc.GetString("immovable-rod-consumed-none", ("rod", uid)));
  113. }
  114. else
  115. {
  116. args.PushText(Loc.GetString("immovable-rod-consumed-souls", ("rod", uid), ("amount", component.MobCount)));
  117. }
  118. }
  119. }