diff --git a/Content.Server/Destructible/Thresholds/Behaviors/WeightedSpawnEntityBehavior.cs b/Content.Server/Destructible/Thresholds/Behaviors/WeightedSpawnEntityBehavior.cs
new file mode 100644
index 0000000000..e02ed87322
--- /dev/null
+++ b/Content.Server/Destructible/Thresholds/Behaviors/WeightedSpawnEntityBehavior.cs
@@ -0,0 +1,89 @@
+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;
+
+///
+/// Behavior that can be assigned to a trigger that that takes a
+/// 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.
+///
+[Serializable]
+[DataDefinition]
+public sealed partial class WeightedSpawnEntityBehavior : IThresholdBehavior
+{
+ ///
+ /// A table of entities with assigned weights to randomly pick from
+ ///
+ [DataField(required: true)]
+ public ProtoId WeightedEntityTable;
+
+ ///
+ /// How far away to spawn the entity from the parent position
+ ///
+ [DataField]
+ public float SpawnOffset = 1;
+
+ ///
+ /// The mininum number of entities to spawn randomly
+ ///
+ [DataField]
+ public int MinSpawn = 1;
+
+ ///
+ /// The max number of entities to spawn randomly
+ ///
+ [DataField]
+ public int MaxSpawn = 1;
+
+ ///
+ /// Time in seconds to wait before spawning entities
+ ///
+ [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();
+ 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(spawner, out var timedDespawnComponent);
+ timedDespawnComponent.Lifetime = SpawnAfter;
+ system.EntityManager.EnsureComponent(spawner, out var spawnOnDespawnComponent);
+ system.EntityManager.System().SetPrototype((spawner, spawnOnDespawnComponent), entity);
+ }
+ }
+ else
+ {
+ // directly spawn the desired entities
+ for (var i = 0; i < amountToSpawn; i++)
+ {
+ system.EntityManager.SpawnEntity(entity, position.Offset(GetRandomVector()));
+ }
+ }
+ }
+}
diff --git a/Content.Server/Spawners/EntitySystems/SpawnOnDespawnSystem.cs b/Content.Server/Spawners/EntitySystems/SpawnOnDespawnSystem.cs
index f5a34728dc..2f850faab1 100644
--- a/Content.Server/Spawners/EntitySystems/SpawnOnDespawnSystem.cs
+++ b/Content.Server/Spawners/EntitySystems/SpawnOnDespawnSystem.cs
@@ -1,4 +1,5 @@
using Content.Server.Spawners.Components;
+using Robust.Shared.Prototypes;
using Robust.Shared.Spawners;
namespace Content.Server.Spawners.EntitySystems;
@@ -19,4 +20,9 @@ public sealed class SpawnOnDespawnSystem : EntitySystem
Spawn(comp.Prototype, xform.Coordinates);
}
+
+ public void SetPrototype(Entity entity, EntProtoId prototype)
+ {
+ entity.Comp.Prototype = prototype;
+ }
}
diff --git a/Resources/Prototypes/Entities/Markers/Spawners/temp.yml b/Resources/Prototypes/Entities/Markers/Spawners/temp.yml
new file mode 100644
index 0000000000..aa76bb5ea7
--- /dev/null
+++ b/Resources/Prototypes/Entities/Markers/Spawners/temp.yml
@@ -0,0 +1,11 @@
+- type: entity
+ id: TemporaryEntityForTimedDespawnSpawners
+ categories: [ HideSpawnMenu, Spawner ]
+ components:
+ - type: Transform
+ anchored: True
+ - type: Physics
+ bodyType: Static
+ canCollide: false
+ - type: TimedDespawn
+ # we can't declare the SpawnOnDespawnComponent because the entity is required on yml
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/meteors.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/meteors.yml
index 3468cade76..235010acc9 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/meteors.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/meteors.yml
@@ -112,6 +112,11 @@
sound:
collection: MetalBreak
- !type:ExplodeBehavior
+ - !type:WeightedSpawnEntityBehavior
+ weightedEntityTable: "MeteorSpawnAsteroidWallTable"
+ minSpawn: 2
+ maxSpawn: 4
+ spawnAfter: 0.5
- type: entity
parent: BaseMeteor
@@ -147,6 +152,12 @@
sound:
collection: MetalBreak
- !type:ExplodeBehavior
+ - !type:WeightedSpawnEntityBehavior
+ weightedEntityTable: "MeteorSpawnAsteroidWallTable"
+ spawnOffset: 2
+ minSpawn: 3
+ maxSpawn: 6
+ spawnAfter: 0.5
- type: entity
parent: BaseMeteor
@@ -169,6 +180,12 @@
sound:
collection: MetalBreak
- !type:ExplodeBehavior
+ - !type:WeightedSpawnEntityBehavior
+ weightedEntityTable: "MeteorSpawnAsteroidWallTable"
+ spawnOffset: 3
+ minSpawn: 5
+ maxSpawn: 8
+ spawnAfter: 0.5
- type: entity
parent: BaseMeteor
@@ -203,4 +220,4 @@
volume: 10
- !type:SpillBehavior
solution: blood
- - !type:ExplodeBehavior
+ - !type:ExplodeBehavior
\ No newline at end of file
diff --git a/Resources/Prototypes/GameRules/meteorswarms.yml b/Resources/Prototypes/GameRules/meteorswarms.yml
index b85032f056..2f1cb4eba5 100644
--- a/Resources/Prototypes/GameRules/meteorswarms.yml
+++ b/Resources/Prototypes/GameRules/meteorswarms.yml
@@ -17,6 +17,20 @@
GameRuleMeteorSwarmLarge: 5
GameRuleUristSwarm: 0.05
+- type: weightedRandomEntity
+ id: MeteorSpawnAsteroidWallTable
+ weights:
+ AsteroidRock: 10
+ AsteroidRockCoal: 5
+ AsteroidRockQuartz: 5
+ AsteroidRockTin: 5
+ AsteroidRockSilver: 2
+ AsteroidRockGold: 2
+ AsteroidRockPlasma: 2
+ AsteroidRockDiamond: 2
+ AsteroidRockUranium: 0.5
+ AsteroidRockBananium: 0.5
+
- type: entity
parent: BaseGameRule
id: GameRuleMeteorSwarm