ChaoticJumpSystem.cs 2.9 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. using Content.Server.Physics.Components;
  2. using Robust.Shared.Random;
  3. using Robust.Shared.Timing;
  4. using Robust.Shared.Physics.Systems;
  5. using Robust.Shared.Physics;
  6. using System.Numerics;
  7. using Robust.Shared.Physics.Controllers;
  8. using Robust.Shared.Utility;
  9. namespace Content.Server.Physics.Controllers;
  10. /// <summary>
  11. /// A component which makes its entity periodically chaotic jumps arounds
  12. /// </summary>
  13. public sealed class ChaoticJumpSystem : VirtualController
  14. {
  15. [Dependency] private readonly IGameTiming _gameTiming = default!;
  16. [Dependency] private readonly SharedTransformSystem _transform = default!;
  17. [Dependency] private readonly IRobustRandom _random = default!;
  18. [Dependency] private readonly SharedPhysicsSystem _physics = default!;
  19. public override void Initialize()
  20. {
  21. base.Initialize();
  22. SubscribeLocalEvent<ChaoticJumpComponent, MapInitEvent>(OnMapInit);
  23. }
  24. private void OnMapInit(Entity<ChaoticJumpComponent> chaotic, ref MapInitEvent args)
  25. {
  26. //So the entity doesn't teleport instantly. For tesla, for example, it's important for it to eat tesla's generator.
  27. chaotic.Comp.NextJumpTime = _gameTiming.CurTime + TimeSpan.FromSeconds(_random.NextFloat(chaotic.Comp.JumpMinInterval, chaotic.Comp.JumpMaxInterval));
  28. }
  29. public override void UpdateBeforeSolve(bool prediction, float frameTime)
  30. {
  31. base.UpdateBeforeSolve(prediction, frameTime);
  32. var query = EntityQueryEnumerator<ChaoticJumpComponent>();
  33. while (query.MoveNext(out var uid, out var chaotic))
  34. {
  35. //Jump
  36. if (chaotic.NextJumpTime <= _gameTiming.CurTime)
  37. {
  38. Jump(uid, chaotic);
  39. chaotic.NextJumpTime += TimeSpan.FromSeconds(_random.NextFloat(chaotic.JumpMinInterval, chaotic.JumpMaxInterval));
  40. }
  41. }
  42. }
  43. private void Jump(EntityUid uid, ChaoticJumpComponent component)
  44. {
  45. var transform = Transform(uid);
  46. var startPos = _transform.GetWorldPosition(uid);
  47. Vector2 targetPos;
  48. var direction = _random.NextAngle();
  49. var range = _random.NextFloat(component.RangeMin, component.RangeMax);
  50. var ray = new CollisionRay(startPos, direction.ToVec(), component.CollisionMask);
  51. var rayCastResults = _physics.IntersectRay(transform.MapID, ray, range, uid, returnOnFirstHit: false).FirstOrNull();
  52. if (rayCastResults != null)
  53. {
  54. targetPos = rayCastResults.Value.HitPos;
  55. targetPos = new Vector2(targetPos.X - (float) Math.Cos(direction), targetPos.Y - (float) Math.Sin(direction)); //offset so that the teleport does not take place directly inside the target
  56. }
  57. else
  58. {
  59. targetPos = new Vector2(startPos.X + range * (float) Math.Cos(direction), startPos.Y + range * (float) Math.Sin(direction));
  60. }
  61. Spawn(component.Effect, transform.Coordinates);
  62. _transform.SetWorldPosition(uid, targetPos);
  63. }
  64. }