Новые эффекты взрывов (#1410)
Co-authored-by: Vero <73014819+vero5123@users.noreply.github.com> Co-authored-by: Whisper <121047731+QuietlyWhisper@users.noreply.github.com> Co-authored-by: DrSmugleaf <10968691+DrSmugleaf@users.noreply.github.com>
This commit is contained in:
parent
26f5302d6a
commit
6c8050eb1e
40 changed files with 910 additions and 9 deletions
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Content.Client._RMC14.Explosion;
|
||||||
|
using Content.Client._RMC14.Xenonids.Screech;
|
||||||
using Content.Client._Sunrise.Entry;
|
using Content.Client._Sunrise.Entry;
|
||||||
using Content.Client._Sunrise.ServersHub;
|
using Content.Client._Sunrise.ServersHub;
|
||||||
using Content.Client.Administration.Managers;
|
using Content.Client.Administration.Managers;
|
||||||
|
|
@ -174,6 +176,10 @@ namespace Content.Client.Entry
|
||||||
_parallaxManager.LoadDefaultParallax();
|
_parallaxManager.LoadDefaultParallax();
|
||||||
|
|
||||||
_overlayManager.AddOverlay(new SingularityOverlay());
|
_overlayManager.AddOverlay(new SingularityOverlay());
|
||||||
|
// Sunrise edit start
|
||||||
|
_overlayManager.AddOverlay(new RMCExplosionShockWaveOverlay());
|
||||||
|
_overlayManager.AddOverlay(new RMCXenoScreechShockWaveOverlay());
|
||||||
|
// Sunrise edit end
|
||||||
_overlayManager.AddOverlay(new RadiationPulseOverlay());
|
_overlayManager.AddOverlay(new RadiationPulseOverlay());
|
||||||
_chatManager.Initialize();
|
_chatManager.Initialize();
|
||||||
_clientPreferencesManager.Initialize();
|
_clientPreferencesManager.Initialize();
|
||||||
|
|
|
||||||
101
Content.Client/_RMC14/Explosion/RMCExplosionShockWaveOverlay.cs
Normal file
101
Content.Client/_RMC14/Explosion/RMCExplosionShockWaveOverlay.cs
Normal file
|
|
@ -0,0 +1,101 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Shared._RMC14.Explosion.Components;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Client._RMC14.Explosion;
|
||||||
|
|
||||||
|
public sealed class RMCExplosionShockWaveOverlay : Overlay, IEntityEventSubscriber
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IEntityManager _entMan = default!;
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = 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 = 10;
|
||||||
|
|
||||||
|
public RMCExplosionShockWaveOverlay()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_shader = _prototypeManager.Index<ShaderPrototype>("RMCShockWave").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 readonly float[] _times = new float[MaxCount];
|
||||||
|
private int _count;
|
||||||
|
|
||||||
|
private readonly TimeSpan _timeCompensation = TimeSpan.FromSeconds(0.2f);
|
||||||
|
|
||||||
|
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<RMCExplosionShockWaveComponent, 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;
|
||||||
|
|
||||||
|
var currentTime = (float)(_timing.CurTime - distortion.CreationTime - _timeCompensation).TotalSeconds;
|
||||||
|
currentTime = Math.Clamp(currentTime, 0.1f, float.MaxValue);
|
||||||
|
|
||||||
|
_positions[_count] = tempCoords;
|
||||||
|
_falloffPower[_count] = distortion.FalloffPower ?? 20f; // Sunrise edit - фолбек
|
||||||
|
_sharpness[_count] = distortion.Sharpness;
|
||||||
|
_width[_count] = distortion.Width ?? 0.8f;
|
||||||
|
_times[_count] = currentTime;
|
||||||
|
_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("time", _times);
|
||||||
|
_shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||||
|
|
||||||
|
var worldHandle = args.WorldHandle;
|
||||||
|
worldHandle.UseShader(_shader);
|
||||||
|
worldHandle.DrawRect(args.WorldBounds, Color.White);
|
||||||
|
worldHandle.UseShader(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,77 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Shared._RMC14.Xenonids.Screech;
|
||||||
|
using Robust.Client.Graphics;
|
||||||
|
using Robust.Shared.Enums;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Client._RMC14.Xenonids.Screech;
|
||||||
|
|
||||||
|
public sealed class RMCXenoScreechShockWaveOverlay : 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;
|
||||||
|
|
||||||
|
public RMCXenoScreechShockWaveOverlay()
|
||||||
|
{
|
||||||
|
IoCManager.InjectDependencies(this);
|
||||||
|
_shader = _prototypeManager.Index<ShaderPrototype>("RMCXenoScreechShockWave").Instance().Duplicate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private Vector2 _position;
|
||||||
|
private float _waveStrength;
|
||||||
|
private float _waveSpeed;
|
||||||
|
private float _downScale;
|
||||||
|
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<RMCXenoScreechShockWaveComponent, TransformComponent>();
|
||||||
|
|
||||||
|
if (query.MoveNext(out var uid, out var distortion, out var xform))
|
||||||
|
{
|
||||||
|
if (xform.MapID != args.MapId)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
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;
|
||||||
|
|
||||||
|
_position = tempCoords;
|
||||||
|
_waveStrength = distortion.WaveStrength;
|
||||||
|
_waveSpeed = distortion.WaveSpeed;
|
||||||
|
_downScale = distortion.DownScale;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void Draw(in OverlayDrawArgs args)
|
||||||
|
{
|
||||||
|
if (ScreenTexture == null || args.Viewport.Eye == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_shader?.SetParameter("position", _position);
|
||||||
|
_shader?.SetParameter("waveSpeed", _waveSpeed);
|
||||||
|
_shader?.SetParameter("downScale", _downScale);
|
||||||
|
_shader?.SetParameter("waveStrength", _waveStrength);
|
||||||
|
_shader?.SetParameter("SCREEN_TEXTURE", ScreenTexture);
|
||||||
|
|
||||||
|
var worldHandle = args.WorldHandle;
|
||||||
|
worldHandle.UseShader(_shader);
|
||||||
|
worldHandle.DrawRect(args.WorldBounds, Color.White);
|
||||||
|
worldHandle.UseShader(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
using Content.Shared._RMC14.Explosion.Components;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Client._RMC14._Sunrise.Explosion;
|
||||||
|
|
||||||
|
public sealed class ClientExplosionShockWaveSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<RMCExplosionShockWaveComponent, ComponentInit>(OnInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(Entity<RMCExplosionShockWaveComponent> ent, ref ComponentInit args)
|
||||||
|
{
|
||||||
|
ent.Comp.CreationTime = _timing.CurTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Content.Shared._RMC14.Explosion;
|
||||||
|
using Robust.Client.Animations;
|
||||||
|
using Robust.Client.GameObjects;
|
||||||
|
using Robust.Shared.Animations;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Client._RMC14._Sunrise.Explosion;
|
||||||
|
|
||||||
|
// Омг это же партикл систем за 1$
|
||||||
|
public sealed class RMCExplosionSystem : SharedRMCExplosionSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||||
|
[Dependency] private readonly AnimationPlayerSystem _player = default!;
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
private const string SmokeTrack = "smoke-animation";
|
||||||
|
private const string ExplosionTrack = "explosion-animation";
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ExplosionSmokeEffectComponent, ComponentStartup>(OnSmokeStartup);
|
||||||
|
SubscribeLocalEvent<ExplosionEffectComponent, ComponentStartup>(OnExplosionStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSmokeStartup(Entity<ExplosionSmokeEffectComponent> ent, ref ComponentStartup args)
|
||||||
|
{
|
||||||
|
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var targetX = 2f + _random.NextFloat(-ExplosionSmokeEffectComponent.Variation, ExplosionSmokeEffectComponent.Variation);
|
||||||
|
var targetY = 2f + _random.NextFloat(-ExplosionSmokeEffectComponent.Variation, ExplosionSmokeEffectComponent.Variation);
|
||||||
|
|
||||||
|
var animation = new Animation()
|
||||||
|
{
|
||||||
|
Length = TimeSpan.FromSeconds(ent.Comp.LifeTime),
|
||||||
|
AnimationTracks =
|
||||||
|
{
|
||||||
|
new AnimationTrackComponentProperty()
|
||||||
|
{
|
||||||
|
Property = nameof(SpriteComponent.Offset),
|
||||||
|
ComponentType = typeof(SpriteComponent),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(sprite.Offset, 0f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(new Vector2(targetX, targetY), ent.Comp.LifeTime),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new AnimationTrackComponentProperty()
|
||||||
|
{
|
||||||
|
Property = nameof(SpriteComponent.Color),
|
||||||
|
ComponentType = typeof(SpriteComponent),
|
||||||
|
InterpolationMode = AnimationInterpolationMode.Linear,
|
||||||
|
KeyFrames =
|
||||||
|
{
|
||||||
|
new AnimationTrackProperty.KeyFrame(sprite.Color, 0f),
|
||||||
|
new AnimationTrackProperty.KeyFrame(GetTransparentColor(sprite.Color), ent.Comp.LifeTime),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
_player.Play(ent, animation, SmokeTrack);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExplosionStartup(Entity<ExplosionEffectComponent> ent, ref ComponentStartup args)
|
||||||
|
{
|
||||||
|
if (!TryComp<SpriteComponent>(ent, out var sprite))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sprite.Scale = new Vector2(ent.Comp.SizeModifier);
|
||||||
|
_sprite.SetAutoAnimateSync(sprite, ent.Comp.LifeTime);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Color GetTransparentColor(Color color)
|
||||||
|
{
|
||||||
|
return new Color(color.R, color.G, color.B, 0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -20,6 +20,8 @@ using Content.Shared.Stealth.Components;
|
||||||
using Content.Shared.Damage.Components;
|
using Content.Shared.Damage.Components;
|
||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
using Content.Shared._Sunrise.CollectiveMind;
|
using Content.Shared._Sunrise.CollectiveMind;
|
||||||
|
using Content.Shared._RMC14.Xenonids.Screech;
|
||||||
|
using Content.Shared.Coordinates;
|
||||||
|
|
||||||
namespace Content.Server.Changeling;
|
namespace Content.Server.Changeling;
|
||||||
|
|
||||||
|
|
@ -263,6 +265,10 @@ public sealed partial class ChangelingSystem : EntitySystem
|
||||||
|
|
||||||
_popup.PopupEntity(Loc.GetString("changeling-stasis-exit"), uid, uid);
|
_popup.PopupEntity(Loc.GetString("changeling-stasis-exit"), uid, uid);
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
StartScreech(uid);
|
||||||
|
// Sunrise edit end
|
||||||
|
|
||||||
comp.IsInStasis = false;
|
comp.IsInStasis = false;
|
||||||
|
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
|
|
@ -637,4 +643,17 @@ public sealed partial class ChangelingSystem : EntitySystem
|
||||||
}
|
}
|
||||||
|
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
private void StartScreech(EntityUid uid, XenoScreechComponent? component = null, bool playSound = true)
|
||||||
|
{
|
||||||
|
if (!Resolve(uid, ref component))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (playSound)
|
||||||
|
_audio.PlayPvs(component.Sound, uid);
|
||||||
|
|
||||||
|
SpawnAttachedTo(component.Effect, uid.ToCoordinates());
|
||||||
|
}
|
||||||
|
// Sunrise edit end
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ using Content.Shared.Mobs.Components;
|
||||||
using Content.Server.Stunnable;
|
using Content.Server.Stunnable;
|
||||||
using Content.Shared.Jittering;
|
using Content.Shared.Jittering;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared._RMC14.Xenonids.Screech;
|
||||||
using Content.Shared.Forensics.Components;
|
using Content.Shared.Forensics.Components;
|
||||||
using Content.Shared.Radio;
|
using Content.Shared.Radio;
|
||||||
|
|
||||||
|
|
@ -266,6 +267,10 @@ public sealed partial class ChangelingSystem : EntitySystem
|
||||||
{
|
{
|
||||||
_audio.PlayPvs(comp.ShriekSound, uid);
|
_audio.PlayPvs(comp.ShriekSound, uid);
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
StartScreech(uid, playSound: false);
|
||||||
|
// Sunrise edit end
|
||||||
|
|
||||||
var center = Transform(uid).MapPosition;
|
var center = Transform(uid).MapPosition;
|
||||||
var gamers = Filter.Empty();
|
var gamers = Filter.Empty();
|
||||||
gamers.AddInRange(center, comp.ShriekPower, _player, EntityManager);
|
gamers.AddInRange(center, comp.ShriekPower, _player, EntityManager);
|
||||||
|
|
@ -607,6 +612,10 @@ public sealed partial class ChangelingSystem : EntitySystem
|
||||||
RemComp<ThirstComponent>(uid);
|
RemComp<ThirstComponent>(uid);
|
||||||
EnsureComp<ZombieImmuneComponent>(uid);
|
EnsureComp<ZombieImmuneComponent>(uid);
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
EnsureComp<XenoScreechComponent>(uid);
|
||||||
|
// Sunrise edit end
|
||||||
|
|
||||||
// add actions
|
// add actions
|
||||||
foreach (var actionId in comp.BaseChangelingActions)
|
foreach (var actionId in comp.BaseChangelingActions)
|
||||||
_actions.AddAction(uid, actionId);
|
_actions.AddAction(uid, actionId);
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Content.Shared.Explosion;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
using System.Text.Json.Serialization;
|
using System.Text.Json.Serialization;
|
||||||
|
using Content.Shared._Sunrise.Explosion;
|
||||||
|
|
||||||
namespace Content.Server.EntityEffects.Effects;
|
namespace Content.Server.EntityEffects.Effects;
|
||||||
|
|
||||||
|
|
@ -68,6 +69,11 @@ public sealed partial class ExplosionReactionEffect : EntityEffect
|
||||||
intensity = MathF.Min((float) reagentArgs.Quantity * IntensityPerUnit, MaxTotalIntensity);
|
intensity = MathF.Min((float) reagentArgs.Quantity * IntensityPerUnit, MaxTotalIntensity);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
args.EntityManager.System<SharedSunriseExplosionSystem>()
|
||||||
|
.TryAddExplosionEffect(args.TargetEntity, ExplosionType);
|
||||||
|
// Sunrise edit end
|
||||||
|
|
||||||
args.EntityManager.System<ExplosionSystem>()
|
args.EntityManager.System<ExplosionSystem>()
|
||||||
.QueueExplosion(
|
.QueueExplosion(
|
||||||
args.TargetEntity,
|
args.TargetEntity,
|
||||||
|
|
|
||||||
|
|
@ -37,9 +37,15 @@ public sealed partial class ExplosionSystem
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructor for the shared <see cref="ExplosionEvent"/> using the server-exclusive explosion classes.
|
/// Constructor for the shared <see cref="ExplosionEvent"/> using the server-exclusive explosion classes.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private EntityUid CreateExplosionVisualEntity(MapCoordinates epicenter, string prototype, Matrix3x2 spaceMatrix, ExplosionSpaceTileFlood? spaceData, IEnumerable<ExplosionGridTileFlood> gridData, List<float> iterationIntensity)
|
private EntityUid CreateExplosionVisualEntity(MapCoordinates epicenter, ExplosionPrototype prototype, Matrix3x2 spaceMatrix, ExplosionSpaceTileFlood? spaceData, IEnumerable<ExplosionGridTileFlood> gridData, List<float> iterationIntensity)
|
||||||
{
|
{
|
||||||
var explosionEntity = Spawn(null, MapCoordinates.Nullspace);
|
var explosionEntity = Spawn(null, MapCoordinates.Nullspace);
|
||||||
|
|
||||||
|
// Sunrise added start
|
||||||
|
if (prototype.EffectType != ExplosionEffectType.Standard)
|
||||||
|
return explosionEntity;
|
||||||
|
// Sunrise added end
|
||||||
|
|
||||||
var comp = AddComp<ExplosionVisualsComponent>(explosionEntity);
|
var comp = AddComp<ExplosionVisualsComponent>(explosionEntity);
|
||||||
|
|
||||||
foreach (var grid in gridData)
|
foreach (var grid in gridData)
|
||||||
|
|
@ -49,7 +55,7 @@ public sealed partial class ExplosionSystem
|
||||||
|
|
||||||
comp.SpaceTiles = spaceData?.TileLists;
|
comp.SpaceTiles = spaceData?.TileLists;
|
||||||
comp.Epicenter = epicenter;
|
comp.Epicenter = epicenter;
|
||||||
comp.ExplosionType = prototype;
|
comp.ExplosionType = prototype.ID; // Sunrise edit
|
||||||
comp.Intensity = iterationIntensity;
|
comp.Intensity = iterationIntensity;
|
||||||
comp.SpaceMatrix = spaceMatrix;
|
comp.SpaceMatrix = spaceMatrix;
|
||||||
comp.SpaceTileSize = spaceData?.TileSize ?? DefaultTileSize;
|
comp.SpaceTileSize = spaceData?.TileSize ?? DefaultTileSize;
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ using Content.Server.Atmos.Components;
|
||||||
using Content.Server.Chat.Managers;
|
using Content.Server.Chat.Managers;
|
||||||
using Content.Server.NodeContainer.EntitySystems;
|
using Content.Server.NodeContainer.EntitySystems;
|
||||||
using Content.Server.NPC.Pathfinding;
|
using Content.Server.NPC.Pathfinding;
|
||||||
|
using Content.Shared._RMC14.Explosion;
|
||||||
using Content.Shared.Camera;
|
using Content.Shared.Camera;
|
||||||
using Content.Shared.CCVar;
|
using Content.Shared.CCVar;
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
|
|
@ -319,6 +320,14 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
|
||||||
};
|
};
|
||||||
_explosionQueue.Enqueue(boom);
|
_explosionQueue.Enqueue(boom);
|
||||||
_queuedExplosions.Add(boom);
|
_queuedExplosions.Add(boom);
|
||||||
|
|
||||||
|
// Sunrise added start
|
||||||
|
if (!cause.HasValue)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var ev = new CMExplosiveTriggeredEvent();
|
||||||
|
RaiseLocalEvent(cause.Value, ref ev);
|
||||||
|
// Sunrise added end
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
@ -339,7 +348,8 @@ public sealed partial class ExplosionSystem : SharedExplosionSystem
|
||||||
|
|
||||||
var (area, iterationIntensity, spaceData, gridData, spaceMatrix) = results.Value;
|
var (area, iterationIntensity, spaceData, gridData, spaceMatrix) = results.Value;
|
||||||
|
|
||||||
var visualEnt = CreateExplosionVisualEntity(pos, queued.Proto.ID, spaceMatrix, spaceData, gridData.Values, iterationIntensity);
|
// Sunrise edit - queued.Proto.ID -> queued.Proto
|
||||||
|
var visualEnt = CreateExplosionVisualEntity(pos, queued.Proto, spaceMatrix, spaceData, gridData.Values, iterationIntensity);
|
||||||
|
|
||||||
// camera shake
|
// camera shake
|
||||||
CameraShake(iterationIntensity.Count * 4f, pos, queued.TotalIntensity);
|
CameraShake(iterationIntensity.Count * 4f, pos, queued.TotalIntensity);
|
||||||
|
|
|
||||||
8
Content.Server/_Sunrise/Explosions/RMCExplosionSystem.cs
Normal file
8
Content.Server/_Sunrise/Explosions/RMCExplosionSystem.cs
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
using Content.Shared._RMC14.Explosion;
|
||||||
|
|
||||||
|
namespace Content.Server._Sunrise.Explosions;
|
||||||
|
|
||||||
|
public sealed class RMCExplosionSystem : SharedRMCExplosionSystem
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
using Content.Shared.Damage;
|
using Content.Shared.Damage;
|
||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Serialization;
|
||||||
using Robust.Shared.Utility;
|
using Robust.Shared.Utility;
|
||||||
|
|
||||||
namespace Content.Shared.Explosion;
|
namespace Content.Shared.Explosion;
|
||||||
|
|
@ -110,6 +111,11 @@ public sealed partial class ExplosionPrototype : IPrototype
|
||||||
[DataField("fireStates")]
|
[DataField("fireStates")]
|
||||||
public int FireStates = 3;
|
public int FireStates = 3;
|
||||||
|
|
||||||
|
// Sunrise added start
|
||||||
|
[DataField]
|
||||||
|
public ExplosionEffectType EffectType = ExplosionEffectType.Fancy;
|
||||||
|
// Sunrise added end
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Basic function for linear interpolation of the _tileBreakChance and _tileBreakIntensity arrays
|
/// Basic function for linear interpolation of the _tileBreakChance and _tileBreakIntensity arrays
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
@ -133,3 +139,11 @@ public sealed partial class ExplosionPrototype : IPrototype
|
||||||
return _tileBreakChance[i - 1] + slope * (intensity - _tileBreakIntensity[i - 1]);
|
return _tileBreakChance[i - 1] + slope * (intensity - _tileBreakIntensity[i - 1]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Serializable, NetSerializable]
|
||||||
|
public enum ExplosionEffectType : byte
|
||||||
|
{
|
||||||
|
Standard,
|
||||||
|
Fancy,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,9 +193,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;
|
||||||
|
|
|
||||||
|
|
@ -484,7 +484,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;
|
||||||
|
|
||||||
// Sunrise-Start
|
// Sunrise-Start
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared._RMC14.Explosion;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[Access(typeof(SharedRMCExplosionSystem))]
|
||||||
|
public sealed partial class CMExplosionEffectComponent : Component
|
||||||
|
{
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId? Explosion = "CMExplosionEffectGrenade";
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId? ShockWave = "RMCExplosionEffectGrenadeShockWave";
|
||||||
|
|
||||||
|
// Sunrise added
|
||||||
|
[DataField]
|
||||||
|
public EntProtoId? Smoke = "ExplosionEffectSmoke";
|
||||||
|
// Sunrise added
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sunrise added start
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ExplosionSmokeEffectComponent : Component
|
||||||
|
{
|
||||||
|
public const float AnimationDuration = 2.5f;
|
||||||
|
public const float Variation = 1f;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float LifeTime = AnimationDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class ExplosionEffectComponent : Component
|
||||||
|
{
|
||||||
|
public const float AnimationDuration = 2.5f;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float LifeTime = AnimationDuration;
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public float SizeModifier = 2f;
|
||||||
|
}
|
||||||
|
// Sunrise added end
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared._RMC14.Explosion.Components
|
||||||
|
{
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[AutoGenerateComponentState]
|
||||||
|
public sealed partial class RMCExplosionShockWaveComponent : 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 = 20f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How sharp the wave distortion is. Higher values make the wave more pronounced.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float Sharpness = 5.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Width of the wave.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float? Width = 0.8f;
|
||||||
|
|
||||||
|
[DataField]
|
||||||
|
public TimeSpan CreationTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
122
Content.Shared/_RMC14/Explosion/SharedRMCExplosionSystem.cs
Normal file
122
Content.Shared/_RMC14/Explosion/SharedRMCExplosionSystem.cs
Normal file
|
|
@ -0,0 +1,122 @@
|
||||||
|
using Content.Shared._RMC14.Explosion.Components;
|
||||||
|
using Content.Shared._Sunrise.Helpers;
|
||||||
|
using Content.Shared.Explosion.Components;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Spawners;
|
||||||
|
|
||||||
|
namespace Content.Shared._RMC14.Explosion;
|
||||||
|
|
||||||
|
public abstract class SharedRMCExplosionSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
private const float MinSmokeCountPer100 = 12f;
|
||||||
|
private const float MaxSmokeCountPer100 = 17f;
|
||||||
|
|
||||||
|
private const float SmokeSpawnRadiusPer100 = 2f;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
SubscribeLocalEvent<CMExplosionEffectComponent, CMExplosiveTriggeredEvent>(OnExplosionEffectTriggered);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExplosionEffectTriggered(Entity<CMExplosionEffectComponent> ent, ref CMExplosiveTriggeredEvent args)
|
||||||
|
{
|
||||||
|
DoEffect(ent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sunrise edit start
|
||||||
|
public void DoEffect(Entity<CMExplosionEffectComponent> ent)
|
||||||
|
{
|
||||||
|
if (!TryComp<ExplosiveComponent>(ent, out var explosionComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ent.Comp.ShockWave is { } shockwave)
|
||||||
|
{
|
||||||
|
var wave = SpawnNextToOrDrop(shockwave, ent);
|
||||||
|
ModifyShockwave(wave, explosionComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent.Comp.Explosion is { } explosion)
|
||||||
|
{
|
||||||
|
var explosionEntity = SpawnNextToOrDrop(explosion, ent);
|
||||||
|
CreateFancyExplosionEffect(explosionEntity, explosionComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ent.Comp.Smoke is { } smoke)
|
||||||
|
CreateFancySmoke(ent, explosionComponent, smoke);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ModifyShockwave(EntityUid wave, ExplosiveComponent explosionComponent)
|
||||||
|
{
|
||||||
|
// Дальше идут просто числа, которые я придумал особо не думая, мб нужно подумать
|
||||||
|
// Но идея в том, чтобы чем сильнее взрыв, тем сильнее эффект и наоборот
|
||||||
|
// TODO: Реализовать радиус действия волны и убрать стандартные значения в компоненте
|
||||||
|
|
||||||
|
if (TryComp<RMCExplosionShockWaveComponent>(wave, out var waveComponent))
|
||||||
|
{
|
||||||
|
waveComponent.FalloffPower ??= explosionComponent.TotalIntensity / 4f;
|
||||||
|
waveComponent.Width ??= Math.Clamp(explosionComponent.TotalIntensity / 200f, 0.1f, 0.5f);
|
||||||
|
|
||||||
|
Dirty(wave, waveComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TryComp<TimedDespawnComponent>(wave, out var timedDespawnComponent))
|
||||||
|
timedDespawnComponent.Lifetime = Math.Clamp(explosionComponent.TotalIntensity / 50f, 0.1f, 0.8f);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateFancyExplosionEffect(EntityUid explosionEntity, ExplosiveComponent explosionComponent)
|
||||||
|
{
|
||||||
|
if (!TryComp<TimedDespawnComponent>(explosionEntity, out var timedDespawnComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (!TryComp<ExplosionEffectComponent>(explosionEntity, out var explosionEffectComponent))
|
||||||
|
return;
|
||||||
|
|
||||||
|
var sizeModifier = Math.Clamp(explosionComponent.TotalIntensity / 50f, 1f, 12f);
|
||||||
|
explosionEffectComponent.SizeModifier = sizeModifier;
|
||||||
|
explosionEffectComponent.LifeTime = timedDespawnComponent.Lifetime;
|
||||||
|
|
||||||
|
Dirty(explosionEntity, explosionEffectComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void CreateFancySmoke(Entity<CMExplosionEffectComponent> ent, ExplosiveComponent explosionComponent, EntProtoId smokeId)
|
||||||
|
{
|
||||||
|
var modifier = explosionComponent.TotalIntensity / 100f;
|
||||||
|
|
||||||
|
var smokeCount = _random.NextFloat(MinSmokeCountPer100 * modifier, MaxSmokeCountPer100 * modifier);
|
||||||
|
var coords = Transform(ent).Coordinates;
|
||||||
|
var modifiedRadius = Math.Clamp(SmokeSpawnRadiusPer100 * modifier, 2f, 10f);
|
||||||
|
|
||||||
|
for (var i = 0; i < smokeCount; i++)
|
||||||
|
{
|
||||||
|
var smoke = Spawn(smokeId, coords.GetRandomInRadius(modifiedRadius));
|
||||||
|
|
||||||
|
if (!TryComp<TimedDespawnComponent>(smoke, out var timedDespawnComponent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!TryComp<ExplosionSmokeEffectComponent>(smoke, out var explosionSmokeEffectComponent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
timedDespawnComponent.Lifetime = ExplosionSmokeEffectComponent.AnimationDuration + _random.NextFloat(-ExplosionSmokeEffectComponent.Variation, ExplosionSmokeEffectComponent.Variation);
|
||||||
|
|
||||||
|
// Это нужно, чтобы анимация на клиенте знала, когда мы решили заканчиваться
|
||||||
|
explosionSmokeEffectComponent.LifeTime = timedDespawnComponent.Lifetime;
|
||||||
|
Dirty(smoke, explosionSmokeEffectComponent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Sunrise edit end
|
||||||
|
|
||||||
|
public void TryDoEffect(Entity<CMExplosionEffectComponent?> ent)
|
||||||
|
{
|
||||||
|
if (!Resolve(ent, ref ent.Comp, false))
|
||||||
|
return;
|
||||||
|
|
||||||
|
DoEffect((ent, ent.Comp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public readonly record struct CMExplosiveTriggeredEvent;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
|
||||||
|
namespace Content.Shared._RMC14.Xenonids.Screech;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[AutoGenerateComponentState]
|
||||||
|
public sealed partial class RMCXenoScreechShockWaveComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The speed of each individual wave from the center axis.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float WaveSpeed = 15.3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The size of each wave in its width and distortion effect
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float WaveStrength = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scale of the effect, lower number means a larger total area while smaller numbers downscale it and reduce the effected area.
|
||||||
|
/// </summary>
|
||||||
|
[DataField, AutoNetworkedField, ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float DownScale = 1f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
using Robust.Shared.Audio;
|
||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared._RMC14.Xenonids.Screech;
|
||||||
|
|
||||||
|
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
|
||||||
|
public sealed partial class XenoScreechComponent : Component
|
||||||
|
{
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public EntProtoId Effect = "CMEffectScreechShort";
|
||||||
|
|
||||||
|
[DataField, AutoNetworkedField]
|
||||||
|
public SoundSpecifier Sound = new SoundPathSpecifier("/Audio/_RMC14/Xeno/alien_queen_screech.ogg", AudioParams.Default.WithVolume(-7).WithPlayOffset(1.4f));
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
using Content.Shared._RMC14.Explosion;
|
||||||
|
using Content.Shared.Explosion;
|
||||||
|
using Content.Shared.Explosion.Components;
|
||||||
|
using Robust.Shared.Prototypes;
|
||||||
|
|
||||||
|
namespace Content.Shared._Sunrise.Explosion;
|
||||||
|
|
||||||
|
public sealed class SharedSunriseExplosionSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
|
||||||
|
SubscribeLocalEvent<ExplosiveComponent, ComponentInit>(OnInit);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInit(Entity<ExplosiveComponent> ent, ref ComponentInit args)
|
||||||
|
{
|
||||||
|
TryAddExplosionEffect(ent, ent.Comp.ExplosionType);
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool TryAddExplosionEffect(EntityUid uid, string explosionType)
|
||||||
|
{
|
||||||
|
if (!_prototype.TryIndex<ExplosionPrototype>(explosionType, out var explosionPrototype))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (explosionPrototype.EffectType != ExplosionEffectType.Fancy)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
EnsureComp<CMExplosionEffectComponent>(uid);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
39
Content.Shared/_Sunrise/Helpers/CoordinatesHelpers.cs
Normal file
39
Content.Shared/_Sunrise/Helpers/CoordinatesHelpers.cs
Normal file
|
|
@ -0,0 +1,39 @@
|
||||||
|
using System.Numerics;
|
||||||
|
using Robust.Shared.Map;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Shared._Sunrise.Helpers;
|
||||||
|
|
||||||
|
public static class EntityCoordinatesExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Генерирует случайные координаты в заданном радиусе от исходных координат.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="origin">Исходные координаты.</param>
|
||||||
|
/// <param name="radius">Радиус для генерации случайной точки.</param>
|
||||||
|
/// <param name="rand">Опциональный экземпляр Random для контроля генерации.</param>
|
||||||
|
/// <returns>Новые координаты в пределах радиуса.</returns>
|
||||||
|
public static EntityCoordinates GetRandomInRadius(this EntityCoordinates origin, float radius, IRobustRandom? rand = null)
|
||||||
|
{
|
||||||
|
if (radius < 0)
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(radius), "Radius cannot be negative.");
|
||||||
|
|
||||||
|
if (radius == 0)
|
||||||
|
return origin;
|
||||||
|
|
||||||
|
rand ??= IoCManager.Resolve<IRobustRandom>();
|
||||||
|
|
||||||
|
// Генерируем угол и расстояние.
|
||||||
|
var angle = rand.NextDouble() * Math.Tau; // 0..2π
|
||||||
|
var distance = Math.Sqrt(rand.NextDouble()) * radius; // Равномерное распределение
|
||||||
|
|
||||||
|
// Преобразуем в декартовы координаты.
|
||||||
|
var x = (float)(distance * Math.Cos(angle));
|
||||||
|
var y = (float)(distance * Math.Sin(angle));
|
||||||
|
|
||||||
|
// Смещаем относительно исходной позиции.
|
||||||
|
var newPosition = origin.Position + new Vector2(x, y);
|
||||||
|
|
||||||
|
return new EntityCoordinates(origin.EntityId, newPosition);
|
||||||
|
}
|
||||||
|
}
|
||||||
BIN
Resources/Audio/_RMC14/Xeno/alien_queen_screech.ogg
Normal file
BIN
Resources/Audio/_RMC14/Xeno/alien_queen_screech.ogg
Normal file
Binary file not shown.
|
|
@ -92,7 +92,7 @@
|
||||||
enabled: false
|
enabled: false
|
||||||
- type: NukeLabel
|
- type: NukeLabel
|
||||||
- type: Nuke
|
- type: Nuke
|
||||||
explosionType: Default
|
explosionType: DefaultStandardEffect # Sunrise edit
|
||||||
maxIntensity: 100
|
maxIntensity: 100
|
||||||
intensitySlope: 5
|
intensitySlope: 5
|
||||||
totalIntensity: 5000000
|
totalIntensity: 5000000
|
||||||
|
|
|
||||||
16
Resources/Prototypes/_RMC14/Effects/explosive.yml
Normal file
16
Resources/Prototypes/_RMC14/Effects/explosive.yml
Normal file
|
|
@ -0,0 +1,16 @@
|
||||||
|
- type: entity
|
||||||
|
id: CMExplosionEffectGrenade
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
sprite: _RMC14/Effects/grenade_explosion.rsi
|
||||||
|
state: grenade
|
||||||
|
- type: ExplosionEffect # Sunrise
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.6
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
id: RMCExplosionEffectGrenadeShockWave
|
||||||
|
components:
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 0.5
|
||||||
|
- type: RMCExplosionShockWave
|
||||||
35
Resources/Prototypes/_RMC14/Effects/screech.yml
Normal file
35
Resources/Prototypes/_RMC14/Effects/screech.yml
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
- type: entity
|
||||||
|
# Just fades out with no movement animation
|
||||||
|
id: CMEffectScreech
|
||||||
|
categories: [ HideSpawnMenu ]
|
||||||
|
components:
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 3.2
|
||||||
|
- type: RMCXenoScreechShockWave
|
||||||
|
- type: Sprite
|
||||||
|
sprite: _RMC14/Effects/xeno_screech.rsi
|
||||||
|
noRot: true
|
||||||
|
state: screech
|
||||||
|
drawdepth: Effects
|
||||||
|
- type: EffectVisuals
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HideContextMenu
|
||||||
|
|
||||||
|
- type: entity
|
||||||
|
# Just fades out with no movement animation
|
||||||
|
id: CMEffectScreechShort
|
||||||
|
categories: [ HideSpawnMenu ]
|
||||||
|
components:
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 1.4
|
||||||
|
- type: RMCXenoScreechShockWave
|
||||||
|
- type: Sprite
|
||||||
|
sprite: _RMC14/Effects/xeno_screech.rsi
|
||||||
|
noRot: true
|
||||||
|
state: screech
|
||||||
|
drawdepth: Effects
|
||||||
|
- type: EffectVisuals
|
||||||
|
- type: Tag
|
||||||
|
tags:
|
||||||
|
- HideContextMenu
|
||||||
9
Resources/Prototypes/_RMC14/Shaders/shaders.yml
Normal file
9
Resources/Prototypes/_RMC14/Shaders/shaders.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
||||||
|
- type: shader
|
||||||
|
id: RMCShockWave
|
||||||
|
kind: source
|
||||||
|
path: "/Textures/_RMC14/Shaders/shock_wave.swsl"
|
||||||
|
|
||||||
|
- type: shader
|
||||||
|
id: RMCXenoScreechShockWave
|
||||||
|
kind: source
|
||||||
|
path: "/Textures/_RMC14/Shaders/screech_shock_wave.swsl"
|
||||||
11
Resources/Prototypes/_Sunrise/Entities/Effects/explosion.yml
Normal file
11
Resources/Prototypes/_Sunrise/Entities/Effects/explosion.yml
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
- type: entity
|
||||||
|
id: ExplosionEffectSmoke
|
||||||
|
components:
|
||||||
|
- type: Sprite
|
||||||
|
drawdepth: Effects
|
||||||
|
sprite: _Sunrise/Effects/explosion_smoke.rsi
|
||||||
|
state: smoke
|
||||||
|
shader: unshaded
|
||||||
|
- type: ExplosionSmokeEffect
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 5
|
||||||
14
Resources/Prototypes/_Sunrise/explosion.yml
Normal file
14
Resources/Prototypes/_Sunrise/explosion.yml
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
- type: explosion
|
||||||
|
id: DefaultStandardEffect
|
||||||
|
damagePerIntensity:
|
||||||
|
types:
|
||||||
|
Heat: 5
|
||||||
|
Blunt: 5
|
||||||
|
Piercing: 5
|
||||||
|
tileBreakChance: [0, 0.5, 1]
|
||||||
|
tileBreakIntensity: [0, 10, 30]
|
||||||
|
tileBreakRerollReduction: 20
|
||||||
|
lightColor: Orange
|
||||||
|
texturePath: /Textures/Effects/fire.rsi
|
||||||
|
fireStates: 3
|
||||||
|
effectType: Standard
|
||||||
Binary file not shown.
|
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
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
26
Resources/Textures/_RMC14/Effects/xeno_screech.rsi/meta.json
Normal file
26
Resources/Textures/_RMC14/Effects/xeno_screech.rsi/meta.json
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CC-BY-SA-3.0",
|
||||||
|
"copyright": "Taken from cmss13 at https://github.com/cmss13-devs/cmss13/blob/d5b119380250ea512db2a5319e36592c7f604250/icons/effects/xeno_screech.dmi",
|
||||||
|
"size": {
|
||||||
|
"x": 64,
|
||||||
|
"y": 64
|
||||||
|
},
|
||||||
|
"states": [
|
||||||
|
{
|
||||||
|
"name": "screech",
|
||||||
|
"delays": [
|
||||||
|
[
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2,
|
||||||
|
0.2
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
BIN
Resources/Textures/_RMC14/Effects/xeno_screech.rsi/screech.png
Normal file
BIN
Resources/Textures/_RMC14/Effects/xeno_screech.rsi/screech.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 2.4 KiB |
28
Resources/Textures/_RMC14/Shaders/screech_shock_wave.swsl
Normal file
28
Resources/Textures/_RMC14/Shaders/screech_shock_wave.swsl
Normal file
|
|
@ -0,0 +1,28 @@
|
||||||
|
uniform sampler2D SCREEN_TEXTURE;
|
||||||
|
uniform highp float waveStrength;
|
||||||
|
uniform highp vec2 position;
|
||||||
|
uniform highp float waveSpeed;
|
||||||
|
uniform highp float downScale;
|
||||||
|
|
||||||
|
void fragment()
|
||||||
|
{
|
||||||
|
highp vec2 st = UV;
|
||||||
|
highp vec2 WaveCentre = position;
|
||||||
|
highp float ratio = SCREEN_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.x * 0.5;
|
||||||
|
WaveCentre.y *= ratio;
|
||||||
|
highp float dist = distance(vec2(st.x, st.y * ratio), WaveCentre) * downScale;
|
||||||
|
highp float val = dist;
|
||||||
|
highp float a = 3.0;
|
||||||
|
highp float cosFuns = cos(val * 20.0 - TIME * waveSpeed);
|
||||||
|
highp float powFuns = pow(val * 2.5, a);
|
||||||
|
highp float limtedPowFuns = 0.5 * pow(a / (a + powFuns), 2.0);
|
||||||
|
highp float finalRes = smoothstep(0.0, 1.0, limtedPowFuns * cosFuns) * waveStrength;
|
||||||
|
highp vec3 col = finalRes * vec3(1.0);
|
||||||
|
st = st * 2.0 - 1.0;
|
||||||
|
st *= 1.0 + finalRes * 0.1;
|
||||||
|
st = st * 0.5 + 0.5;
|
||||||
|
highp vec4 texCol = zTextureSpec(SCREEN_TEXTURE, st);
|
||||||
|
texCol += (texCol * finalRes) / (dist * 10.0);
|
||||||
|
|
||||||
|
COLOR = texCol;
|
||||||
|
}
|
||||||
40
Resources/Textures/_RMC14/Shaders/shock_wave.swsl
Normal file
40
Resources/Textures/_RMC14/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;
|
||||||
|
uniform highp float[10] time;
|
||||||
|
|
||||||
|
void fragment() {
|
||||||
|
highp vec2 coord = FRAGCOORD.xy * SCREEN_PIXEL_SIZE.xy;
|
||||||
|
highp float ratio = SCREEN_PIXEL_SIZE.y / SCREEN_PIXEL_SIZE.x * 0.6;
|
||||||
|
|
||||||
|
highp vec2 totalOffset = vec2(0.0);
|
||||||
|
|
||||||
|
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)
|
||||||
|
);
|
||||||
|
|
||||||
|
highp float CurrentTime = time[i];
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
totalOffset += (DiffTexCoord * DiffTime) / (CurrentTime * Dist * falloffPower[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
coord += totalOffset;
|
||||||
|
|
||||||
|
highp vec4 Color = texture(SCREEN_TEXTURE, coord);
|
||||||
|
COLOR = Color;
|
||||||
|
}
|
||||||
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/dust.png
Normal file
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/dust.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/fire.png
Normal file
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/fire.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/gas.png
Normal file
BIN
Resources/Textures/_Sunrise/Effects/explosion_smoke.rsi/gas.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
|
|
@ -0,0 +1,25 @@
|
||||||
|
{
|
||||||
|
"version": 1,
|
||||||
|
"license": "CLA",
|
||||||
|
"copyright": "SUNRISE",
|
||||||
|
"size":
|
||||||
|
{
|
||||||
|
"x": 128,
|
||||||
|
"y": 128
|
||||||
|
},
|
||||||
|
"states":
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"name": "smoke"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "dust"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "fire"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "gas"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
Loading…
Add table
Reference in a new issue