diff --git a/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerComponent.cs b/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerComponent.cs
new file mode 100644
index 0000000000..8d5d24f45a
--- /dev/null
+++ b/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerComponent.cs
@@ -0,0 +1,57 @@
+namespace Content.Server.SimpleStation14.Grenades;
+
+[RegisterComponent]
+
+///
+/// Spawns entities when triggered.
+/// This is used for grenades and other things that spawn entities on trigger.
+///
+public sealed class SpawnEntitiesOnTriggerComponent : Component
+{
+ ///
+ /// The prototype of the entity to spawn.
+ ///
+ [DataField("prototype")]
+ public string? Prototype = null;
+
+ ///
+ /// The amount of entities to spawn.
+ ///
+ [DataField("count")]
+ public int Count = 1;
+
+ ///
+ /// The minimum amount of entities to spawn.
+ /// If this is null, will always spawn full amount.
+ ///
+ [DataField("minCount")]
+ public int? MinCount = null;
+
+ ///
+ /// The velocity to either shoot or throw the spawned entities with.
+ /// If this is null, entities won't be thrown or shot.
+ ///
+ [DataField("velocity")]
+ public float? Velocity = null;
+
+ ///
+ /// The time in seconds before the spawned entities despawn.
+ /// If this is null, entities won't despawn.
+ ///
+ [DataField("despawnTime")]
+ public float? DespawnTime = null;
+
+ ///
+ /// Whether or to shoot the spawned entities.
+ /// If this is false, entities with velocity will be thrown.
+ ///
+ [DataField("shoot")]
+ public bool Shoot = false;
+
+ ///
+ /// The offset multiplier for the spawned entities in max tiles.
+ /// If this is 0, entities will spawn on top of the trigger.
+ ///
+ [DataField("offset")]
+ public float Offset = 0f;
+}
diff --git a/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerSystem.cs b/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerSystem.cs
new file mode 100644
index 0000000000..d27b7e0d7d
--- /dev/null
+++ b/Content.Server/SimpleStation14/SpawnEntitiesOnTrigger/SpawnEntitiesOnTriggerSystem.cs
@@ -0,0 +1,76 @@
+using Content.Shared.Spawners.Components;
+using Robust.Shared.Map;
+using Robust.Shared.Prototypes;
+using Content.Server.Explosion.EntitySystems;
+using Robust.Shared.Random;
+using Robust.Shared.Physics.Components;
+using Robust.Shared.Physics.Systems;
+using Content.Server.Weapons.Ranged.Systems;
+using Content.Shared.Throwing;
+using Robust.Server.GameObjects;
+
+namespace Content.Server.SimpleStation14.Grenades;
+
+public class SpawnEntitiesOnTriggerSystem : EntitySystem
+{
+ [Dependency] private readonly IPrototypeManager _prototypes = default!;
+ [Dependency] private readonly IRobustRandom _random = default!;
+ [Dependency] private readonly GunSystem _guns = default!;
+ [Dependency] private readonly ThrowingSystem _throw = default!;
+ [Dependency] private readonly TransformSystem _transform = default!;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnTrigger);
+ }
+
+ ///
+ /// On trigger, works out if the entity has a variable count, decides how many to spawn,
+ /// then iterates through and spawns each one apply any offset, and any velocity, be it thrown or shot,
+ /// spinning them in a random direction. Finally, sets the entity to be deleted if a despawn time is set.
+ ///
+ private void OnTrigger(EntityUid uid, SpawnEntitiesOnTriggerComponent component, TriggerEvent args)
+ {
+ if (component.Prototype == null) return;
+
+ var prototype = _prototypes.Index(component.Prototype);
+
+ var spawnCount = component.Count;
+
+ if (component.MinCount != null)
+ {
+ spawnCount = _random.Next(component.MinCount.Value, component.Count);
+ }
+
+ for (var i = 0; i < spawnCount; i++)
+ {
+ var spawnedEntity = EntityManager.SpawnEntity(prototype.ID, EntityManager.GetComponent(uid).Coordinates
+ + new EntityCoordinates(EntityManager.GetComponent(uid).ParentUid, _random.NextVector2(-1, 1) * component.Offset));
+
+ var transfComp = EntityManager.GetComponent(spawnedEntity);
+ _transform.AttachToGridOrMap(spawnedEntity);
+
+ if (component.Velocity != null)
+ {
+ transfComp.LocalRotation = Angle.FromDegrees(_random.Next(0, 360));
+
+ if (component.Shoot)
+ {
+ _guns.ShootProjectile(spawnedEntity, transfComp.LocalRotation.ToWorldVec(), Vector2.Zero, speed: component.Velocity.Value * _random.NextFloat(0.8f, 1.2f));
+ }
+ else
+ {
+ _throw.TryThrow(spawnedEntity, transfComp.LocalRotation.ToWorldVec(), 1.0f, null, 5.0f);
+ }
+ }
+
+ if (component.DespawnTime != null)
+ {
+ var despawnComp = EntityManager.EnsureComponent(spawnedEntity);
+ despawnComp.Lifetime = component.DespawnTime.Value;
+ }
+ }
+ }
+}
diff --git a/Resources/Audio/SimpleStation14/Effects/Weapons/Grenades/beenade.ogg b/Resources/Audio/SimpleStation14/Effects/Weapons/Grenades/beenade.ogg
new file mode 100644
index 0000000000..ca49db47d4
Binary files /dev/null and b/Resources/Audio/SimpleStation14/Effects/Weapons/Grenades/beenade.ogg differ
diff --git a/Resources/Prototypes/SimpleStation14/Catalog/uplink_catalog_syndicate.yml b/Resources/Prototypes/SimpleStation14/Catalog/uplink_catalog_syndicate.yml
new file mode 100644
index 0000000000..7361b01fa4
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Catalog/uplink_catalog_syndicate.yml
@@ -0,0 +1,9 @@
+- type: listing
+ id: UplinkExplosiveBeenade
+ name: Beenade
+ description: "A grenade... Full of bees. Now THIS is truly evil."
+ productEntity: GrenadeBees
+ cost:
+ Telecrystal: 3
+ categories:
+ - UplinkExplosives
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Projectiles/shrapnel.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Projectiles/shrapnel.yml
new file mode 100644
index 0000000000..25f01acd7a
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Projectiles/shrapnel.yml
@@ -0,0 +1,41 @@
+- type: entity
+ id: BulletGrenadeShrapnel
+ parent: BaseBullet
+ name: shrapnel
+ noSpawn: true
+ components:
+ - type: Sprite
+ sprite: SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi
+ layers:
+ - state: shrapnel
+ shader: unshaded
+ - type: Projectile
+ damage:
+ types:
+ Piercing: 30
+ - type: Fixtures
+ fixtures:
+ - shape:
+ !type:PhysShapeAabb
+ bounds: "-0.3,-0.25,0.3,0.25"
+ hard: false
+ id: projectile
+ mask:
+ - Impassable
+ - BulletImpassable
+ # - *flybyfixture
+
+- type: entity
+ id: BulletGrenadeShrapnelRubber
+ parent: BaseBulletRubber
+ name: rubber ball
+ noSpawn: true
+ components:
+ - type: Projectile
+ damage:
+ types:
+ Blunt: 1.5
+ soundHit:
+ path: /Audio/Weapons/Guns/Hits/snap.ogg
+ - type: StaminaDamageOnCollide
+ damage: 15
diff --git a/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Throwable/grenades.yml b/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Throwable/grenades.yml
new file mode 100644
index 0000000000..98e553befa
--- /dev/null
+++ b/Resources/Prototypes/SimpleStation14/Entities/Objects/Weapons/Guns/Throwable/grenades.yml
@@ -0,0 +1,83 @@
+- type: entity
+ name: fragmentation grenade
+ description: A grenade that explodes into a cloud of shrapnel.
+ parent: GrenadeBase
+ id: GrenadeFragThrown
+ components:
+ - type: Sprite
+ sprite: SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi
+ - type: SpawnEntitiesOnTrigger
+ prototype: BulletGrenadeShrapnel
+ count: 50
+ minCount: 30
+ velocity: 20
+ despawnTime: 0.4
+ shoot: true
+ - type: EmitSoundOnTrigger
+ sound:
+ path: /Audio/Effects/metalbreak.ogg
+ # - type: ExplodeOnTrigger
+ # - type: Explosive
+ # explosionType: Default
+ # totalIntensity: 40
+ # intensitySlope: 45
+ # maxIntensity: 20
+ # canCreateVacuum: false
+ - type: DeleteOnTrigger
+ - type: Appearance
+ visuals:
+ - type: TimerTriggerVisualizer
+ countdown_sound:
+ path: /Audio/Items/pop.ogg
+ - type: OnUseTimerTrigger
+ delay: 5
+
+- type: entity
+ name: rubber ball grenade
+ description:
+ parent: GrenadeBase
+ id: GrenadeRubberBall
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/grenade.rsi
+ - type: SpawnEntitiesOnTrigger
+ prototype: BulletGrenadeShrapnelRubber
+ count: 85
+ minCount: 70
+ velocity: 15
+ despawnTime: 1.5
+ shoot: true
+ - type: EmitSoundOnTrigger
+ sound:
+ path: /Audio/Effects/metalbreak.ogg
+ - type: DeleteOnTrigger
+ # - type: Appearance
+ # visuals:
+ # - type: TimerTriggerVisualizer
+ # countdown_sound:
+ # path: /Audio/Effects/countdown.ogg
+ - type: OnUseTimerTrigger
+ delay: 1.5
+
+- type: entity
+ name: beenade
+ description: A grenade that explodes into a cloud of bees... Nightmarish.
+ parent: GrenadeBase
+ id: GrenadeBees
+ components:
+ - type: Sprite
+ sprite: SimpleStation14/Objects/Weapons/Grenades/beenade.rsi
+ - type: SpawnEntitiesOnTrigger
+ prototype: MobAngryBee
+ count: 14
+ minCount: 8
+ despawnTime: 10
+ offset: 1
+ - type: DeleteOnTrigger
+ - type: Appearance
+ visuals:
+ - type: TimerTriggerVisualizer
+ countdown_sound:
+ path: /Audio/SimpleStation14/Effects/Weapons/Grenades/beenade.ogg
+ - type: OnUseTimerTrigger
+ delay: 3
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/equipped-BELT.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/equipped-BELT.png
new file mode 100644
index 0000000000..c4f5d06a15
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/equipped-BELT.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/icon.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/icon.png
new file mode 100644
index 0000000000..0e3e8facc7
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/icon.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-left.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-left.png
new file mode 100644
index 0000000000..2036d38b74
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-left.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-right.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-right.png
new file mode 100644
index 0000000000..999c50e9ea
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/inhand-right.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/meta.json b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/meta.json
new file mode 100644
index 0000000000..1de1effa9f
--- /dev/null
+++ b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/meta.json
@@ -0,0 +1,30 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by Pspritechologist",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "primed",
+ "delays": [[ 0.2, 0.2, 0.2, 0.2 ]]
+ },
+ {
+ "name": "equipped-BELT",
+ "directions": 4
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/primed.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/primed.png
new file mode 100644
index 0000000000..44849da77e
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/beenade.rsi/primed.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/equipped-BELT.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/equipped-BELT.png
new file mode 100644
index 0000000000..a5da12489e
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/equipped-BELT.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/icon.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/icon.png
new file mode 100644
index 0000000000..c552d96eed
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/icon.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-left.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-left.png
new file mode 100644
index 0000000000..4ab86f4513
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-left.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-right.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-right.png
new file mode 100644
index 0000000000..9e77c9a106
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/inhand-right.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/meta.json b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/meta.json
new file mode 100644
index 0000000000..29ad3a5726
--- /dev/null
+++ b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/meta.json
@@ -0,0 +1,29 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Made by Pspritechologist",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "primed"
+ },
+ {
+ "name": "equipped-BELT",
+ "directions": 4
+ },
+ {
+ "name": "inhand-left",
+ "directions": 4
+ },
+ {
+ "name": "inhand-right",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/primed.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/primed.png
new file mode 100644
index 0000000000..d7fbd7d571
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Grenades/frag_grenade.rsi/primed.png differ
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json b/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json
index 7f921b6e6b..fd4dc5e016 100644
--- a/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json
+++ b/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/meta.json
@@ -54,6 +54,9 @@
0.11
]
]
+ },
+ {
+ "name": "shrapnel"
}
]
-}
\ No newline at end of file
+}
diff --git a/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/shrapnel.png b/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/shrapnel.png
new file mode 100644
index 0000000000..a3ae1339b1
Binary files /dev/null and b/Resources/Textures/SimpleStation14/Objects/Weapons/Guns/Projectiles/projectiles.rsi/shrapnel.png differ