Files
tbd-station-14/Content.Server/Anomaly/AnomalySystem.Vessel.cs
2023-05-25 13:28:40 +10:00

199 lines
7.5 KiB
C#

using Content.Server.Anomaly.Components;
using Content.Server.Construction;
using Content.Server.Power.EntitySystems;
using Content.Shared.Anomaly;
using Content.Shared.Anomaly.Components;
using Content.Shared.Examine;
using Content.Shared.Interaction;
using Content.Shared.Research.Components;
namespace Content.Server.Anomaly;
/// <summary>
/// This handles anomalous vessel as well as
/// the calculations for how many points they
/// should produce.
/// </summary>
public sealed partial class AnomalySystem
{
private void InitializeVessel()
{
SubscribeLocalEvent<AnomalyVesselComponent, ComponentShutdown>(OnVesselShutdown);
SubscribeLocalEvent<AnomalyVesselComponent, MapInitEvent>(OnVesselMapInit);
SubscribeLocalEvent<AnomalyVesselComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<AnomalyVesselComponent, UpgradeExamineEvent>(OnUpgradeExamine);
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)
{
if (!args.IsInDetailsRange)
return;
args.PushText(component.Anomaly == null
? Loc.GetString("anomaly-vessel-component-not-assigned")
: Loc.GetString("anomaly-vessel-component-assigned"));
}
private void OnVesselShutdown(EntityUid uid, AnomalyVesselComponent component, ComponentShutdown args)
{
if (component.Anomaly is not { } anomaly)
return;
if (!TryComp<AnomalyComponent>(anomaly, out var anomalyComp))
return;
anomalyComp.ConnectedVessel = null;
}
private void OnVesselMapInit(EntityUid uid, AnomalyVesselComponent component, MapInitEvent args)
{
UpdateVesselAppearance(uid, component);
}
private void OnRefreshParts(EntityUid uid, AnomalyVesselComponent component, RefreshPartsEvent args)
{
var modifierRating = args.PartRatings[component.MachinePartPointModifier] - 1;
component.PointMultiplier = MathF.Pow(component.PartRatingPointModifier, modifierRating);
}
private void OnUpgradeExamine(EntityUid uid, AnomalyVesselComponent component, UpgradeExamineEvent args)
{
args.AddPercentageUpgrade("anomaly-vessel-component-upgrade-output", component.PointMultiplier);
}
private void OnVesselInteractUsing(EntityUid uid, AnomalyVesselComponent component, InteractUsingEvent args)
{
if (component.Anomaly != null ||
!TryComp<AnomalyScannerComponent>(args.Used, out var scanner) ||
scanner.ScannedAnomaly is not { } anomaly)
{
return;
}
if (!TryComp<AnomalyComponent>(anomaly, out var anomalyComponent) || anomalyComponent.ConnectedVessel != null)
return;
component.Anomaly = scanner.ScannedAnomaly;
anomalyComponent.ConnectedVessel = uid;
UpdateVesselAppearance(uid, component);
Popup.PopupEntity(Loc.GetString("anomaly-vessel-component-anomaly-assigned"), uid);
}
private void OnVesselGetPointsPerSecond(EntityUid uid, AnomalyVesselComponent component, ref ResearchServerGetPointsPerSecondEvent args)
{
if (!this.IsPowered(uid, EntityManager) || component.Anomaly is not {} anomaly)
return;
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)
{
var query = EntityQueryEnumerator<AnomalyVesselComponent>();
while (query.MoveNext(out var ent, out var component))
{
if (args.Anomaly != component.Anomaly)
continue;
component.Anomaly = null;
UpdateVesselAppearance(ent, component);
if (!args.Supercritical)
continue;
_explosion.TriggerExplosive(ent);
}
}
private void OnVesselAnomalyStabilityChanged(ref AnomalyStabilityChangedEvent args)
{
var query = EntityQueryEnumerator<AnomalyVesselComponent>();
while (query.MoveNext(out var ent, out var component))
{
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
/// </summary>
/// <param name="uid"></param>
/// <param name="component"></param>
public void UpdateVesselAppearance(EntityUid uid, AnomalyVesselComponent? component = null)
{
if (!Resolve(uid, ref component))
return;
var on = component.Anomaly != null;
if (!TryComp<AppearanceComponent>(uid, out var appearanceComponent))
return;
Appearance.SetData(uid, AnomalyVesselVisuals.HasAnomaly, on, appearanceComponent);
if (TryComp<SharedPointLightComponent>(uid, out var pointLightComponent))
_pointLight.SetEnabled(uid, on, pointLightComponent);
// 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()
{
var query = EntityQueryEnumerator<AnomalyVesselComponent>();
while (query.MoveNext(out var vesselEnt, out var vessel))
{
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;
}
}
}