Шейдер ударной волны для взрывов (#633)
* Adds shock wave shader (#2631) Co-authored-by: DOOM <N/A> Co-authored-by: Whisper <121047731+QuietlyWhisper@users.noreply.github.com> * add explosive shockwave * add shockwave to fireball * wd edit * cleanup * remove exgreande beeping sound --------- Co-authored-by: Vero <73014819+vero5123@users.noreply.github.com> Co-authored-by: Whisper <121047731+QuietlyWhisper@users.noreply.github.com>
@@ -1,7 +1,6 @@
|
|||||||
using Content.Client._White.Chat;
|
using Content.Client._White.Chat;
|
||||||
using Content.Client._White.JoinQueue;
|
using Content.Client._White.JoinQueue;
|
||||||
using Content.Client._White.Jukebox;
|
using Content.Client._White.Jukebox;
|
||||||
using Content.Client._White.Overlays;
|
|
||||||
using Content.Client._White.Reputation;
|
using Content.Client._White.Reputation;
|
||||||
using Content.Client._White.Sponsors;
|
using Content.Client._White.Sponsors;
|
||||||
using Content.Client._White.Stalin;
|
using Content.Client._White.Stalin;
|
||||||
@@ -10,7 +9,6 @@ using Content.Client.Administration.Managers;
|
|||||||
using Content.Client.Changelog;
|
using Content.Client.Changelog;
|
||||||
using Content.Client.Chat.Managers;
|
using Content.Client.Chat.Managers;
|
||||||
using Content.Client.Eui;
|
using Content.Client.Eui;
|
||||||
using Content.Client.Flash;
|
|
||||||
using Content.Client.Fullscreen;
|
using Content.Client.Fullscreen;
|
||||||
using Content.Client.GhostKick;
|
using Content.Client.GhostKick;
|
||||||
using Content.Client.Guidebook;
|
using Content.Client.Guidebook;
|
||||||
@@ -26,6 +24,7 @@ using Content.Client.Radiation.Overlays;
|
|||||||
using Content.Client.Replay;
|
using Content.Client.Replay;
|
||||||
using Content.Client.Screenshot;
|
using Content.Client.Screenshot;
|
||||||
using Content.Client.Singularity;
|
using Content.Client.Singularity;
|
||||||
|
using Content.Client._White.Explosion;
|
||||||
using Content.Client.Stylesheets;
|
using Content.Client.Stylesheets;
|
||||||
using Content.Client.Viewport;
|
using Content.Client.Viewport;
|
||||||
using Content.Client.Voting;
|
using Content.Client.Voting;
|
||||||
@@ -179,6 +178,7 @@ namespace Content.Client.Entry
|
|||||||
_parallaxManager.LoadDefaultParallax();
|
_parallaxManager.LoadDefaultParallax();
|
||||||
|
|
||||||
_overlayManager.AddOverlay(new SingularityOverlay());
|
_overlayManager.AddOverlay(new SingularityOverlay());
|
||||||
|
_overlayManager.AddOverlay(new ExplosionShockWaveOverlay());
|
||||||
_overlayManager.AddOverlay(new RadiationPulseOverlay());
|
_overlayManager.AddOverlay(new RadiationPulseOverlay());
|
||||||
// _overlayManager.AddOverlay(new GrainOverlay());
|
// _overlayManager.AddOverlay(new GrainOverlay());
|
||||||
// _overlayManager.AddOverlay(new AtmOverlay());
|
// _overlayManager.AddOverlay(new AtmOverlay());
|
||||||
|
|||||||
@@ -0,0 +1,90 @@
|
|||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Shared._White.Explosion;
|
||||||
|
|
||||||
|
namespace Content.Client._White.Explosion;
|
||||||
|
|
||||||
|
public sealed class ExplosionShockWaveOverlay : Overlay, IEntityEventSubscriber
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
|
||||||
|
private SharedTransformSystem? _xformSystem;
|
||||||
|
|
||||||
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
|
public override bool RequestScreenTexture => true;
|
||||||
|
|
||||||
|
private readonly ShaderInstance _shader;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of distortions that can be shown on screen at a time.
|
||||||
|
/// </summary>
|
||||||
|
public const int MaxCount = 30;
|
||||||
|
|
||||||
|
public ExplosionShockWaveOverlay()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_shader = _prototypeManager.Index<ShaderPrototype>("ShockWave").Instance().Duplicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private readonly Vector2[] _positions = new Vector2[MaxCount];
|
||||||
|
private readonly float[] _falloffPower = new float[MaxCount];
|
||||||
|
private readonly float[] _sharpness = new float[MaxCount];
|
||||||
|
private readonly float[] _width = new float[MaxCount];
|
||||||
|
private int _count;
|
||||||
|
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
if (args.Viewport.Eye == null || _xformSystem is null && !_entMan.TrySystem(out _xformSystem))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
var query = _entMan.EntityQueryEnumerator<ExplosionShockWaveComponent, TransformComponent>();
|
||||||
|
|
||||||
|
_count = 0;
|
||||||
|
|
||||||
|
while (query.MoveNext(out var uid, out var distortion, out var xform))
|
||||||
|
{
|
||||||
|
if (xform.MapID != args.MapId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var mapPos = _xformSystem.GetWorldPosition(uid);
|
||||||
|
|
||||||
|
var tempCoords = args.Viewport.WorldToLocal(mapPos);
|
||||||
|
|
||||||
|
// normalized coords, 0 - 1 plane. This is pure hell, we subtract 1 because fragment calculates from the bottom and local goes from the top of the viewport
|
||||||
|
tempCoords.Y = 1 - (tempCoords.Y / args.Viewport.Size.Y);
|
||||||
|
tempCoords.X /= args.Viewport.Size.X;
|
||||||
|
|
||||||
|
_positions[_count] = tempCoords;
|
||||||
|
_falloffPower[_count] = distortion.FalloffPower;
|
||||||
|
_sharpness[_count] = distortion.Sharpness;
|
||||||
|
_width[_count] = distortion.Width;
|
||||||
|
_count++;
|
||||||
|
|
||||||
|
if (_count == MaxCount)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _count > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
if (ScreenTexture == null || args.Viewport.Eye == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_shader?.SetParameter("renderScale", args.Viewport.RenderScale * args.Viewport.Eye.Scale);
|
||||||
|
_shader?.SetParameter("count", _count);
|
||||||
|
_shader?.SetParameter("position", _positions);
|
||||||
|
_shader?.SetParameter("falloffPower", _falloffPower);
|
||||||
|
_shader?.SetParameter("sharpness", _sharpness);
|
||||||
|
_shader?.SetParameter("width", _width);
|
||||||
|
_shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||||
|
|
||||||
|
var worldHandle = args.WorldHandle;
|
||||||
|
worldHandle.UseShader(_shader);
|
||||||
|
worldHandle.DrawRect(args.WorldAABB, Color.White);
|
||||||
|
worldHandle.UseShader(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
|
using System.Numerics;
|
||||||
using Content.Server.Explosion.Components;
|
using Content.Server.Explosion.Components;
|
||||||
|
using Content.Server.Weapons.Ranged.Systems;
|
||||||
|
using Content.Shared.Explosion.Components;
|
||||||
using Content.Shared.Flash.Components;
|
using Content.Shared.Flash.Components;
|
||||||
using Content.Shared.Interaction;
|
using Content.Shared.Interaction;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Robust.Shared.Containers;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Content.Server.Weapons.Ranged.Systems;
|
|
||||||
using System.Numerics;
|
|
||||||
using Content.Shared.Explosion.Components;
|
|
||||||
using Robust.Server.Containers;
|
using Robust.Server.Containers;
|
||||||
using Robust.Server.GameObjects;
|
using Robust.Server.GameObjects;
|
||||||
|
using Robust.Shared.Containers;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
namespace Content.Server.Explosion.EntitySystems;
|
namespace Content.Server.Explosion.EntitySystems;
|
||||||
|
|
||||||
@@ -114,6 +114,7 @@ public sealed class ClusterGrenadeSystem : EntitySystem
|
|||||||
RaiseLocalEvent(uid, ref ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// delete the empty shell of the clusterbomb
|
// delete the empty shell of the clusterbomb
|
||||||
Del(uid);
|
Del(uid);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ using Content.Server.Explosion.Components;
|
|||||||
using Content.Server.NodeContainer.EntitySystems;
|
using Content.Server.NodeContainer.EntitySystems;
|
||||||
using Content.Server.NPC.Pathfinding;
|
using Content.Server.NPC.Pathfinding;
|
||||||
using Content.Server.Station.Systems;
|
using Content.Server.Station.Systems;
|
||||||
|
using Content.Shared._White.Explosion;
|
||||||
using Content.Shared.Audio;
|
using Content.Shared.Audio;
|
||||||
using Content.Shared.Armor;
|
using Content.Shared.Armor;
|
||||||
using Content.Shared.Camera;
|
using Content.Shared.Camera;
|
||||||
@@ -176,6 +177,11 @@ public sealed partial class ExplosionSystem
|
|||||||
totalIntensity ??= RadiusToIntensity((float) radius, explosive.IntensitySlope, explosive.MaxIntensity);
|
totalIntensity ??= RadiusToIntensity((float) radius, explosive.IntensitySlope, explosive.MaxIntensity);
|
||||||
totalIntensity ??= explosive.TotalIntensity;
|
totalIntensity ??= explosive.TotalIntensity;
|
||||||
|
|
||||||
|
// WD edit start
|
||||||
|
var ev = new ExplosiveTriggeredEvent();
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
// WD edit end
|
||||||
|
|
||||||
QueueExplosion(uid,
|
QueueExplosion(uid,
|
||||||
explosive.ExplosionType,
|
explosive.ExplosionType,
|
||||||
(float) totalIntensity,
|
(float) totalIntensity,
|
||||||
|
|||||||
@@ -69,16 +69,18 @@ public sealed class ProjectileSystem : SharedProjectileSystem
|
|||||||
var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage * DamageModifier, component.IgnoreResistances, origin: component.Shooter);
|
var modifiedDamage = _damageableSystem.TryChangeDamage(target, ev.Damage * DamageModifier, component.IgnoreResistances, origin: component.Shooter);
|
||||||
var deleted = Deleted(target);
|
var deleted = Deleted(target);
|
||||||
|
|
||||||
if (modifiedDamage is not null && EntityManager.EntityExists(component.Shooter))
|
if (modifiedDamage is not null && (EntityManager.EntityExists(component.Shooter) || EntityManager.EntityExists(component.Weapon)))
|
||||||
{
|
{
|
||||||
if (modifiedDamage.Any() && !deleted)
|
if (modifiedDamage.Any() && !deleted)
|
||||||
{
|
{
|
||||||
_color.RaiseEffect(Color.Red, new List<EntityUid> { target }, Filter.Pvs(target, entityManager: EntityManager));
|
_color.RaiseEffect(Color.Red, new List<EntityUid> { target }, Filter.Pvs(target, entityManager: EntityManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var shooterOrWeapon = EntityManager.EntityExists(component.Shooter) ? component.Shooter!.Value : component.Weapon!.Value;
|
||||||
|
|
||||||
_adminLogger.Add(LogType.BulletHit,
|
_adminLogger.Add(LogType.BulletHit,
|
||||||
HasComp<ActorComponent>(target) ? LogImpact.Extreme : LogImpact.High,
|
HasComp<ActorComponent>(target) ? LogImpact.Extreme : LogImpact.High,
|
||||||
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(component.Shooter!.Value):user} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
|
$"Projectile {ToPrettyString(uid):projectile} shot by {ToPrettyString(shooterOrWeapon):source} hit {otherName:target} and dealt {modifiedDamage.GetTotal():damage} damage");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!deleted)
|
if (!deleted)
|
||||||
|
|||||||
@@ -203,9 +203,9 @@ public abstract partial class SharedProjectileSystem : EntitySystem
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetShooter(EntityUid id, ProjectileComponent component, EntityUid shooterId)
|
public void SetShooter(EntityUid id, ProjectileComponent component, EntityUid? shooterId = null)
|
||||||
{
|
{
|
||||||
if (component.Shooter == shooterId)
|
if (component.Shooter == shooterId || shooterId == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
component.Shooter = shooterId;
|
component.Shooter = shooterId;
|
||||||
|
|||||||
@@ -423,7 +423,7 @@ public abstract partial class SharedGunSystem : EntitySystem
|
|||||||
Physics.SetLinearVelocity(uid, finalLinear, body: physics);
|
Physics.SetLinearVelocity(uid, finalLinear, body: physics);
|
||||||
|
|
||||||
var projectile = EnsureComp<ProjectileComponent>(uid);
|
var projectile = EnsureComp<ProjectileComponent>(uid);
|
||||||
Projectiles.SetShooter(uid, projectile, user ?? gunUid);
|
Projectiles.SetShooter(uid, projectile, user);
|
||||||
projectile.Weapon = gunUid;
|
projectile.Weapon = gunUid;
|
||||||
|
|
||||||
TransformSystem.SetWorldRotation(uid, direction.ToWorldAngle());
|
TransformSystem.SetWorldRotation(uid, direction.ToWorldAngle());
|
||||||
|
|||||||
@@ -0,0 +1,27 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared._White.Explosion;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
[Access(typeof(SharedExplosionSystem))]
|
||||||
|
public sealed partial class ExplosionEffectComponent : Component
|
||||||
|
{
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntProtoId Explosion = "ExplosionEffectGrenade";
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntProtoId ShockWave = "ExplosionEffectGrenadeShockWave";
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public List<EntProtoId> ShrapnelEffects = new() { "ExplosionEffectShrapnel1", "ExplosionEffectShrapnel2" };
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public int MinShrapnel = 5;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public int MaxShrapnel = 9;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float ShrapnelSpeed = 5;
|
||||||
|
}
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
namespace Content.Shared._White.Explosion;
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct ExplosiveTriggeredEvent;
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared._White.Explosion
|
||||||
|
{
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[AutoGenerateComponentState]
|
||||||
|
[Access(typeof(SharedExplosionSystem))]
|
||||||
|
public sealed partial class ExplosionShockWaveComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The rate at which the wave fades, lower values means it's active for longer.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float FalloffPower = 40f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How sharp the wave distortion is. Higher values make the wave more pronounced.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float Sharpness = 10.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Width of the wave.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float Width = 0.8f;
|
||||||
|
}
|
||||||
|
}
|
||||||
36
Content.Shared/_White/Explosion/SharedCMExplosionSystem.cs
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
using Content.Shared.Throwing;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Shared._White.Explosion;
|
||||||
|
|
||||||
|
public sealed class SharedExplosionSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
[Dependency] private readonly ThrowingSystem _throwing = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<ExplosionEffectComponent, ExplosiveTriggeredEvent>(OnExplosionEffectTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExplosionEffectTriggered(EntityUid uid, ExplosionEffectComponent component, ref ExplosiveTriggeredEvent args)
|
||||||
|
{
|
||||||
|
SpawnNextToOrDrop(component.ShockWave, uid);
|
||||||
|
SpawnNextToOrDrop(component.Explosion, uid);
|
||||||
|
|
||||||
|
if (component.MaxShrapnel <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
foreach (var effect in component.ShrapnelEffects)
|
||||||
|
{
|
||||||
|
var shrapnelCount = _random.Next(component.MinShrapnel, component.MaxShrapnel);
|
||||||
|
for (var i = 0; i < shrapnelCount; i++)
|
||||||
|
{
|
||||||
|
var angle = _random.NextAngle();
|
||||||
|
var direction = angle.ToVec().Normalized() * 10;
|
||||||
|
var shrapnel = SpawnNextToOrDrop(effect, uid);
|
||||||
|
_throwing.TryThrow(shrapnel, direction, component.ShrapnelSpeed / 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -29,6 +29,8 @@
|
|||||||
ignited: true
|
ignited: true
|
||||||
- type: IgniteOnCollide
|
- type: IgniteOnCollide
|
||||||
fireStacks: 0.35
|
fireStacks: 0.35
|
||||||
|
- type: ExplosionEffect # WD
|
||||||
|
maxShrapnel: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: ProjectileAnomalyFireball
|
id: ProjectileAnomalyFireball
|
||||||
|
|||||||
@@ -743,6 +743,8 @@
|
|||||||
totalIntensity: 150 # a ~2 tile radius
|
totalIntensity: 150 # a ~2 tile radius
|
||||||
intensitySlope: 5
|
intensitySlope: 5
|
||||||
maxIntensity: 10
|
maxIntensity: 10
|
||||||
|
- type: ExplosionEffect # WD
|
||||||
|
maxShrapnel: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BulletGrenadeFlash
|
id: BulletGrenadeFlash
|
||||||
@@ -781,6 +783,8 @@
|
|||||||
totalIntensity: 175 # about a ~6 tile radius
|
totalIntensity: 175 # about a ~6 tile radius
|
||||||
intensitySlope: 1
|
intensitySlope: 1
|
||||||
maxIntensity: 10
|
maxIntensity: 10
|
||||||
|
- type: ExplosionEffect # WD
|
||||||
|
maxShrapnel: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: BulletGrenadeEMP
|
id: BulletGrenadeEMP
|
||||||
|
|||||||
@@ -36,10 +36,18 @@
|
|||||||
Primed: { state: primed }
|
Primed: { state: primed }
|
||||||
Unprimed: { state: icon }
|
Unprimed: { state: icon }
|
||||||
|
|
||||||
|
- type: entity # WD
|
||||||
|
abstract: true
|
||||||
|
parent: GrenadeBase
|
||||||
|
id: GrenadeBaseExplosionEffect
|
||||||
|
components:
|
||||||
|
- type: ExplosionEffect
|
||||||
|
maxShrapnel: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: explosive grenade
|
name: explosive grenade
|
||||||
description: Grenade that creates a small but devastating explosion.
|
description: Grenade that creates a small but devastating explosion.
|
||||||
parent: GrenadeBase
|
parent: GrenadeBaseExplosionEffect # WD
|
||||||
id: ExGrenade
|
id: ExGrenade
|
||||||
components:
|
components:
|
||||||
- type: ExplodeOnTrigger
|
- type: ExplodeOnTrigger
|
||||||
@@ -49,13 +57,8 @@
|
|||||||
intensitySlope: 3
|
intensitySlope: 3
|
||||||
totalIntensity: 120 # about a ~4 tile radius
|
totalIntensity: 120 # about a ~4 tile radius
|
||||||
canCreateVacuum: false
|
canCreateVacuum: false
|
||||||
- type: OnUseTimerTrigger
|
- type: ExplosionEffect
|
||||||
beepSound:
|
maxShrapnel: 12
|
||||||
path: "/Audio/Effects/beep1.ogg"
|
|
||||||
params:
|
|
||||||
volume: 5
|
|
||||||
initialBeepDelay: 0
|
|
||||||
beepInterval: 2 # 2 beeps total (at 0 and 2)
|
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
name: flashbang
|
name: flashbang
|
||||||
@@ -102,7 +105,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
name: syndicate minibomb
|
name: syndicate minibomb
|
||||||
description: A syndicate-manufactured explosive used to stow destruction and cause chaos.
|
description: A syndicate-manufactured explosive used to stow destruction and cause chaos.
|
||||||
parent: GrenadeBase
|
parent: GrenadeBaseExplosionEffect # WD
|
||||||
id: SyndieMiniBomb
|
id: SyndieMiniBomb
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
@@ -235,7 +238,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
name: the nuclear option
|
name: the nuclear option
|
||||||
description: Please don't throw it, think of the children.
|
description: Please don't throw it, think of the children.
|
||||||
parent: GrenadeBase
|
parent: GrenadeBaseExplosionEffect # WD
|
||||||
id: NuclearGrenade
|
id: NuclearGrenade
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
@@ -326,7 +329,7 @@
|
|||||||
- type: entity
|
- type: entity
|
||||||
name: holy hand grenade
|
name: holy hand grenade
|
||||||
description: O Lord, bless this thy hand grenade, that with it thou mayst blow thine enemies to tiny bits, in thy mercy.
|
description: O Lord, bless this thy hand grenade, that with it thou mayst blow thine enemies to tiny bits, in thy mercy.
|
||||||
parent: GrenadeBase
|
parent: GrenadeBaseExplosionEffect # WD
|
||||||
id: HolyHandGrenade
|
id: HolyHandGrenade
|
||||||
components:
|
components:
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
|
|||||||
@@ -35,6 +35,8 @@
|
|||||||
explosionType: FireBomb # WD EDIT
|
explosionType: FireBomb # WD EDIT
|
||||||
totalIntensity: 120 # ~ 5 tile radius
|
totalIntensity: 120 # ~ 5 tile radius
|
||||||
canCreateVacuum: false
|
canCreateVacuum: false
|
||||||
|
- type: ExplosionEffect # WD
|
||||||
|
maxShrapnel: 0
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
id: WeldingFuelTankFull
|
id: WeldingFuelTankFull
|
||||||
|
|||||||
@@ -0,0 +1,92 @@
|
|||||||
|
- type: entity
|
||||||
|
id: ExplosionEffectGrenade
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Effects/grenade_explosion.rsi
|
||||||
|
state: grenade
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.5
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ExplosionEffectGrenadeShockWave
|
||||||
|
components:
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.5
|
||||||
|
- type: ExplosionShockWave
|
||||||
|
falloffPower: 30
|
||||||
|
sharpness: 15
|
||||||
|
width: 1.3
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: ExplosionEffectShrapnel1
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: CollisionWake
|
||||||
|
- type: Physics
|
||||||
|
bodyType: Dynamic
|
||||||
|
fixedRotation: true
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
fix1:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.25,-0.25,0.25,0.25"
|
||||||
|
density: 20
|
||||||
|
mask:
|
||||||
|
- ItemMask
|
||||||
|
restitution: 0.3
|
||||||
|
friction: 0
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Objects/Weapons/shrapnel.rsi
|
||||||
|
state: shrapnel_bright1
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.5
|
||||||
|
# - type: DeleteOnCollide
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
parent: ExplosionEffectShrapnel1
|
||||||
|
id: ExplosionEffectShrapnel2
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
state: shrapnel_bright2
|
||||||
|
|
||||||
|
# Не работает каким-то хуем
|
||||||
|
- type: entity
|
||||||
|
parent: BaseBullet
|
||||||
|
id: ProjectileShrapnel
|
||||||
|
name: shrapnel
|
||||||
|
noSpawn: true
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: White/Objects/Weapons/Ammunition/Projectiles/shotgun_projectiles.rsi
|
||||||
|
layers:
|
||||||
|
- state: buckshot
|
||||||
|
- type: Fixtures
|
||||||
|
fixtures:
|
||||||
|
projectile:
|
||||||
|
shape:
|
||||||
|
!type:PhysShapeAabb
|
||||||
|
bounds: "-0.1,-0.1,0.1,0.1"
|
||||||
|
hard: false
|
||||||
|
mask:
|
||||||
|
- Impassable
|
||||||
|
- BulletImpassable
|
||||||
|
- LowImpassable
|
||||||
|
fly-by:
|
||||||
|
shape: !type:PhysShapeCircle
|
||||||
|
radius: 1.5
|
||||||
|
layer:
|
||||||
|
- Impassable
|
||||||
|
- MidImpassable
|
||||||
|
- HighImpassable
|
||||||
|
- LowImpassable
|
||||||
|
hard: False
|
||||||
|
- type: Projectile
|
||||||
|
damage:
|
||||||
|
types:
|
||||||
|
Piercing: 12
|
||||||
|
deleteOnCollide: true
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.5
|
||||||
4
Resources/Prototypes/_White/Shaders/shaders.yml
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
- type: shader
|
||||||
|
id: ShockWave
|
||||||
|
kind: source
|
||||||
|
path: "/Textures/White/Shaders/shock_wave.swsl"
|
||||||
|
After Width: | Height: | Size: 7.7 KiB |
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/add6123ac6b3263f257e4b233ef5a8fea5d3d317/icons/effects/explosion.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 48,
|
||||||
|
"y": 48
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "grenade",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 298 B |
|
After Width: | Height: | Size: 259 B |
|
After Width: | Height: | Size: 212 B |
|
After Width: | Height: | Size: 298 B |
@@ -0,0 +1,23 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/a86a9e2e57e5c00195cab704713a4962e8bc973a/icons/obj/items/weapons/projectiles.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "autocannon"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "buckshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "beanbag"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "flechette"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,55 @@
|
|||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/a86a9e2e57e5c00195cab704713a4962e8bc973a/icons/obj/items/weapons/projectiles.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 32,
|
||||||
|
"y": 32
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "shrapnelshot"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnelshot_bit"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_glass"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_light"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_xeno"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_human"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_human1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_human2"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_bright1",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "shrapnel_bright2",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.1,
|
||||||
|
0.1,
|
||||||
|
0.1
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 465 B |
|
After Width: | Height: | Size: 548 B |
|
After Width: | Height: | Size: 206 B |
|
After Width: | Height: | Size: 257 B |
|
After Width: | Height: | Size: 484 B |
|
After Width: | Height: | Size: 336 B |
|
After Width: | Height: | Size: 204 B |
|
After Width: | Height: | Size: 269 B |
|
After Width: | Height: | Size: 330 B |
|
After Width: | Height: | Size: 245 B |
40
Resources/Textures/White/Shaders/shock_wave.swsl
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
uniform sampler2D SCREEN_TEXTURE;
|
||||||
|
uniform highp vec2 renderScale;
|
||||||
|
uniform lowp int count;
|
||||||
|
uniform highp vec2[10] position;
|
||||||
|
uniform highp float[10] sharpness;
|
||||||
|
uniform highp float[10] width;
|
||||||
|
uniform highp float[10] falloffPower;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
highp vec2 coord = FRAGCOORD.xy * SCREEN_PIXEL_SIZE.xy;
|
||||||
|
highp float ratio = SCREEN_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.x * 0.6;
|
||||||
|
|
||||||
|
for (int i = 0; i < count; ++i) {
|
||||||
|
highp vec2 WaveCentre = position[i];
|
||||||
|
|
||||||
|
highp float Dist = distance(
|
||||||
|
vec2(coord.x, coord.y * ratio),
|
||||||
|
vec2(WaveCentre.x, WaveCentre.y * ratio)
|
||||||
|
);
|
||||||
|
|
||||||
|
// removes the first few frames of the "animation"
|
||||||
|
Dist = max(Dist, 0.13);
|
||||||
|
|
||||||
|
highp float offset = (TIME - floor(TIME)) / TIME;
|
||||||
|
highp float CurrentTime = TIME * offset;
|
||||||
|
|
||||||
|
if (Dist <= (CurrentTime + 0.1) && Dist >= (CurrentTime - 0.1)) {
|
||||||
|
highp float Diff = Dist - CurrentTime;
|
||||||
|
highp float ScaleDiff = 1.0 - pow(abs(Diff * sharpness[i]), width[i]);
|
||||||
|
highp float DiffTime = Diff * ScaleDiff;
|
||||||
|
highp vec2 DiffTexCoord = normalize(coord - WaveCentre);
|
||||||
|
coord += (DiffTexCoord * DiffTime) / (CurrentTime * Dist * falloffPower[i]);
|
||||||
|
highp vec4 Color = zTextureSpec(SCREEN_TEXTURE, coord);
|
||||||
|
Color += (Color * ScaleDiff) / (CurrentTime * Dist * 40.0);
|
||||||
|
COLOR = Color;
|
||||||
|
} else {
|
||||||
|
COLOR = zTextureSpec(SCREEN_TEXTURE, UV);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||