Add device linking to emitter and APE (#16805)

This commit is contained in:
0x6273
2023-05-28 08:44:28 +02:00
committed by GitHub
parent 7594dabe14
commit 7a5a64ffb4
7 changed files with 160 additions and 44 deletions

View File

@@ -1,10 +1,10 @@
using System.Threading;
using Content.Server.Administration.Logs;
using Content.Server.Construction;
using Content.Server.DeviceLinking.Events;
using Content.Server.Power.Components;
using Content.Server.Power.EntitySystems;
using Content.Server.Projectiles;
using Content.Server.Storage.Components;
using Content.Server.Weapons.Ranged.Systems;
using Content.Shared.Database;
using Content.Shared.Examine;
@@ -50,6 +50,7 @@ namespace Content.Server.Singularity.EntitySystems
SubscribeLocalEvent<EmitterComponent, RefreshPartsEvent>(OnRefreshParts);
SubscribeLocalEvent<EmitterComponent, UpgradeExamineEvent>(OnUpgradeExamine);
SubscribeLocalEvent<EmitterComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
SubscribeLocalEvent<EmitterComponent, SignalReceivedEvent>(OnSignalReceived);
}
private void OnAnchorStateChanged(EntityUid uid, EmitterComponent component, ref AnchorStateChangedEvent args)
@@ -57,7 +58,7 @@ namespace Content.Server.Singularity.EntitySystems
if (args.Anchored)
return;
SwitchOff(component);
SwitchOff(uid, component);
}
private void OnInteractHand(EntityUid uid, EmitterComponent component, InteractHandEvent args)
@@ -65,26 +66,26 @@ namespace Content.Server.Singularity.EntitySystems
if (args.Handled)
return;
if (EntityManager.TryGetComponent(uid, out LockComponent? lockComp) && lockComp.Locked)
if (TryComp(uid, out LockComponent? lockComp) && lockComp.Locked)
{
_popup.PopupEntity(Loc.GetString("comp-emitter-access-locked",
("target", component.Owner)), uid, args.User);
("target", uid)), uid, args.User);
return;
}
if (EntityManager.TryGetComponent(component.Owner, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static)
if (TryComp(uid, out PhysicsComponent? phys) && phys.BodyType == BodyType.Static)
{
if (!component.IsOn)
{
SwitchOn(component);
SwitchOn(uid, component);
_popup.PopupEntity(Loc.GetString("comp-emitter-turned-on",
("target", component.Owner)), uid, args.User);
("target", uid)), uid, args.User);
}
else
{
SwitchOff(component);
SwitchOff(uid, component);
_popup.PopupEntity(Loc.GetString("comp-emitter-turned-off",
("target", component.Owner)), uid, args.User);
("target", uid)), uid, args.User);
}
_adminLogger.Add(LogType.Emitter,
@@ -95,7 +96,7 @@ namespace Content.Server.Singularity.EntitySystems
else
{
_popup.PopupEntity(Loc.GetString("comp-emitter-not-anchored",
("target", component.Owner)), uid, args.User);
("target", uid)), uid, args.User);
}
}
@@ -152,11 +153,11 @@ namespace Content.Server.Singularity.EntitySystems
if (args.ReceivedPower < args.DrawRate)
{
PowerOff(component);
PowerOff(uid, component);
}
else
{
PowerOn(component);
PowerOn(uid, component);
}
}
@@ -169,11 +170,11 @@ namespace Content.Server.Singularity.EntitySystems
if (!args.Powered)
{
PowerOff(component);
PowerOff(uid, component);
}
else
{
PowerOn(component);
PowerOn(uid, component);
}
}
@@ -191,33 +192,33 @@ namespace Content.Server.Singularity.EntitySystems
args.AddPercentageUpgrade("emitter-component-upgrade-fire-rate", (float) (component.BaseFireInterval.TotalSeconds / component.FireInterval.TotalSeconds));
}
public void SwitchOff(EmitterComponent component)
public void SwitchOff(EntityUid uid, EmitterComponent component)
{
component.IsOn = false;
if (TryComp<PowerConsumerComponent>(component.Owner, out var powerConsumer))
if (TryComp<PowerConsumerComponent>(uid, out var powerConsumer))
powerConsumer.DrawRate = 1; // this needs to be not 0 so that the visuals still work.
if (TryComp<ApcPowerReceiverComponent>(component.Owner, out var apcReceiever))
apcReceiever.Load = 1;
PowerOff(component);
UpdateAppearance(component);
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcReceiver))
apcReceiver.Load = 1;
PowerOff(uid, component);
UpdateAppearance(uid, component);
}
public void SwitchOn(EmitterComponent component)
public void SwitchOn(EntityUid uid, EmitterComponent component)
{
component.IsOn = true;
if (TryComp<PowerConsumerComponent>(component.Owner, out var powerConsumer))
if (TryComp<PowerConsumerComponent>(uid, out var powerConsumer))
powerConsumer.DrawRate = component.PowerUseActive;
if (TryComp<ApcPowerReceiverComponent>(component.Owner, out var apcReceiever))
if (TryComp<ApcPowerReceiverComponent>(uid, out var apcReceiver))
{
apcReceiever.Load = component.PowerUseActive;
PowerOn(component);
apcReceiver.Load = component.PowerUseActive;
PowerOn(uid, component);
}
// Do not directly PowerOn().
// OnReceivedPowerChanged will get fired due to DrawRate change which will turn it on.
UpdateAppearance(component);
UpdateAppearance(uid, component);
}
public void PowerOff(EmitterComponent component)
public void PowerOff(EntityUid uid, EmitterComponent component)
{
if (!component.IsPowered)
{
@@ -230,10 +231,10 @@ namespace Content.Server.Singularity.EntitySystems
DebugTools.AssertNotNull(component.TimerCancel);
component.TimerCancel?.Cancel();
UpdateAppearance(component);
UpdateAppearance(uid, component);
}
public void PowerOn(EmitterComponent component)
public void PowerOn(EntityUid uid, EmitterComponent component)
{
if (component.IsPowered)
{
@@ -245,12 +246,12 @@ namespace Content.Server.Singularity.EntitySystems
component.FireShotCounter = 0;
component.TimerCancel = new CancellationTokenSource();
Timer.Spawn(component.FireBurstDelayMax, () => ShotTimerCallback(component), component.TimerCancel.Token);
Timer.Spawn(component.FireBurstDelayMax, () => ShotTimerCallback(uid, component), component.TimerCancel.Token);
UpdateAppearance(component);
UpdateAppearance(uid, component);
}
private void ShotTimerCallback(EmitterComponent component)
private void ShotTimerCallback(EntityUid uid, EmitterComponent component)
{
if (component.Deleted)
return;
@@ -260,7 +261,7 @@ namespace Content.Server.Singularity.EntitySystems
DebugTools.Assert(component.IsPowered);
DebugTools.Assert(component.IsOn);
Fire(component);
Fire(uid, component);
TimeSpan delay;
if (component.FireShotCounter < component.FireBurstSize)
@@ -278,13 +279,12 @@ namespace Content.Server.Singularity.EntitySystems
// Must be set while emitter powered.
DebugTools.AssertNotNull(component.TimerCancel);
Timer.Spawn(delay, () => ShotTimerCallback(component), component.TimerCancel!.Token);
Timer.Spawn(delay, () => ShotTimerCallback(uid, component), component.TimerCancel!.Token);
}
private void Fire(EmitterComponent component)
private void Fire(EntityUid uid, EmitterComponent component)
{
var uid = component.Owner;
if (!TryComp<GunComponent>(uid, out var guncomp))
if (!TryComp<GunComponent>(uid, out var gunComponent))
return;
var xform = Transform(uid);
@@ -293,10 +293,11 @@ namespace Content.Server.Singularity.EntitySystems
_projectile.SetShooter(proj, uid);
var targetPos = new EntityCoordinates(uid, (0, -1));
_gun.Shoot(uid, guncomp, ent, xform.Coordinates, targetPos, out _);
_gun.Shoot(uid, gunComponent, ent, xform.Coordinates, targetPos, out _);
}
private void UpdateAppearance(EmitterComponent component)
private void UpdateAppearance(EntityUid uid, EmitterComponent component)
{
EmitterVisualState state;
if (component.IsPowered)
@@ -311,7 +312,34 @@ namespace Content.Server.Singularity.EntitySystems
{
state = EmitterVisualState.Off;
}
_appearance.SetData(component.Owner, EmitterVisuals.VisualState, state);
_appearance.SetData(uid, EmitterVisuals.VisualState, state);
}
private void OnSignalReceived(EntityUid uid, EmitterComponent component, ref SignalReceivedEvent args)
{
if (args.Port == component.OffPort)
{
SwitchOff(uid, component);
}
else if (args.Port == component.OnPort)
{
SwitchOn(uid, component);
}
else if (args.Port == component.TogglePort)
{
if (component.IsOn)
{
SwitchOff(uid, component);
}
else
{
SwitchOn(uid, component);
}
}
else if (component.SetTypePorts.TryGetValue(args.Port, out var boltType))
{
component.BoltType = boltType;
}
}
}
}

