Anomaly Vessel visuals + audio (#13927)
This commit is contained in:
@@ -25,7 +25,9 @@ public sealed partial class AnomalySystem
|
||||
SubscribeLocalEvent<AnomalyVesselComponent, InteractUsingEvent>(OnVesselInteractUsing);
|
||||
SubscribeLocalEvent<AnomalyVesselComponent, ExaminedEvent>(OnExamined);
|
||||
SubscribeLocalEvent<AnomalyVesselComponent, ResearchServerGetPointsPerSecondEvent>(OnVesselGetPointsPerSecond);
|
||||
SubscribeLocalEvent<AnomalyVesselComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||
SubscribeLocalEvent<AnomalyShutdownEvent>(OnVesselAnomalyShutdown);
|
||||
SubscribeLocalEvent<AnomalyStabilityChangedEvent>(OnVesselAnomalyStabilityChanged);
|
||||
}
|
||||
|
||||
private void OnExamined(EntityUid uid, AnomalyVesselComponent component, ExaminedEvent args)
|
||||
@@ -94,6 +96,11 @@ public sealed partial class AnomalySystem
|
||||
args.Points += (int) (GetAnomalyPointValue(anomaly) * component.PointMultiplier);
|
||||
}
|
||||
|
||||
private void OnUnpaused(EntityUid uid, AnomalyVesselComponent component, ref EntityUnpausedEvent args)
|
||||
{
|
||||
component.NextBeep += args.PausedTime;
|
||||
}
|
||||
|
||||
private void OnVesselAnomalyShutdown(ref AnomalyShutdownEvent args)
|
||||
{
|
||||
foreach (var component in EntityQuery<AnomalyVesselComponent>())
|
||||
@@ -112,6 +119,18 @@ public sealed partial class AnomalySystem
|
||||
}
|
||||
}
|
||||
|
||||
private void OnVesselAnomalyStabilityChanged(ref AnomalyStabilityChangedEvent args)
|
||||
{
|
||||
foreach (var component in EntityQuery<AnomalyVesselComponent>())
|
||||
{
|
||||
var ent = component.Owner;
|
||||
if (args.Anomaly != component.Anomaly)
|
||||
continue;
|
||||
|
||||
UpdateVesselAppearance(ent, component);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the appearance of an anomaly vessel
|
||||
/// based on whether or not it has an anomaly
|
||||
@@ -125,11 +144,61 @@ public sealed partial class AnomalySystem
|
||||
|
||||
var on = component.Anomaly != null;
|
||||
|
||||
Appearance.SetData(uid, AnomalyVesselVisuals.HasAnomaly, on);
|
||||
if (!TryComp<AppearanceComponent>(uid, out var appearanceComponent))
|
||||
return;
|
||||
|
||||
Appearance.SetData(uid, AnomalyVesselVisuals.HasAnomaly, on, appearanceComponent);
|
||||
if (TryComp<SharedPointLightComponent>(uid, out var pointLightComponent))
|
||||
{
|
||||
pointLightComponent.Enabled = on;
|
||||
}
|
||||
|
||||
// arbitrary value for the generic visualizer to use.
|
||||
// i didn't feel like making an enum for this.
|
||||
var value = 1;
|
||||
if (TryComp<AnomalyComponent>(component.Anomaly, out var anomalyComp))
|
||||
{
|
||||
if (anomalyComp.Stability <= anomalyComp.DecayThreshold)
|
||||
{
|
||||
value = 2;
|
||||
}
|
||||
else if (anomalyComp.Stability >= anomalyComp.GrowthThreshold)
|
||||
{
|
||||
value = 3;
|
||||
}
|
||||
}
|
||||
Appearance.SetData(uid, AnomalyVesselVisuals.AnomalyState, value, appearanceComponent);
|
||||
|
||||
_ambient.SetAmbience(uid, on);
|
||||
}
|
||||
|
||||
private void UpdateVessels()
|
||||
{
|
||||
foreach (var vessel in EntityQuery<AnomalyVesselComponent>())
|
||||
{
|
||||
var vesselEnt = vessel.Owner;
|
||||
if (vessel.Anomaly is not { } anomUid)
|
||||
continue;
|
||||
|
||||
if (!TryComp<AnomalyComponent>(anomUid, out var anomaly))
|
||||
continue;
|
||||
|
||||
if (Timing.CurTime < vessel.NextBeep)
|
||||
continue;
|
||||
|
||||
// a lerp between the max and min values for each threshold.
|
||||
// longer beeps that get shorter as the anomaly gets more extreme
|
||||
float timerPercentage;
|
||||
if (anomaly.Stability <= anomaly.DecayThreshold)
|
||||
timerPercentage = (anomaly.DecayThreshold - anomaly.Stability) / anomaly.DecayThreshold;
|
||||
else if (anomaly.Stability >= anomaly.GrowthThreshold)
|
||||
timerPercentage = (anomaly.Stability - anomaly.GrowthThreshold) / (1 - anomaly.GrowthThreshold);
|
||||
else //it's not unstable
|
||||
continue;
|
||||
|
||||
Audio.PlayPvs(vessel.BeepSound, vesselEnt);
|
||||
var beepInterval = (vessel.MaxBeepInterval - vessel.MinBeepInterval) * (1 - timerPercentage) + vessel.MinBeepInterval;
|
||||
vessel.NextBeep = beepInterval + Timing.CurTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -124,4 +124,11 @@ public sealed partial class AnomalySystem : SharedAnomalySystem
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
}
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
UpdateVessels();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Content.Shared.Construction.Prototypes;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||
|
||||
namespace Content.Server.Anomaly.Components;
|
||||
@@ -37,4 +39,28 @@ public sealed class AnomalyVesselComponent : Component
|
||||
/// </summary>
|
||||
[DataField("partRatingPointModifier")]
|
||||
public float PartRatingPointModifier = 1.5f;
|
||||
|
||||
/// <summary>
|
||||
/// The maximum time between each beep
|
||||
/// </summary>
|
||||
[DataField("maxBeepInterval")]
|
||||
public TimeSpan MaxBeepInterval = TimeSpan.FromSeconds(2f);
|
||||
|
||||
/// <summary>
|
||||
/// The minimum time between each beep
|
||||
/// </summary>
|
||||
[DataField("minBeepInterval")]
|
||||
public TimeSpan MinBeepInterval = TimeSpan.FromSeconds(0.75f);
|
||||
|
||||
/// <summary>
|
||||
/// When the next beep sound will play
|
||||
/// </summary>
|
||||
[DataField("nextBeep", customTypeSerializer:typeof(TimeOffsetSerializer))]
|
||||
public TimeSpan NextBeep = TimeSpan.Zero;
|
||||
|
||||
/// <summary>
|
||||
/// The sound that is played repeatedly when the anomaly is destabilizing/decaying
|
||||
/// </summary>
|
||||
[DataField("beepSound")]
|
||||
public SoundSpecifier BeepSound = new SoundPathSpecifier("/Audio/Machines/vessel_warning.ogg");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user