From 3e766402b9d6c17f41f9e7e814b70eef83a95568 Mon Sep 17 00:00:00 2001
From: Arendian <137322659+Arendian@users.noreply.github.com>
Date: Thu, 14 Dec 2023 04:30:42 +0100
Subject: [PATCH] Cluster grenades for uplink and security (#22029)
* clustergrenades go boom
* Small tweaks
* Some tweaks and soaplet
* clustergrenadesystem changes and launcher types
* small tweaks
* typo
* whitespace
* rsi edit
* another typo
* add containers
* Some changes related to merge
* Forgot to change name
* Made changes based on review
* Removed new china lake ammo based on feedback in other PR
* Unneeded nested loop moment
* Nested loop needed after all moment
---
.../Components/ClusterGrenadeComponent.cs | 88 ++++++-
.../EntitySystems/ClusterGrenadeSystem.cs | 141 +++++++----
.../Projectiles/ProjectileSystem.cs | 14 +-
.../Projectiles/ProjectileComponent.cs | 3 +
.../Locale/en-US/store/uplink-catalog.ftl | 17 +-
.../VendingMachines/Inventories/sec.yml | 2 +
.../Prototypes/Catalog/uplink_catalog.yml | 54 +++++
.../Objects/Specific/Janitorial/soap.yml | 40 ++++
.../Entities/Objects/Weapons/Bombs/funny.yml | 16 +-
.../Guns/Ammunition/Projectiles/grenade.yml | 58 +++++
.../Weapons/Guns/Projectiles/projectiles.yml | 5 +
.../Objects/Weapons/Throwable/clusterbang.yml | 223 +++++++++++++++++-
.../Objects/Weapons/Throwable/grenades.yml | 7 +-
.../Specific/Janitorial/soap.rsi/meta.json | 3 +
.../Janitorial/soap.rsi/syndie-soaplet.png | Bin 0 -> 157 bytes
.../Weapons/Grenades/clusterbang.rsi/icon.png | Bin 0 -> 459 bytes
.../Grenades/clusterbang.rsi/meta.json | 13 +
.../Grenades/clusterbang.rsi/primed.png | Bin 0 -> 680 bytes
.../Grenades/clusterbomb.rsi/base-1.png | Bin 0 -> 467 bytes
.../Grenades/clusterbomb.rsi/base-2.png | Bin 0 -> 502 bytes
.../Weapons/Grenades/clusterbomb.rsi/icon.png | Bin 0 -> 476 bytes
.../Grenades/clusterbomb.rsi/meta.json | 29 +++
.../Grenades/clusterbomb.rsi/primed.png | Bin 0 -> 667 bytes
.../pyrogrenade.rsi/equipped-BELT.png | Bin 0 -> 234 bytes
.../Weapons/Grenades/pyrogrenade.rsi/icon.png | Bin 0 -> 290 bytes
.../Grenades/pyrogrenade.rsi/meta.json | 27 +++
.../Grenades/pyrogrenade.rsi/primed.png | Bin 0 -> 349 bytes
.../shrapnelgrenade.rsi/equipped-BELT.png | Bin 0 -> 233 bytes
.../Grenades/shrapnelgrenade.rsi/icon.png | Bin 0 -> 293 bytes
.../Grenades/shrapnelgrenade.rsi/meta.json | 27 +++
.../Grenades/shrapnelgrenade.rsi/primed.png | Bin 0 -> 351 bytes
.../stingergrenade.rsi/equipped-BELT.png | Bin 0 -> 254 bytes
.../Grenades/stingergrenade.rsi/icon.png | Bin 0 -> 312 bytes
.../Grenades/stingergrenade.rsi/meta.json | 27 +++
.../Grenades/stingergrenade.rsi/primed.png | Bin 0 -> 377 bytes
.../Explosives/explosives.rsi/meta.json | 2 +-
36 files changed, 727 insertions(+), 69 deletions(-)
create mode 100644 Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/grenade.yml
create mode 100644 Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-soaplet.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/primed.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-1.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-2.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/primed.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/equipped-BELT.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/primed.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/equipped-BELT.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/primed.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/equipped-BELT.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/icon.png
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/meta.json
create mode 100644 Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/primed.png
diff --git a/Content.Server/Explosion/Components/ClusterGrenadeComponent.cs b/Content.Server/Explosion/Components/ClusterGrenadeComponent.cs
index e2e3ca2733..fe1b8caede 100644
--- a/Content.Server/Explosion/Components/ClusterGrenadeComponent.cs
+++ b/Content.Server/Explosion/Components/ClusterGrenadeComponent.cs
@@ -1,7 +1,6 @@
using Content.Server.Explosion.EntitySystems;
using Robust.Shared.Containers;
using Robust.Shared.Prototypes;
-using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
namespace Content.Server.Explosion.Components
{
@@ -13,8 +12,8 @@ namespace Content.Server.Explosion.Components
///
/// What we fill our prototype with if we want to pre-spawn with grenades.
///
- [DataField("fillPrototype", customTypeSerializer:typeof(PrototypeIdSerializer))]
- public string? FillPrototype;
+ [DataField("fillPrototype")]
+ public EntProtoId? FillPrototype;
///
/// If we have a pre-fill how many more can we spawn.
@@ -28,20 +27,91 @@ namespace Content.Server.Explosion.Components
public int MaxGrenades = 3;
///
- /// How long until our grenades are shot out and armed.
+ /// Maximum delay in seconds between individual grenade triggers
///
- [ViewVariables(VVAccess.ReadWrite)] [DataField("delay")]
- public float Delay = 1;
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("grenadeTriggerIntervalMax")]
+ public float GrenadeTriggerIntervalMax = 0f;
///
- /// Max distance grenades can be thrown.
+ /// Minimum delay in seconds between individual grenade triggers
///
- [ViewVariables(VVAccess.ReadWrite)] [DataField("distance")]
- public float ThrowDistance = 50;
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("grenadeTriggerIntervalMin")]
+ public float GrenadeTriggerIntervalMin = 0f;
+
+ ///
+ /// Minimum delay in seconds before any grenades start to be triggered.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("baseTriggerDelay")]
+ public float BaseTriggerDelay = 1.0f;
+
+ ///
+ /// Decides if grenades trigger after getting launched
+ ///
+ [DataField("triggerGrenades")]
+ public bool TriggerGrenades = true;
+
+ ///
+ /// Does the cluster grenade shoot or throw
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("grenadeType")]
+ public Enum GrenadeType = Components.GrenadeType.Throw;
+
+ ///
+ /// The speed at which grenades get thrown
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("velocity")]
+ public float Velocity = 5;
+
+ ///
+ /// Should the spread be random
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("randomSpread")]
+ public bool RandomSpread = false;
+
+ ///
+ /// Should the angle be random
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("randomAngle")]
+ public bool RandomAngle = false;
+
+ ///
+ /// Static distance grenades will be thrown to.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("distance")]
+ public float Distance = 1f;
+
+ ///
+ /// Max distance grenades should randomly be thrown to.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("maxSpreadDistance")]
+ public float MaxSpreadDistance = 2.5f;
+
+ ///
+ /// Minimal distance grenades should randomly be thrown to.
+ ///
+ [ViewVariables(VVAccess.ReadWrite)]
+ [DataField("minSpreadDistance")]
+ public float MinSpreadDistance = 0f;
///
/// This is the end.
///
public bool CountDown;
}
+
+ public enum GrenadeType
+ {
+ Throw,
+ Shoot
+ }
+
}
diff --git a/Content.Server/Explosion/EntitySystems/ClusterGrenadeSystem.cs b/Content.Server/Explosion/EntitySystems/ClusterGrenadeSystem.cs
index 9467966cb6..2674a8d61b 100644
--- a/Content.Server/Explosion/EntitySystems/ClusterGrenadeSystem.cs
+++ b/Content.Server/Explosion/EntitySystems/ClusterGrenadeSystem.cs
@@ -6,6 +6,10 @@ using Content.Shared.Interaction.Events;
using Content.Shared.Throwing;
using Robust.Shared.Containers;
using Robust.Shared.Random;
+using Content.Server.Weapons.Ranged.Systems;
+using System.Numerics;
+using Robust.Server.Containers;
+using Robust.Server.GameObjects;
namespace Content.Server.Explosion.EntitySystems;
@@ -13,9 +17,11 @@ public sealed class ClusterGrenadeSystem : EntitySystem
{
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly SharedContainerSystem _container = default!;
- [Dependency] private readonly TriggerSystem _trigger = default!;
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
+ [Dependency] private readonly GunSystem _gun = default!;
+ [Dependency] private readonly TransformSystem _transformSystem = default!;
+ [Dependency] private readonly ContainerSystem _containerSystem = default!;
public override void Initialize()
{
@@ -23,12 +29,12 @@ public sealed class ClusterGrenadeSystem : EntitySystem
SubscribeLocalEvent(OnClugInit);
SubscribeLocalEvent(OnClugStartup);
SubscribeLocalEvent(OnClugUsing);
- SubscribeLocalEvent(OnClugUse);
+ SubscribeLocalEvent(OnClugTrigger);
}
private void OnClugInit(EntityUid uid, ClusterGrenadeComponent component, ComponentInit args)
{
- component.GrenadesContainer = _container.EnsureContainer(uid, "cluster-flash");
+ component.GrenadesContainer = _container.EnsureContainer(uid, "cluster-payload");
}
private void OnClugStartup(Entity clug, ref ComponentStartup args)
@@ -53,64 +59,97 @@ public sealed class ClusterGrenadeSystem : EntitySystem
!HasComp(args.Used))
return;
- component.GrenadesContainer.Insert(args.Used);
+ _containerSystem.Insert(args.Used, component.GrenadesContainer);
UpdateAppearance(clug);
args.Handled = true;
}
- private void OnClugUse(EntityUid uid, ClusterGrenadeComponent component, UseInHandEvent args)
+ private void OnClugTrigger(Entity clug, ref TriggerEvent args)
{
- if (component.CountDown || (component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount) <= 0)
- return;
-
- // TODO: Should be an Update loop
- uid.SpawnTimer((int) (component.Delay * 1000), () =>
- {
- if (Deleted(uid))
- return;
-
- component.CountDown = true;
- var delay = 20;
- var grenadesInserted = component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount;
- var thrownCount = 0;
- var segmentAngle = 360 / grenadesInserted;
- while (TryGetGrenade((uid, component), out var grenade))
- {
- var angleMin = segmentAngle * thrownCount;
- var angleMax = segmentAngle * (thrownCount + 1);
- var angle = Angle.FromDegrees(_random.Next(angleMin, angleMax));
- // var distance = random.NextFloat() * _throwDistance;
-
- delay += _random.Next(550, 900);
- thrownCount++;
-
- // TODO: Suss out throw strength
- _throwingSystem.TryThrow(grenade, angle.ToVec().Normalized() * component.ThrowDistance);
-
- grenade.SpawnTimer(delay, () =>
- {
- if ((!EntityManager.EntityExists(grenade) ? EntityLifeStage.Deleted : MetaData(grenade).EntityLifeStage) >= EntityLifeStage.Deleted)
- return;
-
- _trigger.Trigger(grenade, args.User);
- });
- }
-
- EntityManager.DeleteEntity(uid);
- });
-
+ var component = clug.Comp;
+ component.CountDown = true;
args.Handled = true;
}
- private bool TryGetGrenade(Entity ent, out EntityUid grenade)
+ public override void Update(float frameTime)
+ {
+ base.Update(frameTime);
+ var query = EntityQueryEnumerator();
+
+ while (query.MoveNext(out var uid, out var clug))
+ {
+ if (clug.CountDown && clug.UnspawnedCount > 0)
+ {
+ var grenadesInserted = clug.GrenadesContainer.ContainedEntities.Count + clug.UnspawnedCount;
+ var thrownCount = 0;
+ var segmentAngle = 360 / grenadesInserted;
+ var grenadeDelay = 0f;
+
+ while (TryGetGrenade(uid, clug, out var grenade))
+ {
+ // var distance = random.NextFloat() * _throwDistance;
+ var angleMin = segmentAngle * thrownCount;
+ var angleMax = segmentAngle * (thrownCount + 1);
+ var angle = Angle.FromDegrees(_random.Next(angleMin, angleMax));
+ if (clug.RandomAngle)
+ angle = _random.NextAngle();
+ thrownCount++;
+
+ switch (clug.GrenadeType)
+ {
+ case GrenadeType.Shoot:
+ ShootProjectile(grenade, angle, clug, uid);
+ break;
+ case GrenadeType.Throw:
+ ThrowGrenade(grenade, angle, clug);
+ break;
+ }
+
+ // give an active timer trigger to the contained grenades when they get launched
+ if (clug.TriggerGrenades)
+ {
+ grenadeDelay += _random.NextFloat(clug.GrenadeTriggerIntervalMin, clug.GrenadeTriggerIntervalMax);
+ var grenadeTimer = EnsureComp(grenade);
+ grenadeTimer.TimeRemaining = (clug.BaseTriggerDelay + grenadeDelay);
+ var ev = new ActiveTimerTriggerEvent(grenade, uid);
+ RaiseLocalEvent(uid, ref ev);
+ }
+ }
+ // delete the empty shell of the clusterbomb
+ Del(uid);
+ }
+ }
+ }
+
+ private void ShootProjectile(EntityUid grenade, Angle angle, ClusterGrenadeComponent clug, EntityUid clugUid)
+ {
+ var direction = angle.ToVec().Normalized();
+
+ if (clug.RandomSpread)
+ direction = _random.NextVector2().Normalized();
+
+ _gun.ShootProjectile(grenade, direction, Vector2.One.Normalized(), clugUid);
+
+ }
+
+ private void ThrowGrenade(EntityUid grenade, Angle angle, ClusterGrenadeComponent clug)
+ {
+ var direction = angle.ToVec().Normalized() * clug.Distance;
+
+ if (clug.RandomSpread)
+ direction = angle.ToVec().Normalized() * _random.NextFloat(clug.MinSpreadDistance, clug.MaxSpreadDistance);
+
+ _throwingSystem.TryThrow(grenade, direction, clug.Velocity);
+ }
+
+ private bool TryGetGrenade(EntityUid clugUid, ClusterGrenadeComponent component, out EntityUid grenade)
{
grenade = default;
- var component = ent.Comp;
if (component.UnspawnedCount > 0)
{
component.UnspawnedCount--;
- grenade = EntityManager.SpawnEntity(component.FillPrototype, Transform(ent).MapPosition);
+ grenade = Spawn(component.FillPrototype, _transformSystem.GetMapCoordinates(clugUid));
return true;
}
@@ -128,12 +167,12 @@ public sealed class ClusterGrenadeSystem : EntitySystem
return false;
}
- private void UpdateAppearance(Entity ent)
+ private void UpdateAppearance(Entity clug)
{
- var component = ent.Comp;
- if (!TryComp(ent, out var appearance))
+ var component = clug.Comp;
+ if (!TryComp(clug, out var appearance))
return;
- _appearance.SetData(ent, ClusterGrenadeVisuals.GrenadesCounter, component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount, appearance);
+ _appearance.SetData(clug, ClusterGrenadeVisuals.GrenadesCounter, component.GrenadesContainer.ContainedEntities.Count + component.UnspawnedCount, appearance);
}
}
diff --git a/Content.Server/Projectiles/ProjectileSystem.cs b/Content.Server/Projectiles/ProjectileSystem.cs
index b8a6b8c5b2..1d256071d6 100644
--- a/Content.Server/Projectiles/ProjectileSystem.cs
+++ b/Content.Server/Projectiles/ProjectileSystem.cs
@@ -7,6 +7,7 @@ using Content.Shared.Database;
using Content.Shared.Projectiles;
using Robust.Server.GameObjects;
using Robust.Shared.Physics.Events;
+using Content.Shared.Mobs.Components;
using Robust.Shared.Player;
namespace Content.Server.Projectiles;
@@ -70,7 +71,18 @@ public sealed class ProjectileSystem : SharedProjectileSystem
component.DamagedEntity = true;
- if (component.DeleteOnCollide)
+ if (component.DeleteOnCollide )
+ {
+ QueueDel(uid);
+ }
+ if (component.CanPenetrate)
+ {
+ component.DamagedEntity = false;
+
+ if (!TryComp(target, out var mobState))
+ QueueDel(uid);
+ }
+ else if (component.DeleteOnCollide && !component.CanPenetrate)
{
QueueDel(uid);
}
diff --git a/Content.Shared/Projectiles/ProjectileComponent.cs b/Content.Shared/Projectiles/ProjectileComponent.cs
index 276e0943e0..3b5cd33c79 100644
--- a/Content.Shared/Projectiles/ProjectileComponent.cs
+++ b/Content.Shared/Projectiles/ProjectileComponent.cs
@@ -33,6 +33,9 @@ public sealed partial class ProjectileComponent : Component
[DataField("deleteOnCollide")]
public bool DeleteOnCollide = true;
+ [DataField("canPenetrate")]
+ public bool CanPenetrate = false;
+
[DataField("ignoreResistances")]
public bool IgnoreResistances = false;
diff --git a/Resources/Locale/en-US/store/uplink-catalog.ftl b/Resources/Locale/en-US/store/uplink-catalog.ftl
index 55bcb94c57..3ad5fb5de3 100644
--- a/Resources/Locale/en-US/store/uplink-catalog.ftl
+++ b/Resources/Locale/en-US/store/uplink-catalog.ftl
@@ -28,7 +28,7 @@ uplink-gloves-north-star-desc = A pair of gloves that reduce your punching coold
# Explosives
uplink-explosive-grenade-name = Explosive Grenade
-uplink-explosive-grenade-desc = A simplistic grenade with a ten-second fuse that is geared towards injuring personnel. Causes minimal hull damage.
+uplink-explosive-grenade-desc = A simplistic grenade with a three-and-a-half-second long fuse that is geared towards injuring personnel. Causes minimal hull damage.
uplink-flash-grenade-name = Flashbang
uplink-flash-grenade-desc = A standard-issue flashbang, capable of blinding and slowing down anyone without proper protection. This, of course, includes you; make sure you're properly equipped before using it.
@@ -63,6 +63,15 @@ uplink-exploding-pen-desc = A class IV explosive device contained within a stand
uplink-exploding-syndicate-bomb-name = Syndicate Bomb
uplink-exploding-syndicate-bomb-desc = A big, anchored bomb that can create a huge explosion if not defused in time. Useful as a distraction. Has an adjustable timer with a minimum setting of 120 seconds.
+uplink-cluster-grenade-name = Cluster Grenade
+uplink-cluster-grenade-desc = Three explosive grenades bundled together, the grenades get launched after the 3.5 second timer runs out.
+
+uplink-incendiary-grenade-name = Incendiary Grenade
+uplink-incendiary-grenade-desc = Releases a spray of incendiary fragments, igniting anyone near the detonation area.
+
+uplink-shrapnel-grenade-name = Shrapnel Grenade
+uplink-shrapnel-grenade-desc = Launches a spray of sharp fragments dealing great damage against unarmored targets.
+
# Ammo
uplink-pistol-magazine-name = Pistol Magazine (.35 auto)
uplink-pistol-magazine-desc = Pistol magazine with 10 catridges. Compatible with the Viper.
@@ -240,6 +249,9 @@ uplink-proximity-mine-desc = A mine disguised as a wet floor sign.
uplink-disposable-turret-name = Disposable Ballistic Turret
uplink-disposable-turret-desc = Looks and functions like a normal electrical toolbox. Upon hitting the toolbox it will transform into a ballistic turret, theoretically shooting at anyone except members of the syndicate. Can be turned back into a toolbox using a screwdriver and repaired using a wrench.
+uplink-cluster-banana-peel-name = Cluster Banana
+uplink-cluster-banana-peel-desc = Splits into 6 explosive banana peels after being thrown, the peels detonate automatically after 20 seconds if nobody slips on them.
+
# Armor
uplink-chameleon-name = Chameleon Kit
uplink-chameleon-desc = A backpack full of items that contain chameleon technology allowing you to disguise as pretty much anything on the station, and more!
@@ -308,6 +320,9 @@ uplink-syndicate-segway-crate-desc = Be an enemy of the corporation, in style!
uplink-syndicate-sponge-box-name = Syndicate Sponge Box
uplink-syndicate-sponge-box-desc = A box containing 6 syndicate sponges disguised as monkey cubes, these cubes turn into a variety of angry wildlife after coming into contact with water.
+uplink-slipocalypse-clustersoap-name = Slipocalypse Clustersoap
+uplink-slipocalypse-clustersoap-desc = Scatters arounds small pieces of syndicate-brand soap after being thrown, these pieces of soap evaporate after 60 seconds.
+
# Pointless
uplink-revolver-cap-gun-name = Cap Gun
uplink-revolver-cap-gun-desc = Looks almost like the real thing! Ages 8 and up.
diff --git a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml
index 658a955b88..cd319c3b42 100644
--- a/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml
+++ b/Resources/Prototypes/Catalog/VendingMachines/Inventories/sec.yml
@@ -3,6 +3,8 @@
startingInventory:
Handcuffs: 8
GrenadeFlashBang: 4
+ ClusterBangFull: 2
+ GrenadeStinger: 4
Flash: 5
FlashlightSeclite: 5
ClothingEyesGlassesSunglasses: 2
diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml
index 344bd6a081..cce9897256 100644
--- a/Resources/Prototypes/Catalog/uplink_catalog.yml
+++ b/Resources/Prototypes/Catalog/uplink_catalog.yml
@@ -250,6 +250,36 @@
- UplinkExplosives
restockTime: 30
+- type: listing
+ id: UplinkClusterGrenade
+ name: uplink-cluster-grenade-name
+ description: uplink-cluster-grenade-desc
+ productEntity: ClusterGrenade
+ cost:
+ Telecrystal: 8
+ categories:
+ - UplinkExplosives
+
+- type: listing
+ id: UplinkGrenadeShrapnel
+ name: uplink-shrapnel-grenade-name
+ description: uplink-shrapnel-grenade-desc
+ productEntity: GrenadeShrapnel
+ cost:
+ Telecrystal: 4
+ categories:
+ - UplinkExplosives
+
+- type: listing
+ id: UplinkGrenadeIncendiary
+ name: uplink-incendiary-grenade-name
+ description: uplink-incendiary-grenade-desc
+ productEntity: GrenadeIncendiary
+ cost:
+ Telecrystal: 4
+ categories:
+ - UplinkExplosives
+
# Ammo
- type: listing
@@ -956,6 +986,20 @@
whitelist:
- Clown
+- type: listing
+ id: UplinkClusterBananaPeel
+ name: uplink-cluster-banana-peel-name
+ description: uplink-cluster-banana-peel-desc
+ productEntity: ClusterBananaPeel
+ cost:
+ Telecrystal: 6
+ categories:
+ - UplinkJob
+ conditions:
+ - !type:BuyerJobCondition
+ whitelist:
+ - Clown
+
- type: listing
id: UplinkHoloclownKit
name: uplink-holoclown-kit-name
@@ -1186,6 +1230,16 @@
categories:
- UplinkMisc
+- type: listing
+ id: UplinkSlipocalypseClusterSoap
+ name: uplink-slipocalypse-clustersoap-name
+ description: uplink-slipocalypse-clustersoap-desc
+ productEntity: SlipocalypseClusterSoap
+ cost:
+ Telecrystal: 3
+ categories:
+ - UplinkMisc
+
- type: listing
id: UplinkUltrabrightLantern
name: uplink-ultrabright-lantern-name
diff --git a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml
index 09f48b258e..ca267a308c 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/Janitorial/soap.yml
@@ -128,6 +128,46 @@
- clean
- punishment
+- type: entity
+ name: soaplet
+ id: SoapletSyndie
+ noSpawn: true
+ parent: Soap
+ description: A tiny piece of syndicate soap.
+ components:
+ - type: Sprite
+ layers:
+ - state: syndie-soaplet
+ - type: Slippery
+ paralyzeTime: 5
+ launchForwardsMultiplier: 2.5
+ - type: StepTrigger
+ intersectRatio: 0.04
+ - type: Item
+ heldPrefix: syndie
+ - type: Fixtures
+ fixtures:
+ slips:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.08,-0.06,0.08,0.06"
+ layer:
+ - SlipLayer
+ hard: false
+ fix1:
+ shape:
+ !type:PhysShapeAabb
+ bounds: "-0.08,-0.06,0.08,0.06"
+ density: 1
+ mask:
+ - ItemMask
+ - type: DeleteOnTrigger
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Effects/Fluids/splat.ogg"
+ params:
+ volume: -20
+
- type: entity
name: soap
id: SoapHomemade
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Bombs/funny.yml b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/funny.yml
index 84883c975d..7d95e7481e 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Bombs/funny.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Bombs/funny.yml
@@ -83,11 +83,23 @@
- type: ExplodeOnTrigger
- type: Explosive
explosionType: Default
- maxIntensity: 2
- totalIntensity: 10
+ maxIntensity: 3.4
+ intensitySlope: 3
+ totalIntensity: 20
canCreateVacuum: false
- type: DeleteOnTrigger
- type: AnimationPlayer
+ - type: Damageable
+ damageContainer: Inorganic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 10
+ behaviors:
+ - !type:TriggerBehavior
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
- type: entity
parent: BaseItem
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/grenade.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/grenade.yml
new file mode 100644
index 0000000000..511cf76df9
--- /dev/null
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Ammunition/Projectiles/grenade.yml
@@ -0,0 +1,58 @@
+- type: entity
+ id: PelletClusterRubber
+ name: pellet (ball, Rubber)
+ noSpawn: true
+ parent: BaseBullet
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi
+ state: buckshot
+ - type: Projectile
+ deleteOnCollide: false
+ canPenetrate: true
+ damage:
+ types:
+ Blunt: 4
+ - type: StaminaDamageOnCollide
+ damage: 55
+ - type: TimedDespawn
+ lifetime: 0.25
+
+- type: entity
+ id: PelletClusterLethal
+ name: pellet (ball, Lethal)
+ noSpawn: true
+ parent: BaseBullet
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi
+ state: buckshot
+ - type: Projectile
+ deleteOnCollide: false
+ canPenetrate: true
+ damage:
+ types:
+ Piercing: 45
+ - type: TimedDespawn
+ lifetime: 0.25
+
+- type: entity
+ id: PelletClusterIncendiary
+ name: pellet (ball, incendiary)
+ noSpawn: true
+ parent: BaseBulletIncendiary
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Guns/Projectiles/projectiles2.rsi
+ state: buckshot-flare
+ - type: Projectile
+ deleteOnCollide: false
+ canPenetrate: true
+ damage:
+ groups:
+ Burn: 4
+ - type: IgniteOnCollide
+ fireStacks: 3
+ count: 10
+ - type: TimedDespawn
+ lifetime: 0.25
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
index b94191ef02..d5bca926b9 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Guns/Projectiles/projectiles.yml
@@ -641,6 +641,11 @@
- state: grenade
- type: FlashOnTrigger
range: 7
+ - type: SpawnOnTrigger
+ proto: GrenadeFlashEffect
+ - type: ActiveTimerTrigger
+ timeRemaining: 0.3
+ - type: DeleteOnTrigger
# This is supposed to spawn shrapnel and stuff so uhh... TODO?
- type: entity
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/clusterbang.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/clusterbang.yml
index f7d0a0e5df..43ed06a3ea 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/clusterbang.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/clusterbang.yml
@@ -11,16 +11,233 @@
- type: ClusterGrenadeVisuals
state: base
- type: ClusterGrenade
+ - type: OnUseTimerTrigger
+ delay: 3.5
- type: ContainerContainer
containers:
- cluster-flash: !type:Container
+ cluster-payload: !type:Container
- type: entity
- parent: ClusterBang
+ parent: GrenadeBase
id: ClusterBangFull
+ name: ClusterBang
+ description: Launches three flashbangs after the timer runs out.
suffix: Full
components:
- type: Sprite
- state: base-3
+ sprite: Objects/Weapons/Grenades/clusterbang.rsi
+ layers:
+ - state: icon
+ map: ["enum.TriggerVisualLayers.Base"]
- type: ClusterGrenade
fillPrototype: GrenadeFlashBang
+ distance: 7
+ velocity: 7
+ - type: TimerTriggerVisuals
+ primingSound:
+ path: /Audio/Effects/countdown.ogg
+ - type: GenericVisualizer
+ visuals:
+ enum.Trigger.TriggerVisuals.VisualState:
+ enum.ConstructionVisuals.Layer:
+ Primed: { state: primed }
+ Unprimed: { state: icon }
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Machines/door_lock_off.ogg"
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: GrenadeBase
+ id: ClusterGrenade
+ name: clustergrenade
+ description: Why use one grenade when you can use three at once!
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/clusterbomb.rsi
+ layers:
+ - state: icon
+ map: ["enum.TriggerVisualLayers.Base"]
+ - type: ClusterGrenade
+ fillPrototype: ExGrenade
+ velocity: 3.5
+ distance: 5
+ - type: OnUseTimerTrigger
+ beepSound:
+ path: "/Audio/Effects/beep1.ogg"
+ params:
+ volume: 5
+ initialBeepDelay: 0
+ beepInterval: 0.5
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Machines/door_lock_off.ogg"
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: BaseItem
+ id: ClusterBananaPeel
+ name: cluster banana peel
+ description: Splits into 6 explosive banana peels after throwing, guaranteed fun!
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Hydroponics/banana.rsi
+ state: produce
+ - type: Appearance
+ - type: ClusterGrenade
+ fillPrototype: TrashBananaPeelExplosive
+ maxGrenadesCount: 6
+ baseTriggerDelay: 20
+ - type: DamageOnLand
+ damage:
+ types:
+ Blunt: 10
+ - type: Damageable
+ damageContainer: Inorganic
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Items/bikehorn.ogg"
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 10
+ behaviors:
+ - !type:TriggerBehavior
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: GrenadeBase
+ id: GrenadeStinger
+ name: stinger grenade
+ description: Nothing to see here, please disperse.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/stingergrenade.rsi
+ layers:
+ - state: icon
+ map: ["enum.TriggerVisualLayers.Base"]
+ - type: ClusterGrenade
+ fillPrototype: PelletClusterRubber
+ maxGrenadesCount: 30
+ grenadeType: enum.GrenadeType.Shoot
+ - type: FlashOnTrigger
+ range: 7
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Effects/flash_bang.ogg"
+ - type: SpawnOnTrigger
+ proto: GrenadeFlashEffect
+ - type: TimerTriggerVisuals
+ primingSound:
+ path: /Audio/Effects/countdown.ogg
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: GrenadeBase
+ id: GrenadeIncendiary
+ name: incendiary grenade
+ description: Guaranteed to light up the mood.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/pyrogrenade.rsi
+ layers:
+ - state: icon
+ map: ["enum.TriggerVisualLayers.Base"]
+ - type: ClusterGrenade
+ fillPrototype: PelletClusterIncendiary
+ maxGrenadesCount: 15
+ grenadeType: enum.GrenadeType.Shoot
+ - type: OnUseTimerTrigger
+ beepSound:
+ path: "/Audio/Effects/beep1.ogg"
+ params:
+ volume: 5
+ initialBeepDelay: 0
+ beepInterval: 2
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Weapons/Guns/Gunshots/batrifle.ogg"
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: GrenadeBase
+ id: GrenadeShrapnel
+ name: shrapnel grenade
+ description: Releases a deadly spray of shrapnel that causes severe bleeding.
+ components:
+ - type: Sprite
+ sprite: Objects/Weapons/Grenades/shrapnelgrenade.rsi
+ layers:
+ - state: icon
+ map: ["enum.TriggerVisualLayers.Base"]
+ - type: ClusterGrenade
+ fillPrototype: PelletClusterLethal
+ maxGrenadesCount: 30
+ grenadeType: enum.GrenadeType.Shoot
+ - type: OnUseTimerTrigger
+ beepSound:
+ path: "/Audio/Effects/beep1.ogg"
+ params:
+ volume: 5
+ initialBeepDelay: 0
+ beepInterval: 2
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Weapons/Guns/Gunshots/batrifle.ogg"
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
+
+- type: entity
+ parent: SoapSyndie
+ id: SlipocalypseClusterSoap
+ name: slipocalypse clustersoap
+ description: Spreads small pieces of syndicate soap over an area upon landing on the floor.
+ components:
+ - type: Sprite
+ sprite: Objects/Specific/Janitorial/soap.rsi
+ layers:
+ - state: syndie-4
+ - type: Appearance
+ - type: ClusterGrenade
+ fillPrototype: SoapletSyndie
+ maxGrenadesCount: 30
+ grenadeTriggerIntervalMax: 0
+ grenadeTriggerIntervalMin: 0
+ baseTriggerDelay: 60
+ randomSpread: true
+ velocity: 3
+ - type: DamageOnLand
+ damage:
+ types:
+ Blunt: 10
+ - type: EmitSoundOnTrigger
+ sound:
+ path: "/Audio/Effects/flash_bang.ogg"
+ - type: Damageable
+ damageContainer: Inorganic
+ - type: Destructible
+ thresholds:
+ - trigger:
+ !type:DamageTrigger
+ damage: 10
+ behaviors:
+ - !type:TriggerBehavior
+ - !type:DoActsBehavior
+ acts: ["Destruction"]
+ - type: ContainerContainer
+ containers:
+ cluster-payload: !type:Container
diff --git a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml
index ece4ec4ef4..7f5124a5eb 100644
--- a/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml
+++ b/Resources/Prototypes/Entities/Objects/Weapons/Throwable/grenades.yml
@@ -29,7 +29,12 @@
acts: ["Destruction"]
- type: Appearance
- type: AnimationPlayer
- - type: TimerTriggerVisuals
+ - type: GenericVisualizer
+ visuals:
+ enum.Trigger.TriggerVisuals.VisualState:
+ enum.ConstructionVisuals.Layer:
+ Primed: { state: primed }
+ Unprimed: { state: icon }
- type: entity
name: explosive grenade
diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json
index 1b0c2eb436..ce6de2f88f 100644
--- a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json
+++ b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/meta.json
@@ -79,6 +79,9 @@
{
"name": "syndie-4"
},
+ {
+ "name": "syndie-soaplet"
+ },
{
"name": "inhand-left",
"directions": 4
diff --git a/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-soaplet.png b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-soaplet.png
new file mode 100644
index 0000000000000000000000000000000000000000..b07121978187ceb85a296d61bfdd4fef28e76c18
GIT binary patch
literal 157
zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|gaUj*T!Hj_
zU*9_$H%@eNI#*eFx~C`1q;4Tll&vJlFPPy!2vk)*_y-hG_jGX#vFJ@skYGJ5ZeV2i
wIQ+n&Q!Vj~!rI(*tY>_Bmh8+F;ZbE^@X}{c?kvh=2WnyPboFyt=akR{0DHeL!TEfE%=JyPLbN3y$L`9W_nENkCbaP!vUv+#&*m?e!OI-d865Dg%^yirg>^P!XDPK8t_~mSqV9XnqWO1jgz`!1`8I)y+}n_hkr&(h0VY%E0#J
z72rc!yxPI~#$0S`k^n`DU%J_w`#T{6hoKs{&FP^-|
z^|*661ET~$dXmYI=Xoms-BYg886u#eq4B=}fFD$G5%ekS^Tq%G002ovPDHLkV1jqx
B(SZN}
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/meta.json
index 01b494cc95..c017ee2117 100644
--- a/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/meta.json
+++ b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/meta.json
@@ -22,6 +22,19 @@
{
"name": "base-3",
"directions": 1
+ },
+ {
+ "name": "icon",
+ "directions": 1
+ },
+ {
+ "name": "primed",
+ "delays": [
+ [
+ 0.1,
+ 0.1
+ ]
+ ]
}
]
}
diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/primed.png
new file mode 100644
index 0000000000000000000000000000000000000000..7ce992cde8f781cd9e84db17b9c72f9935b10786
GIT binary patch
literal 680
zcmV;Z0$2TsP)Px%Vo5|nRA_$+B+=LZKbm&>i7wI_K|{a4k2Ns@pN0>^QLNa^x@Uy6reD6c%v
z`Sta+(#CNd5JHe7iEdM^>%Ts@9>+1J
z(<#z4m9~sAVbhql^ba~fF#7NhH-E0G-5dbMux!wGL2C5QZUuC(m~}9jF#`
z>gL!mlM?l5s
z-92#orri1Y9)zjKKR2Uax4_>@=lcxgqj&UNS_cSEGsfhb_2%v^m{;Cya2Ei0z;HM$
zMW;KHQH@hg;>KC$u
zeA8z{BL|3$h$z>g%8pYJ8xc{i)mLOk9a;y76rz*@fOc|9DJZ3-LgW5@1IG@j-
zb=OJC&x3jnum+uD_o0QNoqee)YBuH=1!9sqT9X4|&4*=(AY!>#J?{S1jk>Px$jY&j7R9J=Wl(BAuFc5}+H;l=ciRO3!OU;}iWDa8=z*C;g50H`B$~$<>0BM$X
zG$WBaBu0b;FlwcC;FA#N^Ko~+I|Gc2jEwv-tf^2+Rk9GmHut5JY_r+;2Vf5&?g-j8
zgbn(ZG{|X^B=yR5Ci~LoY-n(Y*4oRiw*qar
zQx?WxI-3CiOVhO4zmz2kV|x8ORN&d*wV|~}mgm0aehCcaQkFmZzPAOgms)Ea4hH~0
z6h*ck_-12Y!w{3;>T(hUt~H%_RUqHbk?-eNq@Pa3-j>TMSVV+~hyh@ivSjt^+lSW>
z()$+x;KVtAtLz5MB~iy`_`DNvr-|bjz-{od3`vq8A_4$RXEPMW;NyJ0+OF5Xmw@AV
zJl?GfV^~do`i)N|9ukmJG9iR@Z>MkmSlp@W>$=Q2AJmEpr4*D>AR!%F8WGyGWXbk0Dt4Zj_HWMt%D@C~HBx_12kaoqp_002ov
JPDHLkV1foN)Y5
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-2.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-2.png
new file mode 100644
index 0000000000000000000000000000000000000000..392d6981b4433a1e28cd1d6d90caaa9e42955635
GIT binary patch
literal 502
zcmVPx$ut`KgR9J=Wm9cKZFc60Sv>nOVE{MwmL@G0jVU5Q=fTz3+ui*#i$ZS}60*?%a
ztsTQi@KA#7Zt=H>l
z438I!#l^d)m@=i5&-1*V3n4I@&7hR>&bce$9HX_ycDu!9vuWFdF%K~T%w#p`a=9zE
zQ@}wUel4I+Z1f1akWzX8I93%#X$l1DsSj5>5GtY=)>^pzzV~9G+?_|z#nPx$mPtfGR9J=WRl82ZFcdu?egT%MK~+bOOj(>v5$ebXFcztk<0TWL
z$Ep%hm-ZvV0N2=#^J*)x_(+lby7!)QoZJ8b0RaIH>bmZIgb;|Ls5T!V#GqIgckV(_
z6ndQJc_U)IUfb6@L@imTLfr+4jKfy?u#I$gi=b+l~OR@
zmp1%fot6762d0}NK0fcQwdbcJ)Z_SEy#z?9QcAzs)#3q>;Q#EB2w7}pF0;3APYI?0AShc1Lqu^bE^?uM1Zi{
z?XG&Rl>oI_x81tR_pf_E{*B`z2H@|GX3jKCt-V_xE3-IbOm{xBKg`}{@QvwAmSy_-
zx_V1vQ3#>Od7jr)oRqcw@!UN#&MfXa&`E$uxayK5@zvMAa$igvfq;O3f5$hPx%RY^oaRA_2*teGoKClCA2$DGrR|7>?t>vMer=yIj{5;=b>TD@{|@
z>-D5DmSw?l9K>;4_fl8ae_Qn+yWNg?o+s`JAs7q>2!ep&kU3%nHk%CqV6|GYFbpxD
z&yggFh^3VB7-g=dU&??Y)9F^$%>W>ZB1BOHN@FoYAOL>hpac
zz<=kv-7fe8)x|bt^y~I?eMxMQk^w;w)CTqY{oDia`#MzSzP7$B18Tq5BuR2~cX>P>=Z>1p5tUn=n=el))3>UxWB{LtyL=4U>b#Uo>em{;
zQ-}}(0F`GhhY$inNUjih376Ja-UOG+C
zwr!+o%8re%K*aF>>0uZGfRX`i>T5I_jYji|cm{p!x#B5A7zY3V002ovPDHLkV1foY
BJLv!b
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/equipped-BELT.png b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/equipped-BELT.png
new file mode 100644
index 0000000000000000000000000000000000000000..20d341ef8c8ba81b0108b0235cffa4df2687ec2e
GIT binary patch
literal 234
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|mUy~2hE&XX
zdutPx#+(|@1R9J=WmAeYUFcd(K;wJt=meQ%vMV#C_`UieT|40A8v16cg7c#jOI*W+l
zB6ZM+uO+uZhvrO4;O3s(ydV$=^qqkuNGa9Yc3sz^Im7}sd6s1W6h+ZVV(1$1oUCb@
z7bywi3cO1xrCLcPMy|Fw(8v{DHt0e~oqz6pqN7SLK_jCu5vB>AntdNJWL9Ro01
zojN54!7cEOa|M>0BgS-JxmY02bE>LBYyBSqxE;j(;ruZ!c?ZO2AT49kGM0vS7x0B>
o3jntBofiRbe}Na9Kp@adu2iy3JzqYuO8@`>07*qoM6N<$f)QnQ)c^nh
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/meta.json
new file mode 100644
index 0000000000..28d3e6969a
--- /dev/null
+++ b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/meta.json
@@ -0,0 +1,27 @@
+{
+ "version": 1,
+ "license": "CC-BY-SA-3.0",
+ "copyright": "Taken from tgstation at https://github.com/tgstation/tgstation/commit/b13d244d761a07e200a9a41730bd446e776020d5",
+ "size": {
+ "x": 32,
+ "y": 32
+ },
+ "states": [
+ {
+ "name": "icon"
+ },
+ {
+ "name": "primed",
+ "delays": [
+ [
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "equipped-BELT",
+ "directions": 4
+ }
+ ]
+}
diff --git a/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/primed.png
new file mode 100644
index 0000000000000000000000000000000000000000..fbe975391a57a23d14364d615ba75ab645b35d5d
GIT binary patch
literal 349
zcmV-j0iyniP)Px$7fD1xRA_7Gh#i1P}y45Cq|0X}J_BrK+gm?H!0RTV{1g{$K
z2DhIafYut;+UtE7hAfSI%1;hpIql&%=mG$Si+v-x3*3J4Tj19qPrz)ogSGyj{JZ?*
z0FoquF$P*|wkAI5CkFtW52DTX@U-shi;&ardE;Xkf*=TjAp8y|JEWX|vKyvu00000NkvXXu0mjfO1G5^
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/equipped-BELT.png b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/equipped-BELT.png
new file mode 100644
index 0000000000000000000000000000000000000000..3b76c4e57f2e03254a2cbde32a7c4621feb8bd84
GIT binary patch
literal 233
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|7JIrlhE&XX
zdut~~uKi#h91Zq0KersFo
z_iKeKxL)nbo4ZWY^V0X)$amYV`$QEzi)w8yoA|aRuIRe6Wbqq@>6f)X+dRK_Z?%&7
zOAYG-n{*_P8$Q3iQ|ptuEYKj3S^rnw;Hr7rzrS_WT8EqE71^QDjd$f1WNB}>&3pss
bj|1-axYzi1-g|RH6{OtL)z4*}Q$iB}rkq|4
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..5bb1563118d025b37dff1fae50cb4bcc414194e1
GIT binary patch
literal 293
zcmV+=0owkFP)Px#-$_J4R9J=WmA?vtP!xy1BH9{yfxCz_2yRX7zD3XB1N9b;7sN3L?htK)vqVcv
z*ic6QAnx&2gZG>C;_-a`JbJ<7@${X6q(~{%w8v#xitZs6XqzWV0zj5!og{{~1^3OW
zs(O%;AWq;}N-5Pyk{H=GZ=-LY{z@a2uo3_Wg5aHi7;6EoHO83Rc@#yz6Px$8A(JzRA_Q9`Bj*usktVPZwzS&9Hjp}~
zjg7=YBmRNRW?WI{RmqasH+&461P}y45Cq|0X}J_BrKssCzGf!dWY2$t55OggZ
xPx_pF(EW=k%RX%X0xaEpfnN{=K@f!B;Rx;IoOBo#Q1k!*002ovPDHLkV1ge%l92!a
literal 0
HcmV?d00001
diff --git a/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/equipped-BELT.png b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/equipped-BELT.png
new file mode 100644
index 0000000000000000000000000000000000000000..85a06f2d4d8362e5da14ef191ad065e22cfce242
GIT binary patch
literal 254
zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I1|(Ny7TyC=jKx9jP7LeL$-D$|c6hothE&XX
zdut=_Ap?wnkoideesy@9oZrmLY_?0oUnCw#5KR(H?Z+b~ZSY#`XszK9&wS$`gXPuMDI@LTrX
t*(_~?H;n(bGiCEsHz;mn0@+*lmtlK;*zQHPx#@<~KNR9J=Wlrav1FcgM=jDt?b)u9U`2XJM2gI6%=B^)?~m*^p!n=Zry^a3Qf
z8N;L-PAH&>c@%JW1ppM6z0={H1Rl2oii`c7IFvw=BuLW~#+Y6N
z*mIz7dKGAo<Px$Gf6~2RA_GgitrOG7+diL@$1|CHlTGa{T@JWhXYED2k#e%DHmE8Qe4t0Ki&%_AO&
z{_+<^!J2C}RZc`8qN6Y|koL0+_}+Nm_eY^(Anl*L0_wVk_kIW!s|0C3YyTQ!4nzdt
zt9=0Q-VY&8`Ax9aj{3W