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 0000000000..b071219781 Binary files /dev/null and b/Resources/Textures/Objects/Specific/Janitorial/soap.rsi/syndie-soaplet.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/icon.png new file mode 100644 index 0000000000..18a1d3042c Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/icon.png differ 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 0000000000..7ce992cde8 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbang.rsi/primed.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-1.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-1.png new file mode 100644 index 0000000000..d28cae5a6b Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-1.png differ 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 0000000000..392d6981b4 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/base-2.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/icon.png new file mode 100644 index 0000000000..7b4ccd1c0f Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/meta.json new file mode 100644 index 0000000000..a4d1e8aeb9 --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/meta.json @@ -0,0 +1,29 @@ +{ + "version": 1, + "license": "CC-BY-SA-3.0", + "copyright": "Taken from tgstation and modified by Swept at https://github.com/tgstation/tgstation/commit/29c0ed1b000619cb5398ef921000a8d4502ba0b6 and modified by Swept", + "size": { + "x": 32, + "y": 32 + }, + "states": [ + { + "name": "icon" + }, + { + "name": "base-1" + }, + { + "name": "base-2" + }, + { + "name": "primed", + "delays": [ + [ + 0.1, + 0.1 + ] + ] + } + ] +} diff --git a/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/primed.png new file mode 100644 index 0000000000..b3383c172d Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/clusterbomb.rsi/primed.png differ 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 0000000000..20d341ef8c Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/equipped-BELT.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/icon.png new file mode 100644 index 0000000000..50421bf708 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/icon.png differ 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 0000000000..fbe975391a Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/pyrogrenade.rsi/primed.png differ 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 0000000000..3b76c4e57f Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/equipped-BELT.png differ 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 0000000000..5bb1563118 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/meta.json new file mode 100644 index 0000000000..28d3e6969a --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.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/shrapnelgrenade.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/primed.png new file mode 100644 index 0000000000..2369617cd3 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/shrapnelgrenade.rsi/primed.png differ 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 0000000000..85a06f2d4d Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/equipped-BELT.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/icon.png b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/icon.png new file mode 100644 index 0000000000..1fae857453 Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/icon.png differ diff --git a/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/meta.json b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/meta.json new file mode 100644 index 0000000000..28d3e6969a --- /dev/null +++ b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.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/stingergrenade.rsi/primed.png b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/primed.png new file mode 100644 index 0000000000..32d39cb89f Binary files /dev/null and b/Resources/Textures/Objects/Weapons/Grenades/stingergrenade.rsi/primed.png differ diff --git a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi/meta.json b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi/meta.json index 5a58b6b608..bfdf73fe57 100644 --- a/Resources/Textures/Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi/meta.json +++ b/Resources/Textures/Objects/Weapons/Guns/Ammunition/Explosives/explosives.rsi/meta.json @@ -29,4 +29,4 @@ "name": "spent" } ] -} \ No newline at end of file +}