View File

@@ -25,14 +25,25 @@ namespace Content.Server.Singularity
var entityManager = IoCManager.Resolve<IEntityManager>();
var entitySystemManager = IoCManager.Resolve<IEntitySystemManager>();
foreach (var comp in entityManager.EntityQuery<EmitterComponent>())
// Turn on emitters
var emitterQuery = entityManager.EntityQueryEnumerator<EmitterComponent>();
var emitterSystem = entitySystemManager.GetEntitySystem<EmitterSystem>();
while (emitterQuery.MoveNext(out var uid, out var emitterComponent))
{
entitySystemManager.GetEntitySystem<EmitterSystem>().SwitchOn(comp);
//FIXME: This turns on ALL emitters, including APEs. It should only turn on the containment field emitters.
emitterSystem.SwitchOn(uid, emitterComponent);
}
foreach (var comp in entityManager.EntityQuery<RadiationCollectorComponent>())
// Turn on radiation collectors
var radiationCollectorQuery = entityManager.EntityQueryEnumerator<RadiationCollectorComponent>();
var radiationCollectorSystem = entitySystemManager.GetEntitySystem<RadiationCollectorSystem>();
while (radiationCollectorQuery.MoveNext(out var uid, out var radiationCollectorComponent))
{
entitySystemManager.GetEntitySystem<RadiationCollectorSystem>().SetCollectorEnabled(comp.Owner, true, null, comp);
radiationCollectorSystem.SetCollectorEnabled(uid, enabled: true, user: null, radiationCollectorComponent);
}
// Setup PA
foreach (var comp in entityManager.EntityQuery<ParticleAcceleratorControlBoxComponent>())
{
comp.RescanParts();

View File

@@ -1,10 +1,12 @@
using System.Threading;
using Content.Shared.Construction.Prototypes;
using Content.Shared.DeviceLinking;
using Robust.Shared.GameStates;
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.List;
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Dictionary;
namespace Content.Shared.Singularity.Components;
@@ -107,6 +109,30 @@ public sealed class EmitterComponent : Component
/// </summary>
[DataField("underpoweredState")]
public string? UnderpoweredState = "underpowered";
/// <summary>
/// Signal port that turns on the emitter.
/// </summary>
[DataField("onPort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string OnPort = "On";
/// <summary>
/// Signal port that turns off the emitter.
/// </summary>
[DataField("offPort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string OffPort = "Off";
/// <summary>
/// Signal port that toggles the emitter on or off.
/// </summary>
[DataField("togglePort", customTypeSerializer: typeof(PrototypeIdSerializer<SinkPortPrototype>))]
public string TogglePort = "Toggle";
/// <summary>
/// Map of signal ports to entity prototype IDs of the entity that will be fired.
/// </summary>
[DataField("setTypePorts", customTypeSerializer: typeof(PrototypeIdDictionarySerializer<string, SinkPortPrototype>))]
public Dictionary<string, string> SetTypePorts = new();
}
[NetSerializable, Serializable]

View File

@@ -60,3 +60,12 @@ signal-port-description-artifact-analyzer-sender = Analysis console signal sende
signal-port-name-artifact-analyzer-receiver = Pad
signal-port-description-artifact-analyzer-receiver = Artifact analyzer signal receiver
signal-port-name-set-particle-delta = Set particle type: delta
signal-port-description-set-particle-delta = Sets the type of particle this device emits to delta.
signal-port-name-set-particle-epsilon = Set particle type: epsilon
signal-port-description-set-particle-epsilon = Sets the type of particle this device emits to epsilon.
signal-port-name-set-particle-zeta = Set particle type: zeta
signal-port-description-set-particle-zeta = Sets the type of particle this device emits to zeta.

View File

@@ -97,3 +97,18 @@
id: B2
name: "Input B2"
description: "Input B2"
- type: sinkPort
id: SetParticleDelta
name: signal-port-name-set-particle-delta
description: signal-port-description-set-particle-delta
- type: sinkPort
id: SetParticleEpsilon
name: signal-port-name-set-particle-epsilon
description: signal-port-description-set-particle-epsilon
- type: sinkPort
id: SetParticleZeta
name: signal-port-name-set-particle-zeta
description: signal-port-description-set-particle-zeta

View File

@@ -151,6 +151,10 @@
- AnomalousParticleDelta
- AnomalousParticleEpsilon
- AnomalousParticleZeta
setTypePorts:
SetParticleDelta: AnomalousParticleDelta
SetParticleEpsilon: AnomalousParticleEpsilon
SetParticleZeta: AnomalousParticleZeta
fireBurstSize: 1
baseFireBurstDelayMin: 2
baseFireBurstDelayMax: 6
@@ -179,6 +183,19 @@
enum.PowerDeviceVisualLayers.Powered:
True: { visible: true }
False: { visible: false }
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: BasicDevice
- type: WirelessNetworkConnection
range: 200
- type: DeviceLinkSink
ports:
- On
- Off
- Toggle
- SetParticleDelta
- SetParticleEpsilon
- SetParticleZeta
- type: entity
id: MachineAnomalyGenerator

View File

@@ -90,3 +90,13 @@
board: EmitterCircuitboard
- type: GuideHelp
guides: [ Singularity, Power ]
- type: DeviceNetwork
deviceNetId: Wireless
receiveFrequencyId: BasicDevice
- type: WirelessNetworkConnection
range: 200
- type: DeviceLinkSink
ports:
- On
- Off
- Toggle