RespawnableSpawnerSystem.cs 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using Robust.Shared.GameObjects;
  2. using Robust.Shared.IoC;
  3. using Robust.Shared.Random;
  4. using Robust.Shared.Timing;
  5. using Robust.Shared;
  6. namespace Content.Server.Spawners;
  7. public sealed class RespawnableSpawnerSystem : EntitySystem
  8. {
  9. [Dependency] private readonly IEntityManager _entityManager = default!;
  10. [Dependency] private readonly IGameTiming _gameTiming = default!;
  11. [Dependency] private readonly IRobustRandom _random = default!;
  12. public override void Initialize()
  13. {
  14. base.Initialize();
  15. SubscribeLocalEvent<RespawnableSpawnerComponent, MapInitEvent>(OnMapInit);
  16. SubscribeLocalEvent<SpawnedByComponent, EntityTerminatingEvent>(OnEntityTerminating);
  17. }
  18. private void OnMapInit(EntityUid uid, RespawnableSpawnerComponent component, MapInitEvent args)
  19. {
  20. if (component.Prototypes.Count > 0)
  21. {
  22. var prototype = component.Prototypes[_random.Next(component.Prototypes.Count)];
  23. var newEntity = _entityManager.SpawnEntity(prototype, Transform(uid).Coordinates);
  24. var spawnedBy = _entityManager.AddComponent<SpawnedByComponent>(newEntity);
  25. spawnedBy.Spawner = uid;
  26. }
  27. }
  28. private void OnEntityTerminating(EntityUid uid, SpawnedByComponent spawnedBy, EntityTerminatingEvent args)
  29. {
  30. if (_entityManager.TryGetComponent<RespawnableSpawnerComponent>(spawnedBy.Spawner, out var spawner))
  31. {
  32. if (spawner != null)
  33. {
  34. var delay = _random.NextFloat(spawner.MinDelay, spawner.MaxDelay);
  35. var respawnTime = (float)_gameTiming.CurTime.TotalSeconds + delay;
  36. spawner.RespawnTimers[uid] = respawnTime;
  37. }
  38. }
  39. else
  40. {
  41. Log.Warning($"Spawner {spawnedBy.Spawner} not found or lacks RespawnableSpawnerComponent for entity {uid}");
  42. }
  43. }
  44. public override void Update(float frameTime)
  45. {
  46. var query = EntityQueryEnumerator<RespawnableSpawnerComponent>();
  47. while (query.MoveNext(out var uid, out var component))
  48. {
  49. var toRemove = new List<EntityUid>();
  50. foreach (var (entity, respawnTime) in component.RespawnTimers)
  51. {
  52. var currentTime = (float)_gameTiming.CurTime.TotalSeconds;
  53. if (currentTime >= respawnTime)
  54. {
  55. try
  56. {
  57. var prototype = component.Prototypes[_random.Next(component.Prototypes.Count)];
  58. var newEntity = _entityManager.SpawnEntity(prototype, Transform(uid).Coordinates);
  59. var spawnedBy = _entityManager.AddComponent<SpawnedByComponent>(newEntity);
  60. spawnedBy.Spawner = uid;
  61. }
  62. catch (Exception ex)
  63. {
  64. Log.Error($"Failed to spawn entity for spawner {uid}: {ex.Message}");
  65. }
  66. finally
  67. {
  68. toRemove.Add(entity); // Marks it to remove from RespawnTimers, even if it fails
  69. }
  70. }
  71. }
  72. foreach (var remove in toRemove)
  73. {
  74. component.RespawnTimers.Remove(remove);
  75. }
  76. }
  77. }
  78. }