| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889 |
- using System.Numerics;
- using Content.Server.Spawners.Components;
- using Content.Server.Spawners.EntitySystems;
- using Content.Shared.Random;
- using Content.Shared.Random.Helpers;
- using Robust.Server.GameObjects;
- using Robust.Shared.Prototypes;
- using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
- using Robust.Shared.Spawners;
- namespace Content.Server.Destructible.Thresholds.Behaviors;
- /// <summary>
- /// Behavior that can be assigned to a trigger that that takes a <see cref="WeightedRandomEntityPrototype"/>
- /// and spawns a number of the same entity between a given min and max
- /// at a random offset from the final position of the entity.
- /// </summary>
- [Serializable]
- [DataDefinition]
- public sealed partial class WeightedSpawnEntityBehavior : IThresholdBehavior
- {
- /// <summary>
- /// A table of entities with assigned weights to randomly pick from
- /// </summary>
- [DataField(required: true)]
- public ProtoId<WeightedRandomEntityPrototype> WeightedEntityTable;
- /// <summary>
- /// How far away to spawn the entity from the parent position
- /// </summary>
- [DataField]
- public float SpawnOffset = 1;
- /// <summary>
- /// The mininum number of entities to spawn randomly
- /// </summary>
- [DataField]
- public int MinSpawn = 1;
- /// <summary>
- /// The max number of entities to spawn randomly
- /// </summary>
- [DataField]
- public int MaxSpawn = 1;
- /// <summary>
- /// Time in seconds to wait before spawning entities
- /// </summary>
- [DataField]
- public float SpawnAfter;
- public void Execute(EntityUid uid, DestructibleSystem system, EntityUid? cause = null)
- {
- // Get the position at which to start initially spawning entities
- var transform = system.EntityManager.System<TransformSystem>();
- var position = transform.GetMapCoordinates(uid);
- // Helper function used to randomly get an offset to apply to the original position
- Vector2 GetRandomVector() => new (system.Random.NextFloat(-SpawnOffset, SpawnOffset), system.Random.NextFloat(-SpawnOffset, SpawnOffset));
- // Randomly pick the entity to spawn and randomly pick how many to spawn
- var entity = system.PrototypeManager.Index(WeightedEntityTable).Pick(system.Random);
- var amountToSpawn = system.Random.NextFloat(MinSpawn, MaxSpawn);
- // Different behaviors for delayed spawning and immediate spawning
- if (SpawnAfter != 0)
- {
- // if it fails to get the spawner, this won't ever work so just return
- if (!system.PrototypeManager.TryIndex("TemporaryEntityForTimedDespawnSpawners", out var tempSpawnerProto))
- return;
- // spawn the spawner, assign it a lifetime, and assign the entity that it will spawn when despawned
- for (var i = 0; i < amountToSpawn; i++)
- {
- var spawner = system.EntityManager.SpawnEntity(tempSpawnerProto.ID, position.Offset(GetRandomVector()));
- system.EntityManager.EnsureComponent<TimedDespawnComponent>(spawner, out var timedDespawnComponent);
- timedDespawnComponent.Lifetime = SpawnAfter;
- system.EntityManager.EnsureComponent<SpawnOnDespawnComponent>(spawner, out var spawnOnDespawnComponent);
- system.EntityManager.System<SpawnOnDespawnSystem>().SetPrototype((spawner, spawnOnDespawnComponent), entity);
- }
- }
- else
- {
- // directly spawn the desired entities
- for (var i = 0; i < amountToSpawn; i++)
- {
- system.EntityManager.SpawnEntity(entity, position.Offset(GetRandomVector()));
- }
- }
- }
- }
|