Anomaly Synchronizer (#20945)

* added textures and basic prototype without functionality

* add full functional

* finish work

* fix naming

* reduce random anomaly spawner offset

* Update AnomalySystem.Vessel.cs

* Update SharedAnomalySystem.cs

* Update SharedAnomalySystem.cs

* Update production.yml

* fix errors

* fix?

* Update anomaly_sync.yml

* deltanedas code fixes. Thx, deltanedas!

* git what

* fix yml

* fix yml 2

* meh, try again

* work, work, work

* fix powered checking. now component work also without ApcPowerReceiving

* now supercrit port invoke on start growing, not after explosion
fix errors

* deltanedas fix pack 1

* Update AnomalySynchronizerComponent.cs
This commit is contained in:
Ed
2023-11-06 07:02:02 +03:00
committed by GitHub
parent ad1a280494
commit 8b3adf6085
20 changed files with 393 additions and 12 deletions

View File

@@ -0,0 +1,148 @@
using Content.Server.Anomaly.Components;
using Content.Server.DeviceLinking.Systems;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Shared.Anomaly.Components;
using Content.Shared.Interaction;
using Content.Shared.Popups;
namespace Content.Server.Anomaly;
/// <summary>
/// a device that allows you to translate anomaly activity into multitool signals.
/// </summary>
public sealed partial class AnomalySynchronizerSystem : EntitySystem
{
[Dependency] private readonly AnomalySystem _anomaly = default!;
[Dependency] private readonly SharedAudioSystem _audio = default!;
[Dependency] private readonly EntityLookupSystem _entityLookup = default!;
[Dependency] private readonly DeviceLinkSystem _signal = default!;
[Dependency] private readonly SharedTransformSystem _transform = default!;
[Dependency] private readonly SharedPopupSystem _popup = default!;
[Dependency] private readonly PowerReceiverSystem _power = default!;
public override void Initialize()
{
base.Initialize();
SubscribeLocalEvent<AnomalySynchronizerComponent, InteractHandEvent>(OnInteractHand);
SubscribeLocalEvent<AnomalySynchronizerComponent, PowerChangedEvent>(OnPowerChanged);
SubscribeLocalEvent<AnomalyPulseEvent>(OnAnomalyPulse);
SubscribeLocalEvent<AnomalySeverityChangedEvent>(OnAnomalySeverityChanged);
SubscribeLocalEvent<AnomalyStabilityChangedEvent>(OnAnomalyStabilityChanged);
}
private void OnPowerChanged(EntityUid uid, AnomalySynchronizerComponent component, ref PowerChangedEvent args)
{
if (args.Powered)
return;
if (!TryComp<AnomalyComponent>(component.ConnectedAnomaly, out var anomaly))
return;
_anomaly.DoAnomalyPulse(component.ConnectedAnomaly.Value, anomaly);
DisconneсtFromAnomaly(uid, component, anomaly);
}
private void OnInteractHand(EntityUid uid, AnomalySynchronizerComponent component, InteractHandEvent args)
{
if (!_power.IsPowered(uid))
return;
foreach (var entity in _entityLookup.GetEntitiesInRange(uid, 0.15f)) //is the radius of one tile. It must not be set higher, otherwise the anomaly can be moved from tile to tile
{
if (!TryComp<AnomalyComponent>(entity, out var anomaly))
continue;
ConnectToAnomaly(uid, component, entity, anomaly);
break;
}
}
private void ConnectToAnomaly(EntityUid uid, AnomalySynchronizerComponent component, EntityUid auid, AnomalyComponent anomaly)
{
if (component.ConnectedAnomaly == auid)
return;
component.ConnectedAnomaly = auid;
//move the anomaly to the center of the synchronizer, for aesthetics.
var targetXform = _transform.GetWorldPosition(uid);
_transform.SetWorldPosition(auid, targetXform);
_anomaly.DoAnomalyPulse(component.ConnectedAnomaly.Value, anomaly);
_popup.PopupEntity(Loc.GetString("anomaly-sync-connected"), uid, PopupType.Medium);
_audio.PlayPvs(component.ConnectedSound, uid);
}
//TO DO: disconnection from the anomaly should also be triggered if the anomaly is far away from the synchronizer.
//Currently only bluespace anomaly can do this, but for some reason it is the only one that cannot be connected to the synchronizer.
private void DisconneсtFromAnomaly(EntityUid uid, AnomalySynchronizerComponent component, AnomalyComponent anomaly)
{
if (component.ConnectedAnomaly == null)
return;
_anomaly.DoAnomalyPulse(component.ConnectedAnomaly.Value, anomaly);
_popup.PopupEntity(Loc.GetString("anomaly-sync-disconnected"), uid, PopupType.Large);
_audio.PlayPvs(component.ConnectedSound, uid);
component.ConnectedAnomaly = default!;
}
private void OnAnomalyPulse(ref AnomalyPulseEvent args)
{
var query = EntityQueryEnumerator<AnomalySynchronizerComponent>();
while (query.MoveNext(out var ent, out var component))
{
if (args.Anomaly != component.ConnectedAnomaly)
continue;
if (!_power.IsPowered(ent))
continue;
_signal.InvokePort(ent, component.PulsePort);
}
}
private void OnAnomalySeverityChanged(ref AnomalySeverityChangedEvent args)
{
var query = EntityQueryEnumerator<AnomalySynchronizerComponent>();
while (query.MoveNext(out var ent, out var component))
{
if (args.Anomaly != component.ConnectedAnomaly)
continue;
if (!_power.IsPowered(ent))
continue;
//The superscritical port is invoked not at the AnomalySupercriticalEvent,
//but at the moment the growth animation starts. Otherwise, there is no point in this port.
//ATTENTION! the console command supercriticalanomaly does not work here,
//as it forcefully causes growth to start without increasing severity.
if (args.Severity >= 1)
_signal.InvokePort(ent, component.SupercritPort);
}
}
private void OnAnomalyStabilityChanged(ref AnomalyStabilityChangedEvent args)
{
var query = EntityQueryEnumerator<AnomalySynchronizerComponent>();
while (query.MoveNext(out var ent, out var component))
{
if (args.Anomaly != component.ConnectedAnomaly)
continue;
if (TryComp<ApcPowerReceiverComponent>(ent, out var apcPower) && !apcPower.Powered)
continue;
if (args.Stability < 0.25f) //I couldn't find where these values are stored, so I hardcoded them. Tell me where these variables are stored and I'll fix it
{
_signal.InvokePort(ent, component.DecayingPort);
}
else if (args.Stability > 0.5f) //I couldn't find where these values are stored, so I hardcoded them. Tell me where these variables are stored and I'll fix it
{
_signal.InvokePort(ent, component.GrowingPort);
}
else
{
_signal.InvokePort(ent, component.StabilizePort);
}
}
}
}