This reverts commit 0da5a78509.
This commit is contained in:
24
Content.Client/Emp/EmpSystem.cs
Normal file
24
Content.Client/Emp/EmpSystem.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
using Content.Shared.Emp;
|
||||||
|
using Robust.Shared.Random;
|
||||||
|
|
||||||
|
namespace Content.Client.Emp;
|
||||||
|
|
||||||
|
public sealed class EmpSystem : SharedEmpSystem
|
||||||
|
{
|
||||||
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
var query = EntityQueryEnumerator<EmpDisabledComponent, TransformComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out var comp, out var transform))
|
||||||
|
{
|
||||||
|
if (Timing.CurTime > comp.TargetTime)
|
||||||
|
{
|
||||||
|
comp.TargetTime = Timing.CurTime + _random.NextFloat(0.8f, 1.2f) * TimeSpan.FromSeconds(comp.EffectCooldown);
|
||||||
|
Spawn(EmpDisabledEffectPrototype, transform.Coordinates);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -59,7 +59,7 @@ public sealed class ElectricityAnomalySystem : EntitySystem
|
|||||||
}
|
}
|
||||||
|
|
||||||
var empRange = component.MaxElectrocuteRange * 3;
|
var empRange = component.MaxElectrocuteRange * 3;
|
||||||
_emp.EmpPulse(Transform(uid).MapPosition, empRange, component.EmpEnergyConsumption);
|
_emp.EmpPulse(Transform(uid).MapPosition, empRange, component.EmpEnergyConsumption, component.EmpDisabledDuration);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void Update(float frameTime)
|
public override void Update(float frameTime)
|
||||||
|
|||||||
@@ -15,4 +15,10 @@ public sealed class EmpOnTriggerComponent : Component
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[DataField("energyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField("energyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float EnergyConsumption;
|
public float EnergyConsumption;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// How long it disables targets in seconds
|
||||||
|
/// </summary>
|
||||||
|
[DataField("disableDuration"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float DisableDuration = 60f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,39 +1,107 @@
|
|||||||
using Content.Server.Explosion.EntitySystems;
|
using Content.Server.Explosion.EntitySystems;
|
||||||
|
using Content.Server.Power.EntitySystems;
|
||||||
|
using Content.Server.Radio;
|
||||||
|
using Content.Server.SurveillanceCamera;
|
||||||
|
using Content.Shared.Emp;
|
||||||
|
using Content.Shared.Examine;
|
||||||
using Robust.Shared.Map;
|
using Robust.Shared.Map;
|
||||||
|
|
||||||
namespace Content.Server.Emp;
|
namespace Content.Server.Emp;
|
||||||
|
|
||||||
public sealed class EmpSystem : EntitySystem
|
public sealed class EmpSystem : SharedEmpSystem
|
||||||
{
|
{
|
||||||
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
[Dependency] private readonly EntityLookupSystem _lookup = default!;
|
||||||
|
|
||||||
public const string EmpPulseEffectPrototype = "EffectEmpPulse";
|
public const string EmpPulseEffectPrototype = "EffectEmpPulse";
|
||||||
public const string EmpDisabledEffectPrototype = "EffectEmpDisabled";
|
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
{
|
{
|
||||||
base.Initialize();
|
base.Initialize();
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, EntityUnpausedEvent>(OnUnpaused);
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, ExaminedEvent>(OnExamine);
|
||||||
SubscribeLocalEvent<EmpOnTriggerComponent, TriggerEvent>(HandleEmpTrigger);
|
SubscribeLocalEvent<EmpOnTriggerComponent, TriggerEvent>(HandleEmpTrigger);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, RadioSendAttemptEvent>(OnRadioSendAttempt);
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, RadioReceiveAttemptEvent>(OnRadioReceiveAttempt);
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, ApcToggleMainBreakerAttemptEvent>(OnApcToggleMainBreaker);
|
||||||
|
SubscribeLocalEvent<EmpDisabledComponent, SurveillanceCameraSetActiveAttemptEvent>(OnCameraSetActive);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void EmpPulse(MapCoordinates coordinates, float range, float energyConsumption)
|
public void EmpPulse(MapCoordinates coordinates, float range, float energyConsumption, float duration)
|
||||||
{
|
{
|
||||||
foreach (var uid in _lookup.GetEntitiesInRange(coordinates, range))
|
foreach (var uid in _lookup.GetEntitiesInRange(coordinates, range))
|
||||||
{
|
{
|
||||||
var ev = new EmpPulseEvent(energyConsumption, false);
|
var ev = new EmpPulseEvent(energyConsumption, false, false);
|
||||||
RaiseLocalEvent(uid, ref ev);
|
RaiseLocalEvent(uid, ref ev);
|
||||||
if (ev.Affected)
|
if (ev.Affected)
|
||||||
|
{
|
||||||
Spawn(EmpDisabledEffectPrototype, Transform(uid).Coordinates);
|
Spawn(EmpDisabledEffectPrototype, Transform(uid).Coordinates);
|
||||||
|
}
|
||||||
|
if (ev.Disabled)
|
||||||
|
{
|
||||||
|
var disabled = EnsureComp<EmpDisabledComponent>(uid);
|
||||||
|
disabled.DisabledUntil = Timing.CurTime + TimeSpan.FromSeconds(duration);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Spawn(EmpPulseEffectPrototype, coordinates);
|
Spawn(EmpPulseEffectPrototype, coordinates);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public override void Update(float frameTime)
|
||||||
|
{
|
||||||
|
base.Update(frameTime);
|
||||||
|
|
||||||
|
var query = EntityQueryEnumerator<EmpDisabledComponent>();
|
||||||
|
while (query.MoveNext(out var uid, out var comp))
|
||||||
|
{
|
||||||
|
if (comp.DisabledUntil < Timing.CurTime)
|
||||||
|
{
|
||||||
|
RemComp<EmpDisabledComponent>(uid);
|
||||||
|
var ev = new EmpDisabledRemoved();
|
||||||
|
RaiseLocalEvent(uid, ref ev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnUnpaused(EntityUid uid, EmpDisabledComponent component, ref EntityUnpausedEvent args)
|
||||||
|
{
|
||||||
|
component.DisabledUntil += args.PausedTime;
|
||||||
|
component.TargetTime += args.PausedTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnExamine(EntityUid uid, EmpDisabledComponent component, ExaminedEvent args)
|
||||||
|
{
|
||||||
|
args.PushMarkup(Loc.GetString("emp-disabled-comp-on-examine"));
|
||||||
|
}
|
||||||
|
|
||||||
private void HandleEmpTrigger(EntityUid uid, EmpOnTriggerComponent comp, TriggerEvent args)
|
private void HandleEmpTrigger(EntityUid uid, EmpOnTriggerComponent comp, TriggerEvent args)
|
||||||
{
|
{
|
||||||
EmpPulse(Transform(uid).MapPosition, comp.Range, comp.EnergyConsumption);
|
EmpPulse(Transform(uid).MapPosition, comp.Range, comp.EnergyConsumption, comp.DisableDuration);
|
||||||
args.Handled = true;
|
args.Handled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnRadioSendAttempt(EntityUid uid, EmpDisabledComponent component, ref RadioSendAttemptEvent args)
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRadioReceiveAttempt(EntityUid uid, EmpDisabledComponent component, ref RadioReceiveAttemptEvent args)
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnApcToggleMainBreaker(EntityUid uid, EmpDisabledComponent component, ref ApcToggleMainBreakerAttemptEvent args)
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCameraSetActive(EntityUid uid, EmpDisabledComponent component, ref SurveillanceCameraSetActiveAttemptEvent args)
|
||||||
|
{
|
||||||
|
args.Cancelled = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[ByRefEvent]
|
[ByRefEvent]
|
||||||
public record struct EmpPulseEvent(float EnergyConsumption, bool Affected);
|
public record struct EmpPulseEvent(float EnergyConsumption, bool Affected, bool Disabled);
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct EmpDisabledRemoved();
|
||||||
|
|||||||
@@ -224,19 +224,20 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Try to break bulb inside light fixture
|
/// Try to break bulb inside light fixture
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void TryDestroyBulb(EntityUid uid, PoweredLightComponent? light = null)
|
public bool TryDestroyBulb(EntityUid uid, PoweredLightComponent? light = null)
|
||||||
{
|
{
|
||||||
// check bulb state
|
// check bulb state
|
||||||
var bulbUid = GetBulb(uid, light);
|
var bulbUid = GetBulb(uid, light);
|
||||||
if (bulbUid == null || !EntityManager.TryGetComponent(bulbUid.Value, out LightBulbComponent? lightBulb))
|
if (bulbUid == null || !EntityManager.TryGetComponent(bulbUid.Value, out LightBulbComponent? lightBulb))
|
||||||
return;
|
return false;
|
||||||
if (lightBulb.State == LightBulbState.Broken)
|
if (lightBulb.State == LightBulbState.Broken)
|
||||||
return;
|
return false;
|
||||||
|
|
||||||
// break it
|
// break it
|
||||||
_bulbSystem.SetState(bulbUid.Value, LightBulbState.Broken, lightBulb);
|
_bulbSystem.SetState(bulbUid.Value, LightBulbState.Broken, lightBulb);
|
||||||
_bulbSystem.PlayBreakSound(bulbUid.Value, lightBulb);
|
_bulbSystem.PlayBreakSound(bulbUid.Value, lightBulb);
|
||||||
UpdateLight(uid, light);
|
UpdateLight(uid, light);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
@@ -428,8 +429,8 @@ namespace Content.Server.Light.EntitySystems
|
|||||||
|
|
||||||
private void OnEmpPulse(EntityUid uid, PoweredLightComponent component, ref EmpPulseEvent args)
|
private void OnEmpPulse(EntityUid uid, PoweredLightComponent component, ref EmpPulseEvent args)
|
||||||
{
|
{
|
||||||
args.Affected = true;
|
if (TryDestroyBulb(uid, component))
|
||||||
TryDestroyBulb(uid, component);
|
args.Affected = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,6 +69,15 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
}
|
}
|
||||||
private void OnToggleMainBreaker(EntityUid uid, ApcComponent component, ApcToggleMainBreakerMessage args)
|
private void OnToggleMainBreaker(EntityUid uid, ApcComponent component, ApcToggleMainBreakerMessage args)
|
||||||
{
|
{
|
||||||
|
var attemptEv = new ApcToggleMainBreakerAttemptEvent();
|
||||||
|
RaiseLocalEvent(uid, ref attemptEv);
|
||||||
|
if (attemptEv.Cancelled)
|
||||||
|
{
|
||||||
|
_popup.PopupCursor(Loc.GetString("apc-component-on-toggle-cancel"),
|
||||||
|
args.Session, PopupType.Medium);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
TryComp<AccessReaderComponent>(uid, out var access);
|
TryComp<AccessReaderComponent>(uid, out var access);
|
||||||
if (args.Session.AttachedEntity == null)
|
if (args.Session.AttachedEntity == null)
|
||||||
return;
|
return;
|
||||||
@@ -183,8 +192,12 @@ namespace Content.Server.Power.EntitySystems
|
|||||||
if (component.MainBreakerEnabled)
|
if (component.MainBreakerEnabled)
|
||||||
{
|
{
|
||||||
args.Affected = true;
|
args.Affected = true;
|
||||||
|
args.Disabled = true;
|
||||||
ApcToggleBreaker(uid, component);
|
ApcToggleBreaker(uid, component);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct ApcToggleMainBreakerAttemptEvent(bool Cancelled);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using Content.Server.Chat.Systems;
|
using Content.Server.Chat.Systems;
|
||||||
|
using Content.Server.Emp;
|
||||||
using Content.Server.Radio.Components;
|
using Content.Server.Radio.Components;
|
||||||
using Content.Shared.Inventory.Events;
|
using Content.Shared.Inventory.Events;
|
||||||
using Content.Shared.Radio;
|
using Content.Shared.Radio;
|
||||||
@@ -21,6 +22,8 @@ public sealed class HeadsetSystem : SharedHeadsetSystem
|
|||||||
SubscribeLocalEvent<HeadsetComponent, EncryptionChannelsChangedEvent>(OnKeysChanged);
|
SubscribeLocalEvent<HeadsetComponent, EncryptionChannelsChangedEvent>(OnKeysChanged);
|
||||||
|
|
||||||
SubscribeLocalEvent<WearingHeadsetComponent, EntitySpokeEvent>(OnSpeak);
|
SubscribeLocalEvent<WearingHeadsetComponent, EntitySpokeEvent>(OnSpeak);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<HeadsetComponent, EmpPulseEvent>(OnEmpPulse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnKeysChanged(EntityUid uid, HeadsetComponent component, EncryptionChannelsChangedEvent args)
|
private void OnKeysChanged(EntityUid uid, HeadsetComponent component, EncryptionChannelsChangedEvent args)
|
||||||
@@ -98,4 +101,13 @@ public sealed class HeadsetSystem : SharedHeadsetSystem
|
|||||||
if (TryComp(Transform(uid).ParentUid, out ActorComponent? actor))
|
if (TryComp(Transform(uid).ParentUid, out ActorComponent? actor))
|
||||||
_netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.ConnectedClient);
|
_netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.ConnectedClient);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnEmpPulse(EntityUid uid, HeadsetComponent component, ref EmpPulseEvent args)
|
||||||
|
{
|
||||||
|
if (component.Enabled)
|
||||||
|
{
|
||||||
|
args.Affected = true;
|
||||||
|
args.Disabled = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,6 +80,7 @@ public sealed class RadioSystem : EntitySystem
|
|||||||
|
|
||||||
var sendAttemptEv = new RadioSendAttemptEvent(channel, radioSource);
|
var sendAttemptEv = new RadioSendAttemptEvent(channel, radioSource);
|
||||||
RaiseLocalEvent(ref sendAttemptEv);
|
RaiseLocalEvent(ref sendAttemptEv);
|
||||||
|
RaiseLocalEvent(radioSource, ref sendAttemptEv);
|
||||||
var canSend = !sendAttemptEv.Cancelled;
|
var canSend = !sendAttemptEv.Cancelled;
|
||||||
|
|
||||||
var sourceMapId = Transform(radioSource).MapID;
|
var sourceMapId = Transform(radioSource).MapID;
|
||||||
@@ -105,6 +106,7 @@ public sealed class RadioSystem : EntitySystem
|
|||||||
// check if message can be sent to specific receiver
|
// check if message can be sent to specific receiver
|
||||||
var attemptEv = new RadioReceiveAttemptEvent(channel, radioSource, receiver);
|
var attemptEv = new RadioReceiveAttemptEvent(channel, radioSource, receiver);
|
||||||
RaiseLocalEvent(ref attemptEv);
|
RaiseLocalEvent(ref attemptEv);
|
||||||
|
RaiseLocalEvent(receiver, ref attemptEv);
|
||||||
if (attemptEv.Cancelled)
|
if (attemptEv.Cancelled)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using Content.Server.DeviceNetwork;
|
using Content.Server.DeviceNetwork;
|
||||||
using Content.Server.DeviceNetwork.Components;
|
using Content.Server.DeviceNetwork.Components;
|
||||||
using Content.Server.DeviceNetwork.Systems;
|
using Content.Server.DeviceNetwork.Systems;
|
||||||
|
using Content.Server.Emp;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Shared.ActionBlocker;
|
using Content.Shared.ActionBlocker;
|
||||||
using Content.Shared.DeviceNetwork;
|
using Content.Shared.DeviceNetwork;
|
||||||
@@ -57,6 +58,9 @@ public sealed class SurveillanceCameraSystem : EntitySystem
|
|||||||
SubscribeLocalEvent<SurveillanceCameraComponent, SurveillanceCameraSetupSetName>(OnSetName);
|
SubscribeLocalEvent<SurveillanceCameraComponent, SurveillanceCameraSetupSetName>(OnSetName);
|
||||||
SubscribeLocalEvent<SurveillanceCameraComponent, SurveillanceCameraSetupSetNetwork>(OnSetNetwork);
|
SubscribeLocalEvent<SurveillanceCameraComponent, SurveillanceCameraSetupSetNetwork>(OnSetNetwork);
|
||||||
SubscribeLocalEvent<SurveillanceCameraComponent, GetVerbsEvent<AlternativeVerb>>(AddVerbs);
|
SubscribeLocalEvent<SurveillanceCameraComponent, GetVerbsEvent<AlternativeVerb>>(AddVerbs);
|
||||||
|
|
||||||
|
SubscribeLocalEvent<SurveillanceCameraComponent, EmpPulseEvent>(OnEmpPulse);
|
||||||
|
SubscribeLocalEvent<SurveillanceCameraComponent, EmpDisabledRemoved>(OnEmpDisabledRemoved);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void OnPacketReceived(EntityUid uid, SurveillanceCameraComponent component, DeviceNetworkPacketEvent args)
|
private void OnPacketReceived(EntityUid uid, SurveillanceCameraComponent component, DeviceNetworkPacketEvent args)
|
||||||
@@ -271,6 +275,10 @@ public sealed class SurveillanceCameraSystem : EntitySystem
|
|||||||
|
|
||||||
if (setting)
|
if (setting)
|
||||||
{
|
{
|
||||||
|
var attemptEv = new SurveillanceCameraSetActiveAttemptEvent();
|
||||||
|
RaiseLocalEvent(camera, ref attemptEv);
|
||||||
|
if (attemptEv.Cancelled)
|
||||||
|
return;
|
||||||
component.Active = setting;
|
component.Active = setting;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -392,6 +400,21 @@ public sealed class SurveillanceCameraSystem : EntitySystem
|
|||||||
|
|
||||||
_appearance.SetData(uid, SurveillanceCameraVisualsKey.Key, key, appearance);
|
_appearance.SetData(uid, SurveillanceCameraVisualsKey.Key, key, appearance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnEmpPulse(EntityUid uid, SurveillanceCameraComponent component, ref EmpPulseEvent args)
|
||||||
|
{
|
||||||
|
if (component.Active)
|
||||||
|
{
|
||||||
|
args.Affected = true;
|
||||||
|
args.Disabled = true;
|
||||||
|
SetActive(uid, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnEmpDisabledRemoved(EntityUid uid, SurveillanceCameraComponent component, ref EmpDisabledRemoved args)
|
||||||
|
{
|
||||||
|
SetActive(uid, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public sealed class OnSurveillanceCameraViewerAddEvent : EntityEventArgs
|
public sealed class OnSurveillanceCameraViewerAddEvent : EntityEventArgs
|
||||||
@@ -414,3 +437,6 @@ public sealed class SurveillanceCameraDeactivateEvent : EntityEventArgs
|
|||||||
Camera = camera;
|
Camera = camera;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[ByRefEvent]
|
||||||
|
public record struct SurveillanceCameraSetActiveAttemptEvent(bool Cancelled);
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Content.Server.Cargo.Systems;
|
using Content.Server.Cargo.Systems;
|
||||||
|
using Content.Server.Emp;
|
||||||
using Content.Server.Power.Components;
|
using Content.Server.Power.Components;
|
||||||
using Content.Server.Power.EntitySystems;
|
using Content.Server.Power.EntitySystems;
|
||||||
using Content.Server.UserInterface;
|
using Content.Server.UserInterface;
|
||||||
@@ -12,6 +13,7 @@ using Content.Shared.Destructible;
|
|||||||
using Content.Shared.DoAfter;
|
using Content.Shared.DoAfter;
|
||||||
using Content.Shared.Emag.Components;
|
using Content.Shared.Emag.Components;
|
||||||
using Content.Shared.Emag.Systems;
|
using Content.Shared.Emag.Systems;
|
||||||
|
using Content.Shared.Emp;
|
||||||
using Content.Shared.Popups;
|
using Content.Shared.Popups;
|
||||||
using Content.Shared.Throwing;
|
using Content.Shared.Throwing;
|
||||||
using Content.Shared.VendingMachines;
|
using Content.Shared.VendingMachines;
|
||||||
@@ -19,6 +21,7 @@ using Robust.Server.GameObjects;
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.Prototypes;
|
using Robust.Shared.Prototypes;
|
||||||
using Robust.Shared.Random;
|
using Robust.Shared.Random;
|
||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
namespace Content.Server.VendingMachines
|
namespace Content.Server.VendingMachines
|
||||||
{
|
{
|
||||||
@@ -31,6 +34,7 @@ namespace Content.Server.VendingMachines
|
|||||||
[Dependency] private readonly PricingSystem _pricing = default!;
|
[Dependency] private readonly PricingSystem _pricing = default!;
|
||||||
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
|
[Dependency] private readonly ThrowingSystem _throwingSystem = default!;
|
||||||
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
[Dependency] private readonly UserInterfaceSystem _userInterfaceSystem = default!;
|
||||||
|
[Dependency] private readonly IGameTiming _timing = default!;
|
||||||
|
|
||||||
private ISawmill _sawmill = default!;
|
private ISawmill _sawmill = default!;
|
||||||
|
|
||||||
@@ -44,6 +48,7 @@ namespace Content.Server.VendingMachines
|
|||||||
SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
|
SubscribeLocalEvent<VendingMachineComponent, GotEmaggedEvent>(OnEmagged);
|
||||||
SubscribeLocalEvent<VendingMachineComponent, DamageChangedEvent>(OnDamage);
|
SubscribeLocalEvent<VendingMachineComponent, DamageChangedEvent>(OnDamage);
|
||||||
SubscribeLocalEvent<VendingMachineComponent, PriceCalculationEvent>(OnVendingPrice);
|
SubscribeLocalEvent<VendingMachineComponent, PriceCalculationEvent>(OnVendingPrice);
|
||||||
|
SubscribeLocalEvent<VendingMachineComponent, EmpPulseEvent>(OnEmpPulse);
|
||||||
|
|
||||||
SubscribeLocalEvent<VendingMachineComponent, ActivatableUIOpenAttemptEvent>(OnActivatableUIOpenAttempt);
|
SubscribeLocalEvent<VendingMachineComponent, ActivatableUIOpenAttemptEvent>(OnActivatableUIOpenAttempt);
|
||||||
SubscribeLocalEvent<VendingMachineComponent, BoundUIOpenedEvent>(OnBoundUIOpened);
|
SubscribeLocalEvent<VendingMachineComponent, BoundUIOpenedEvent>(OnBoundUIOpened);
|
||||||
@@ -437,6 +442,15 @@ namespace Content.Server.VendingMachines
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var disabled = EntityQueryEnumerator<EmpDisabledComponent, VendingMachineComponent>();
|
||||||
|
while (disabled.MoveNext(out var uid, out _, out var comp))
|
||||||
|
{
|
||||||
|
if (comp.NextEmpEject < _timing.CurTime)
|
||||||
|
{
|
||||||
|
EjectRandom(uid, true, false, comp);
|
||||||
|
comp.NextEmpEject += TimeSpan.FromSeconds(5 * comp.EjectDelay);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TryRestockInventory(EntityUid uid, VendingMachineComponent? vendComponent = null)
|
public void TryRestockInventory(EntityUid uid, VendingMachineComponent? vendComponent = null)
|
||||||
@@ -473,5 +487,15 @@ namespace Content.Server.VendingMachines
|
|||||||
|
|
||||||
args.Price += priceSets.Max();
|
args.Price += priceSets.Max();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void OnEmpPulse(EntityUid uid, VendingMachineComponent component, ref EmpPulseEvent args)
|
||||||
|
{
|
||||||
|
if (!component.Broken && this.IsPowered(uid, EntityManager))
|
||||||
|
{
|
||||||
|
args.Affected = true;
|
||||||
|
args.Disabled = true;
|
||||||
|
component.NextEmpEject = _timing.CurTime;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,4 +14,7 @@ public sealed class EmpArtifactComponent : Component
|
|||||||
|
|
||||||
[DataField("energyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField("energyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float EnergyConsumption = 1000000;
|
public float EnergyConsumption = 1000000;
|
||||||
|
|
||||||
|
[DataField("disableDuration"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float DisableDuration = 60f;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,6 +16,6 @@ public sealed class EmpArtifactSystem : EntitySystem
|
|||||||
|
|
||||||
private void OnActivate(EntityUid uid, EmpArtifactComponent component, ArtifactActivatedEvent args)
|
private void OnActivate(EntityUid uid, EmpArtifactComponent component, ArtifactActivatedEvent args)
|
||||||
{
|
{
|
||||||
_emp.EmpPulse(Transform(uid).MapPosition, component.Range, component.EnergyConsumption);
|
_emp.EmpPulse(Transform(uid).MapPosition, component.Range, component.EnergyConsumption, component.DisableDuration);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -44,4 +44,10 @@ public sealed class ElectricityAnomalyComponent : Component
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
[DataField("empEnergyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
[DataField("empEnergyConsumption"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
public float EmpEnergyConsumption = 100000f;
|
public float EmpEnergyConsumption = 100000f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Duration of devices being disabled by the emp pulse upon going supercritical.
|
||||||
|
/// <summary>
|
||||||
|
[DataField("empDisabledDuration"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float EmpDisabledDuration = 60f;
|
||||||
}
|
}
|
||||||
|
|||||||
27
Content.Shared/Emp/EmpDisabledComponent.cs
Normal file
27
Content.Shared/Emp/EmpDisabledComponent.cs
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
using Robust.Shared.GameStates;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
|
|
||||||
|
namespace Content.Shared.Emp;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// While entity has this component it is "disabled" by EMP.
|
||||||
|
/// Add desired behaviour in other systems
|
||||||
|
/// </summary>
|
||||||
|
[RegisterComponent, NetworkedComponent]
|
||||||
|
[Access(typeof(SharedEmpSystem))]
|
||||||
|
public sealed class EmpDisabledComponent : Component
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Moment of time when component is removed and entity stops being "disabled"
|
||||||
|
/// </summary>
|
||||||
|
[DataField("timeLeft", customTypeSerializer: typeof(TimeOffsetSerializer)), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public TimeSpan DisabledUntil;
|
||||||
|
|
||||||
|
[DataField("effectCoolDown"), ViewVariables(VVAccess.ReadWrite)]
|
||||||
|
public float EffectCooldown = 3f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// When next effect will be spawned
|
||||||
|
/// </summary>
|
||||||
|
public TimeSpan TargetTime = TimeSpan.Zero;
|
||||||
|
}
|
||||||
10
Content.Shared/Emp/SharedEmpSystem.cs
Normal file
10
Content.Shared/Emp/SharedEmpSystem.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
using Robust.Shared.Timing;
|
||||||
|
|
||||||
|
namespace Content.Shared.Emp;
|
||||||
|
|
||||||
|
public abstract class SharedEmpSystem : EntitySystem
|
||||||
|
{
|
||||||
|
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||||
|
|
||||||
|
protected const string EmpDisabledEffectPrototype = "EffectEmpDisabled";
|
||||||
|
}
|
||||||
@@ -3,6 +3,7 @@ using Content.Shared.Actions.ActionTypes;
|
|||||||
using Robust.Shared.Audio;
|
using Robust.Shared.Audio;
|
||||||
using Robust.Shared.GameStates;
|
using Robust.Shared.GameStates;
|
||||||
using Robust.Shared.Serialization;
|
using Robust.Shared.Serialization;
|
||||||
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype;
|
||||||
|
|
||||||
namespace Content.Shared.VendingMachines
|
namespace Content.Shared.VendingMachines
|
||||||
@@ -115,6 +116,12 @@ namespace Content.Shared.VendingMachines
|
|||||||
public float DenyAccumulator = 0f;
|
public float DenyAccumulator = 0f;
|
||||||
public float DispenseOnHitAccumulator = 0f;
|
public float DispenseOnHitAccumulator = 0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// While disabled by EMP it randomly ejects items
|
||||||
|
/// </summary>
|
||||||
|
[DataField("nextEmpEject", customTypeSerializer: typeof(TimeOffsetSerializer))]
|
||||||
|
public TimeSpan NextEmpEject = TimeSpan.Zero;
|
||||||
|
|
||||||
#region Client Visuals
|
#region Client Visuals
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// RSI state for when the vending machine is unpowered.
|
/// RSI state for when the vending machine is unpowered.
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
apc-component-insufficient-access = Insufficient access!
|
apc-component-insufficient-access = Insufficient access!
|
||||||
apc-component-on-examine-panel-open = The [color=lightgray]APC electronics panel[/color] is [color=red]open[/color].
|
apc-component-on-examine-panel-open = The [color=lightgray]APC electronics panel[/color] is [color=red]open[/color].
|
||||||
apc-component-on-examine-panel-closed = The [color=lightgray]APC electronics panel[/color] is [color=darkgreen]closed[/color].
|
apc-component-on-examine-panel-closed = The [color=lightgray]APC electronics panel[/color] is [color=darkgreen]closed[/color].
|
||||||
|
apc-component-on-toggle-cancel = It does nothing!
|
||||||
|
|||||||
1
Resources/Locale/en-US/emp/emp.ftl
Normal file
1
Resources/Locale/en-US/emp/emp.ftl
Normal file
@@ -0,0 +1 @@
|
|||||||
|
emp-disabled-comp-on-examine = [color=lightblue]It's disrupted by an electric field... [/color]
|
||||||
Reference in New Issue
Block a user