diff --git a/Content.Server/_Forge/SolarFlareGenerator/Components/SolarFlareGeneratorComponent.cs b/Content.Server/_Forge/SolarFlareGenerator/Components/SolarFlareGeneratorComponent.cs new file mode 100644 index 000000000000..409b6b1caf5b --- /dev/null +++ b/Content.Server/_Forge/SolarFlareGenerator/Components/SolarFlareGeneratorComponent.cs @@ -0,0 +1,20 @@ +using Content.Server.Solar.EntitySystems; + +/// +/// Стационарное устройство, при активации которого на срок в 30-60 секунд в радиусе 100-150 происходит эффект "Солнечной вспышки" +/// +[RegisterComponent] +[Access(typeof(SolarFlareGeneratorSystem))] +public sealed partial class SolarFlareGeneratorComponent : Component +{ + [DataField] + public bool IsActive = false; + [DataField] + public bool IsReady = true; + [DataField] + public TimeSpan EffectTimer = TimeSpan.Zero; + [DataField] + public TimeSpan CooldownTimer = TimeSpan.Zero; + [DataField] + public float Radius; +} diff --git a/Content.Server/_Forge/SolarFlareGenerator/EntitySystems/SolarFlareGeneratorSystem.cs b/Content.Server/_Forge/SolarFlareGenerator/EntitySystems/SolarFlareGeneratorSystem.cs new file mode 100644 index 000000000000..a059958297df --- /dev/null +++ b/Content.Server/_Forge/SolarFlareGenerator/EntitySystems/SolarFlareGeneratorSystem.cs @@ -0,0 +1,156 @@ +using Content.Client; +using Content.Server.Bed.Components; +using Content.Server.Botany.Components; +using Content.Server.Power.EntitySystems; +using Content.Server.PowerCell; +using Content.Server.Radio; +using Content.Shared.Bed.Sleep; +using Content.Shared.Buckle.Components; +using Content.Shared.Damage; +using Content.Shared.DeviceNetwork.Components; +using Content.Shared.DeviceNetwork.Systems; +using Content.Shared.Interaction; +using Content.Shared.Mobs.Systems; +using Content.Shared.Popups; +using Content.Shared.PowerCell.Components; +using Content.Shared.Radio.Components; +using Content.Shared.Radio.EntitySystems; +using JetBrains.FormatRipper.Elf; +using Robust.Shared.GameObjects; +using Robust.Shared.Timing; +using System; +using System.ComponentModel; + + +namespace Content.Server.Solar.EntitySystems +{ + public sealed class SolarFlareGeneratorSystem : EntitySystem + { + [Dependency] private readonly PowerCellSystem _powerCell = default!; + [Dependency] private readonly BatterySystem _battery = default!; + [Dependency] private readonly SharedTransformSystem _transform = default!; + [Dependency] private readonly SharedDeviceNetworkJammerSystem _jammer = default!; + [Dependency] private readonly SharedJammerSystem _jammerSystem = default!; + [Dependency] private readonly IGameTiming _timing = default!; + [Dependency] protected readonly SharedPopupSystem Popup = default!; + private const float _cooldownTimerValue = 15; + private const float _effectTimer = 30; + public override void Initialize() + { + base.Initialize(); + + SubscribeLocalEvent(OnInteractHand); + SubscribeLocalEvent(OnRadioReceiveAttempt); + } + + public override void Update(float frameTime) + { + base.Update(frameTime); + + var frameTimeSpan = TimeSpan.FromSeconds(frameTime); + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var solarFlareComponent)) + { + if (solarFlareComponent.IsActive) + { + UpdateActiveGenerator(solarFlareComponent, frameTimeSpan); + } + else if (!solarFlareComponent.IsReady) + { + UpdateCooldown(solarFlareComponent, frameTimeSpan); + } + else + { + solarFlareComponent.EffectTimer = TimeSpan.Zero; + } + } + } + + private void UpdateActiveGenerator(SolarFlareGeneratorComponent component, TimeSpan frameTime) + { + // Обновление таймера эффекта + if (component.EffectTimer > TimeSpan.Zero) + { + component.EffectTimer -= frameTime; + + if (component.EffectTimer <= TimeSpan.Zero) + { + component.IsActive = false; + component.EffectTimer = TimeSpan.Zero; + } + } + + // Обновление кулдауна + UpdateCooldown(component, frameTime); + } + + private void UpdateCooldown(SolarFlareGeneratorComponent component, TimeSpan frameTime) + { + if (component.CooldownTimer > TimeSpan.Zero) + { + component.CooldownTimer -= frameTime; + } + else if (!component.IsReady) + { + component.IsReady = true; + component.CooldownTimer = TimeSpan.Zero; + } + } + + private void OnInteractHand(Entity entity, ref InteractHandEvent args) + { + if (args.Handled) + return; + + if (entity.Comp.IsReady) + { + var state = Loc.GetString("radio-jammer-component-on-state"); + var message = Loc.GetString("radio-jammer-component-on-use", ("state", state)); + Popup.PopupEntity(message, args.User, args.User); + OnActivate(entity, args); + } + + } + + private void OnActivate(Entity entity, InteractHandEvent args) + { + StartSolarFlareGenerator(entity.Comp); + args.Handled = true; + } + + private void StartSolarFlareGenerator(SolarFlareGeneratorComponent component) + { + component.IsActive = true; + component.IsReady = false; + component.CooldownTimer = TimeSpan.FromMinutes(_cooldownTimerValue); + component.EffectTimer = TimeSpan.FromSeconds(_effectTimer); + } + + private void OnRadioReceiveAttempt(ref RadioReceiveAttemptEvent args) + { + if (ShouldCancelReceive(args.RadioSource)) + { + args.Cancelled = true; + } + + } + + private bool ShouldCancelReceive(EntityUid sourceUid) + { + + var query = EntityQueryEnumerator(); + + while (query.MoveNext(out var uid, out var transform, out var solarFlareGeneratorComponent)) + { + var source = Transform(sourceUid).Coordinates; + if (_transform.InRange(source, transform.Coordinates, solarFlareGeneratorComponent.Radius) && solarFlareGeneratorComponent.IsActive) + { + return true; + } + } + + return false; + } + } +} diff --git a/Resources/Prototypes/_Forge/SolarFlareGenerator/solar_flare_generator.yml b/Resources/Prototypes/_Forge/SolarFlareGenerator/solar_flare_generator.yml new file mode 100644 index 000000000000..fad9f2fff5ad --- /dev/null +++ b/Resources/Prototypes/_Forge/SolarFlareGenerator/solar_flare_generator.yml @@ -0,0 +1,15 @@ +- type: entity + name: solar flare generator + parent: BaseItem + id: SolarFlareGenerator + description: We're going dark. + components: + - type: Sprite + sprite: Objects/Fun/bikehorn.rsi + state: icon + - type: Transform + anchored: true + - type: Physics + bodyType: Static + - type: SolarFlareGenerator + radius: 150