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)YPx$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