Radiation pulse ECS (#10641)
This commit is contained in:
@@ -1,37 +0,0 @@
|
|||||||
using Content.Shared.Radiation;
|
|
||||||
|
|
||||||
namespace Content.Client.Radiation
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedRadiationPulseComponent))]
|
|
||||||
public sealed class RadiationPulseComponent : SharedRadiationPulseComponent
|
|
||||||
{
|
|
||||||
private bool _draw;
|
|
||||||
private bool _decay;
|
|
||||||
private float _range;
|
|
||||||
private TimeSpan _startTime;
|
|
||||||
private TimeSpan _endTime;
|
|
||||||
|
|
||||||
public override float Range => _range;
|
|
||||||
public override TimeSpan StartTime => _startTime;
|
|
||||||
public override TimeSpan EndTime => _endTime;
|
|
||||||
public override bool Draw => _draw;
|
|
||||||
public override bool Decay => _decay;
|
|
||||||
|
|
||||||
public override void HandleComponentState(ComponentState? curState, ComponentState? nextState)
|
|
||||||
{
|
|
||||||
base.HandleComponentState(curState, nextState);
|
|
||||||
|
|
||||||
if (curState is not RadiationPulseState state)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_range = state.Range;
|
|
||||||
_draw = state.Draw;
|
|
||||||
_decay = state.Decay;
|
|
||||||
_startTime = state.StartTime;
|
|
||||||
_endTime = state.EndTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Content.Shared.Radiation.Components;
|
||||||
using Robust.Client.Graphics;
|
using Robust.Client.Graphics;
|
||||||
using Robust.Shared.Enums;
|
using Robust.Shared.Enums;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
@@ -18,8 +19,6 @@ namespace Content.Client.Radiation
|
|||||||
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
public override OverlaySpace Space => OverlaySpace.WorldSpace;
|
||||||
public override bool RequestScreenTexture => true;
|
public override bool RequestScreenTexture => true;
|
||||||
|
|
||||||
private TimeSpan _lastTick = default;
|
|
||||||
|
|
||||||
private readonly ShaderInstance _baseShader;
|
private readonly ShaderInstance _baseShader;
|
||||||
private readonly Dictionary<EntityUid, (ShaderInstance shd, RadiationShaderInstance instance)> _pulses = new();
|
private readonly Dictionary<EntityUid, (ShaderInstance shd, RadiationShaderInstance instance)> _pulses = new();
|
||||||
|
|
||||||
@@ -52,7 +51,7 @@ namespace Content.Client.Radiation
|
|||||||
shd?.SetParameter("renderScale", viewport.RenderScale);
|
shd?.SetParameter("renderScale", viewport.RenderScale);
|
||||||
shd?.SetParameter("positionInput", tempCoords);
|
shd?.SetParameter("positionInput", tempCoords);
|
||||||
shd?.SetParameter("range", instance.Range);
|
shd?.SetParameter("range", instance.Range);
|
||||||
var life = (_lastTick - instance.Start) / (instance.End - instance.Start);
|
var life = (_gameTiming.RealTime - instance.Start).TotalSeconds / instance.Duration;
|
||||||
shd?.SetParameter("life", (float) life);
|
shd?.SetParameter("life", (float) life);
|
||||||
|
|
||||||
// There's probably a very good reason not to do this.
|
// There's probably a very good reason not to do this.
|
||||||
@@ -75,8 +74,6 @@ namespace Content.Client.Radiation
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
_lastTick = _gameTiming.CurTime;
|
|
||||||
|
|
||||||
var currentEyeLoc = currentEye.Position;
|
var currentEyeLoc = currentEye.Position;
|
||||||
|
|
||||||
var pulses = _entityManager.EntityQuery<RadiationPulseComponent>();
|
var pulses = _entityManager.EntityQuery<RadiationPulseComponent>();
|
||||||
@@ -92,9 +89,9 @@ namespace Content.Client.Radiation
|
|||||||
_baseShader.Duplicate(),
|
_baseShader.Duplicate(),
|
||||||
new RadiationShaderInstance(
|
new RadiationShaderInstance(
|
||||||
_entityManager.GetComponent<TransformComponent>(pulseEntity).MapPosition.Position,
|
_entityManager.GetComponent<TransformComponent>(pulseEntity).MapPosition.Position,
|
||||||
pulse.Range,
|
pulse.VisualRange,
|
||||||
pulse.StartTime,
|
pulse.StartTime,
|
||||||
pulse.EndTime
|
pulse.VisualDuration
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
@@ -110,7 +107,7 @@ namespace Content.Client.Radiation
|
|||||||
{
|
{
|
||||||
var shaderInstance = _pulses[pulseEntity];
|
var shaderInstance = _pulses[pulseEntity];
|
||||||
shaderInstance.instance.CurrentMapCoords = _entityManager.GetComponent<TransformComponent>(pulseEntity).MapPosition.Position;
|
shaderInstance.instance.CurrentMapCoords = _entityManager.GetComponent<TransformComponent>(pulseEntity).MapPosition.Position;
|
||||||
shaderInstance.instance.Range = pulse.Range;
|
shaderInstance.instance.Range = pulse.VisualRange;
|
||||||
} else {
|
} else {
|
||||||
_pulses[pulseEntity].shd.Dispose();
|
_pulses[pulseEntity].shd.Dispose();
|
||||||
_pulses.Remove(pulseEntity);
|
_pulses.Remove(pulseEntity);
|
||||||
@@ -124,12 +121,12 @@ namespace Content.Client.Radiation
|
|||||||
return _entityManager.GetComponent<TransformComponent>(pulseEntity).MapID == currentEyeLoc.MapId && _entityManager.GetComponent<TransformComponent>(pulseEntity).Coordinates.InRange(_entityManager, EntityCoordinates.FromMap(_entityManager, _entityManager.GetComponent<TransformComponent>(pulseEntity).ParentUid, currentEyeLoc), MaxDist);
|
return _entityManager.GetComponent<TransformComponent>(pulseEntity).MapID == currentEyeLoc.MapId && _entityManager.GetComponent<TransformComponent>(pulseEntity).Coordinates.InRange(_entityManager, EntityCoordinates.FromMap(_entityManager, _entityManager.GetComponent<TransformComponent>(pulseEntity).ParentUid, currentEyeLoc), MaxDist);
|
||||||
}
|
}
|
||||||
|
|
||||||
private sealed record RadiationShaderInstance(Vector2 CurrentMapCoords, float Range, TimeSpan Start, TimeSpan End)
|
private sealed record RadiationShaderInstance(Vector2 CurrentMapCoords, float Range, TimeSpan Start, float Duration)
|
||||||
{
|
{
|
||||||
public Vector2 CurrentMapCoords = CurrentMapCoords;
|
public Vector2 CurrentMapCoords = CurrentMapCoords;
|
||||||
public float Range = Range;
|
public float Range = Range;
|
||||||
public TimeSpan Start = Start;
|
public TimeSpan Start = Start;
|
||||||
public TimeSpan End = End;
|
public float Duration = Duration;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,103 +0,0 @@
|
|||||||
using Content.Shared.Radiation;
|
|
||||||
using Robust.Shared.Audio;
|
|
||||||
using Robust.Shared.Player;
|
|
||||||
using Robust.Shared.Random;
|
|
||||||
using Robust.Shared.Timing;
|
|
||||||
|
|
||||||
namespace Content.Server.Radiation
|
|
||||||
{
|
|
||||||
[RegisterComponent]
|
|
||||||
[ComponentReference(typeof(SharedRadiationPulseComponent))]
|
|
||||||
public sealed class RadiationPulseComponent : SharedRadiationPulseComponent
|
|
||||||
{
|
|
||||||
[Dependency] private readonly IEntityManager _entMan = default!;
|
|
||||||
[Dependency] private readonly IGameTiming _gameTiming = default!;
|
|
||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
|
||||||
|
|
||||||
private float _duration;
|
|
||||||
private float _range = 5f;
|
|
||||||
private TimeSpan _startTime;
|
|
||||||
private TimeSpan _endTime;
|
|
||||||
private bool _draw = true;
|
|
||||||
private bool _decay = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Whether the entity will delete itself after a certain duration defined by
|
|
||||||
/// <see cref="MinPulseLifespan"/> and <see cref="MaxPulseLifespan"/>
|
|
||||||
/// </summary>
|
|
||||||
[DataField("decay")]
|
|
||||||
public override bool Decay
|
|
||||||
{
|
|
||||||
get => _decay;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_decay = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataField("minPulseLifespan")]
|
|
||||||
public float MinPulseLifespan { get; set; } = 0.8f;
|
|
||||||
|
|
||||||
[DataField("maxPulseLifespan")]
|
|
||||||
public float MaxPulseLifespan { get; set; } = 2.5f;
|
|
||||||
|
|
||||||
[DataField("sound")] public SoundSpecifier Sound { get; set; } = new SoundCollectionSpecifier("RadiationPulse");
|
|
||||||
|
|
||||||
[DataField("range")]
|
|
||||||
public override float Range
|
|
||||||
{
|
|
||||||
get => _range;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_range = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
[DataField("draw")]
|
|
||||||
public override bool Draw
|
|
||||||
{
|
|
||||||
get => _draw;
|
|
||||||
set
|
|
||||||
{
|
|
||||||
_draw = value;
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override TimeSpan StartTime => _startTime;
|
|
||||||
public override TimeSpan EndTime => _endTime;
|
|
||||||
|
|
||||||
public void DoPulse()
|
|
||||||
{
|
|
||||||
if (Decay)
|
|
||||||
{
|
|
||||||
var currentTime = _gameTiming.CurTime;
|
|
||||||
_startTime = currentTime;
|
|
||||||
_duration = _random.NextFloat() * (MaxPulseLifespan - MinPulseLifespan) + MinPulseLifespan;
|
|
||||||
_endTime = currentTime + TimeSpan.FromSeconds(_duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
SoundSystem.Play(Sound.GetSound(), Filter.Pvs(Owner), Owner);
|
|
||||||
|
|
||||||
Dirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override ComponentState GetComponentState()
|
|
||||||
{
|
|
||||||
return new RadiationPulseState(_range, Draw, Decay, _startTime, _endTime);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void Update(float frameTime)
|
|
||||||
{
|
|
||||||
if (!Decay || _entMan.Deleted(Owner))
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (_duration <= 0f)
|
|
||||||
_entMan.QueueDeleteEntity(Owner);
|
|
||||||
|
|
||||||
_duration -= frameTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
using Content.Server.Radiation.Systems;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
namespace Content.Server.Radiation
|
|
||||||
{
|
|
||||||
[UsedImplicitly]
|
|
||||||
public sealed class RadiationPulseSystem : EntitySystem
|
|
||||||
{
|
|
||||||
[Dependency] private readonly RadiationSystem _radiation = default!;
|
|
||||||
|
|
||||||
private const float RadiationCooldown = 1.0f;
|
|
||||||
private float _accumulator;
|
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
|
||||||
{
|
|
||||||
base.Update(frameTime);
|
|
||||||
|
|
||||||
_accumulator += frameTime;
|
|
||||||
|
|
||||||
while (_accumulator > RadiationCooldown)
|
|
||||||
{
|
|
||||||
_accumulator -= RadiationCooldown;
|
|
||||||
|
|
||||||
// All code here runs effectively every RadiationCooldown seconds, so use that as the "frame time".
|
|
||||||
foreach (var comp in EntityManager.EntityQuery<RadiationPulseComponent>())
|
|
||||||
{
|
|
||||||
comp.Update(RadiationCooldown);
|
|
||||||
var ent = comp.Owner;
|
|
||||||
|
|
||||||
if (Deleted(ent)) continue;
|
|
||||||
|
|
||||||
var cords = Transform(ent).MapPosition;
|
|
||||||
_radiation.IrradiateRange(cords, comp.Range, comp.RadsPerSecond, RadiationCooldown);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -7,6 +7,31 @@ public sealed class RadiationSystem : EntitySystem
|
|||||||
{
|
{
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
|
|
||||||
|
private const float RadiationCooldown = 1.0f;
|
||||||
|
private float _accumulator;
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
_accumulator += frameTime;
|
||||||
|
|
||||||
|
while (_accumulator > RadiationCooldown)
|
||||||
|
{
|
||||||
|
_accumulator -= RadiationCooldown;
|
||||||
|
|
||||||
|
// All code here runs effectively every RadiationCooldown seconds, so use that as the "frame time".
|
||||||
|
foreach (var comp in EntityManager.EntityQuery<RadiationSourceComponent>())
|
||||||
|
{
|
||||||
|
var ent = comp.Owner;
|
||||||
|
if (Deleted(ent))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
var cords = Transform(ent).MapPosition;
|
||||||
|
IrradiateRange(cords, comp.Range, comp.RadsPerSecond, RadiationCooldown);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void IrradiateRange(MapCoordinates coordinates, float range, float radsPerSecond, float time)
|
public void IrradiateRange(MapCoordinates coordinates, float range, float radsPerSecond, float time)
|
||||||
{
|
{
|
||||||
var lookUp = _lookup.GetEntitiesInRange(coordinates, range);
|
var lookUp = _lookup.GetEntitiesInRange(coordinates, range);
|
||||||
|
|||||||
@@ -12,6 +12,6 @@ namespace Content.Server.Sound.Components
|
|||||||
|
|
||||||
[ViewVariables(VVAccess.ReadWrite)]
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
[DataField("sound", required: true)]
|
[DataField("sound", required: true)]
|
||||||
public SoundSpecifier Sound { get; set; } = default!;
|
public SoundSpecifier? Sound;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace Content.Server.Sound.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Simple sound emitter that emits sound on entity spawn.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class EmitSoundOnSpawnComponent : BaseEmitSoundComponent
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -54,6 +54,7 @@ namespace Content.Server.Sound
|
|||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<EmitSoundOnSpawnComponent, ComponentInit>(HandleEmitSpawnOnInit);
|
||||||
SubscribeLocalEvent<EmitSoundOnLandComponent, LandEvent>(HandleEmitSoundOnLand);
|
SubscribeLocalEvent<EmitSoundOnLandComponent, LandEvent>(HandleEmitSoundOnLand);
|
||||||
SubscribeLocalEvent<EmitSoundOnUseComponent, UseInHandEvent>(HandleEmitSoundOnUseInHand);
|
SubscribeLocalEvent<EmitSoundOnUseComponent, UseInHandEvent>(HandleEmitSoundOnUseInHand);
|
||||||
SubscribeLocalEvent<EmitSoundOnThrowComponent, ThrownEvent>(HandleEmitSoundOnThrown);
|
SubscribeLocalEvent<EmitSoundOnThrowComponent, ThrownEvent>(HandleEmitSoundOnThrown);
|
||||||
@@ -64,6 +65,11 @@ namespace Content.Server.Sound
|
|||||||
SubscribeLocalEvent<EmitSoundOnDropComponent, DroppedEvent>(HandleEmitSoundOnDrop);
|
SubscribeLocalEvent<EmitSoundOnDropComponent, DroppedEvent>(HandleEmitSoundOnDrop);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void HandleEmitSpawnOnInit(EntityUid uid, EmitSoundOnSpawnComponent component, ComponentInit args)
|
||||||
|
{
|
||||||
|
TryEmitSound(component);
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleEmitSoundOnTrigger(EntityUid uid, EmitSoundOnTriggerComponent component, TriggerEvent args)
|
private void HandleEmitSoundOnTrigger(EntityUid uid, EmitSoundOnTriggerComponent component, TriggerEvent args)
|
||||||
{
|
{
|
||||||
TryEmitSound(component);
|
TryEmitSound(component);
|
||||||
@@ -122,6 +128,8 @@ namespace Content.Server.Sound
|
|||||||
|
|
||||||
private void TryEmitSound(BaseEmitSoundComponent component)
|
private void TryEmitSound(BaseEmitSoundComponent component)
|
||||||
{
|
{
|
||||||
|
if (component.Sound == null)
|
||||||
|
return;
|
||||||
_audioSystem.PlayPvs(component.Sound, component.Owner, component.Sound.Params.AddVolume(-2f));
|
_audioSystem.PlayPvs(component.Sound, component.Owner, component.Sound.Params.AddVolume(-2f));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using Content.Server.Radiation;
|
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
@@ -12,7 +11,6 @@ public sealed class RadiateArtifactComponent : Component
|
|||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Radiation pulse prototype to spawn.
|
/// Radiation pulse prototype to spawn.
|
||||||
/// Should has <see cref="RadiationPulseComponent"/>.
|
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("pulsePrototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
[DataField("pulsePrototype", customTypeSerializer:typeof(PrototypeIdSerializer<EntityPrototype>))]
|
||||||
public string PulsePrototype = "RadiationPulse";
|
public string PulsePrototype = "RadiationPulse";
|
||||||
|
|||||||
@@ -15,11 +15,6 @@ public sealed class RadiateArtifactSystem : EntitySystem
|
|||||||
private void OnActivate(EntityUid uid, RadiateArtifactComponent component, ArtifactActivatedEvent args)
|
private void OnActivate(EntityUid uid, RadiateArtifactComponent component, ArtifactActivatedEvent args)
|
||||||
{
|
{
|
||||||
var transform = Transform(uid);
|
var transform = Transform(uid);
|
||||||
|
EntityManager.SpawnEntity(component.PulsePrototype, transform.Coordinates);
|
||||||
var pulseUid = EntityManager.SpawnEntity(component.PulsePrototype, transform.Coordinates);
|
|
||||||
if (!TryComp(pulseUid, out RadiationPulseComponent? pulse))
|
|
||||||
return;
|
|
||||||
|
|
||||||
pulse.DoPulse();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,30 @@
|
|||||||
|
using Content.Shared.Radiation.Systems;
|
||||||
|
using Content.Shared.Spawners.Components;
|
||||||
|
|
||||||
|
namespace Content.Shared.Radiation.Components;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create circle pulse animation of radiation around object.
|
||||||
|
/// Drawn on client after creation only once per component lifetime.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
[Access(typeof(RadiationPulseSystem))]
|
||||||
|
public sealed class RadiationPulseComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Timestamp when component was assigned to this entity.
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan StartTime;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long will animation play in seconds.
|
||||||
|
/// Can be overridden by <see cref="TimedDespawnComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float VisualDuration = 2f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The range of animation.
|
||||||
|
/// Can be overridden by <see cref="RadiationSourceComponent"/>.
|
||||||
|
/// </summary>
|
||||||
|
public float VisualRange = 5f;
|
||||||
|
}
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
/// <summary>
|
||||||
|
/// Irradiate all objects in range.
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent]
|
||||||
|
public sealed class RadiationSourceComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// How many rads per second receive irradiated object.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("radsPerSecond")]
|
||||||
|
public float RadsPerSecond = 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Radius of radiation source.
|
||||||
|
/// </summary>
|
||||||
|
[ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
[DataField("range")]
|
||||||
|
public float Range = 5f;
|
||||||
|
}
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
using Robust.Shared.GameStates;
|
|
||||||
using Robust.Shared.Serialization;
|
|
||||||
|
|
||||||
namespace Content.Shared.Radiation
|
|
||||||
{
|
|
||||||
[NetworkedComponent()]
|
|
||||||
public abstract class SharedRadiationPulseComponent : Component
|
|
||||||
{
|
|
||||||
[DataField("radsPerSecond")]
|
|
||||||
public float RadsPerSecond { get; set; } = 1;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Radius of the pulse from its position
|
|
||||||
/// </summary>
|
|
||||||
public virtual float Range { get; set; }
|
|
||||||
|
|
||||||
public virtual bool Decay { get; set; }
|
|
||||||
public virtual bool Draw { get; set; }
|
|
||||||
|
|
||||||
public virtual TimeSpan StartTime { get; }
|
|
||||||
public virtual TimeSpan EndTime { get; }
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// For syncing the pulse's lifespan between client and server for the overlay
|
|
||||||
/// </summary>
|
|
||||||
[Serializable, NetSerializable]
|
|
||||||
public sealed class RadiationPulseState : ComponentState
|
|
||||||
{
|
|
||||||
// not networking RadsPerSecond because damage is only ever dealt by server-side systems.
|
|
||||||
|
|
||||||
public readonly float Range;
|
|
||||||
public readonly bool Draw;
|
|
||||||
public readonly bool Decay;
|
|
||||||
public readonly TimeSpan StartTime;
|
|
||||||
public readonly TimeSpan EndTime;
|
|
||||||
|
|
||||||
public RadiationPulseState(float range, bool draw, bool decay, TimeSpan startTime, TimeSpan endTime)
|
|
||||||
{
|
|
||||||
Range = range;
|
|
||||||
Draw = draw;
|
|
||||||
Decay = decay;
|
|
||||||
StartTime = startTime;
|
|
||||||
EndTime = endTime;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
32
Content.Shared/Radiation/Systems/RadiationPulseSystem.cs
Normal file
32
Content.Shared/Radiation/Systems/RadiationPulseSystem.cs
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
using Content.Shared.Radiation.Components;
|
||||||
|
using Content.Shared.Spawners.Components;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.Radiation.Systems;
|
||||||
|
|
||||||
|
public sealed class RadiationPulseSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
|
public override void Initialize()
|
||||||
|
{
|
||||||
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<RadiationPulseComponent, ComponentStartup>(OnStartup);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnStartup(EntityUid uid, RadiationPulseComponent component, ComponentStartup args)
|
||||||
|
{
|
||||||
|
component.StartTime = _timing.RealTime;
|
||||||
|
|
||||||
|
// try to get despawn time or keep default duration time
|
||||||
|
if (TryComp<TimedDespawnComponent>(uid, out var despawn))
|
||||||
|
{
|
||||||
|
component.VisualDuration = despawn.Lifetime;
|
||||||
|
}
|
||||||
|
// try to get radiation range or keep default visual range
|
||||||
|
if (TryComp<RadiationSourceComponent>(uid, out var radSource))
|
||||||
|
{
|
||||||
|
component.VisualRange = radSource.Range;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -105,9 +105,9 @@ namespace Content.Shared.Singularity
|
|||||||
|
|
||||||
singularity.Level = value;
|
singularity.Level = value;
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent(singularity.Owner, out SharedRadiationPulseComponent? pulse))
|
if (EntityManager.TryGetComponent(singularity.Owner, out RadiationSourceComponent? source))
|
||||||
{
|
{
|
||||||
pulse.RadsPerSecond = singularity.RadsPerLevel * value;
|
source.RadsPerSecond = singularity.RadsPerLevel * value;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (EntityManager.TryGetComponent(singularity.Owner, out AppearanceComponent? appearance))
|
if (EntityManager.TryGetComponent(singularity.Owner, out AppearanceComponent? appearance))
|
||||||
|
|||||||
@@ -4,7 +4,12 @@
|
|||||||
noSpawn: true
|
noSpawn: true
|
||||||
description: Looking at this anomaly makes you feel strange, like something is pushing at your eyes.
|
description: Looking at this anomaly makes you feel strange, like something is pushing at your eyes.
|
||||||
components:
|
components:
|
||||||
- type: RadiationPulse
|
- type: RadiationSource
|
||||||
minPulseLifespan: 0.8
|
|
||||||
maxPulseLifespan: 2.5
|
|
||||||
radsPerSecond: 5
|
radsPerSecond: 5
|
||||||
|
- type: TimedDespawn
|
||||||
|
lifetime: 2
|
||||||
|
- type: EmitSoundOnSpawn
|
||||||
|
sound:
|
||||||
|
collection:
|
||||||
|
RadiationPulse
|
||||||
|
- type: RadiationPulse
|
||||||
|
|||||||
@@ -24,13 +24,10 @@
|
|||||||
layer:
|
layer:
|
||||||
- AllMask
|
- AllMask
|
||||||
- type: Singularity
|
- type: Singularity
|
||||||
radsPerLevel: 1 # determines RadiationPulse's radiation per second.
|
radsPerLevel: 1
|
||||||
- type: SingularityDistortion
|
- type: SingularityDistortion
|
||||||
- type: RadiationPulse
|
- type: RadiationSource
|
||||||
range: 10
|
range: 10
|
||||||
decay: false
|
|
||||||
minPulseLifespan: 1
|
|
||||||
maxPulseLifespan: 1
|
|
||||||
- type: Sprite
|
- type: Sprite
|
||||||
sprite: Structures/Power/Generation/Singularity/singularity_1.rsi
|
sprite: Structures/Power/Generation/Singularity/singularity_1.rsi
|
||||||
state: singularity_1
|
state: singularity_1
|
||||||
|
|||||||
@@ -243,8 +243,5 @@
|
|||||||
layers:
|
layers:
|
||||||
- state: rtg_damaged
|
- state: rtg_damaged
|
||||||
- state: rtg_glow
|
- state: rtg_glow
|
||||||
- type: RadiationPulse # ideally only when opened.
|
- type: RadiationSource # ideally only when opened.
|
||||||
range: 2
|
range: 2
|
||||||
decay: false
|
|
||||||
minPulseLifespan: 1
|
|
||||||
maxPulseLifespan: 1
|
|
||||||
|
|||||||
Reference in New Issue
Block a user