]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Add solar flare event (#13749)
authorSlava0135 <40753025+Slava0135@users.noreply.github.com>
Sat, 11 Feb 2023 20:24:29 +0000 (23:24 +0300)
committerGitHub <noreply@github.com>
Sat, 11 Feb 2023 20:24:29 +0000 (20:24 +0000)
* add solar flare event (only affects headsets)

* add popup

* cleaner impl using RadioReceiveAttemptEvent

* unused import

* handheld radio and intercom work again

* Revert "handheld radio and intercom work again"

This reverts commit 0032e3c0725a19a465daf1ff1d6b4942a5c14fbb.

* add radio source to Radio events

* intercoms and handheld radios work now

* use Elapsed instead of new field

* add configuration

* better not touch Elapsed

* the

* make popup bigger

* xml comments for configuration

* very minor refactoring

* default config is now in yaml

* lights can break

* use RobustRandom

* use file namespace

* use RuleStarted

* store config in field

* a

---------

Co-authored-by: AJCM <AJCM@tutanota.com>
Content.Server/GameTicking/Rules/Configurations/SolarFlareEventRuleConfiguration.cs [new file with mode: 0644]
Content.Server/GameTicking/Rules/Configurations/StationEventRuleConfiguration.cs
Content.Server/Radio/EntitySystems/HeadsetSystem.cs
Content.Server/Radio/EntitySystems/RadioDeviceSystem.cs
Content.Server/Radio/EntitySystems/RadioSystem.cs
Content.Server/Radio/RadioReceiveEvent.cs
Content.Server/StationEvents/Events/SolarFlare.cs [new file with mode: 0644]
Resources/Locale/en-US/radio/radio-event.ftl [new file with mode: 0644]
Resources/Locale/en-US/station-events/events/solar-flare.ftl [new file with mode: 0644]
Resources/Prototypes/GameRules/events.yml

diff --git a/Content.Server/GameTicking/Rules/Configurations/SolarFlareEventRuleConfiguration.cs b/Content.Server/GameTicking/Rules/Configurations/SolarFlareEventRuleConfiguration.cs
new file mode 100644 (file)
index 0000000..7c1d1e3
--- /dev/null
@@ -0,0 +1,40 @@
+using Content.Shared.Radio;
+using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set;
+
+namespace Content.Server.GameTicking.Rules.Configurations;
+
+/// <summary>
+///     Solar Flare event specific configuration
+/// </summary>
+public sealed class SolarFlareEventRuleConfiguration : StationEventRuleConfiguration
+{
+    /// <summary>
+    ///     In seconds, most early moment event can end
+    /// </summary>
+    [DataField("minEndAfter")]
+    public int MinEndAfter;
+
+    /// <summary>
+    ///     In seconds, most late moment event can end
+    /// </summary>
+    [DataField("maxEndAfter")]
+    public int MaxEndAfter;
+
+    /// <summary>
+    ///     If true, only headsets affected, but e.g. handheld radio will still work
+    /// </summary>
+    [DataField("onlyJamHeadsets")]
+    public bool OnlyJamHeadsets;
+
+    /// <summary>
+    ///     Channels that will be disabled for a duration of event
+    /// </summary>
+    [DataField("affectedChannels", customTypeSerializer: typeof(PrototypeIdHashSetSerializer<RadioChannelPrototype>))]
+    public readonly HashSet<string> AffectedChannels = new();
+
+    /// <summary>
+    ///     Chance any given light bulb breaks due to event
+    /// </summary>
+    [DataField("lightBreakChance")]
+    public float LightBreakChance;
+}
\ No newline at end of file
index 5fa0b28fe0c5ca2c1dd49b033746f858d5069b2f..84689dc225962c9f25730c715a56ac935ef8960e 100644 (file)
@@ -8,7 +8,7 @@ namespace Content.Server.GameTicking.Rules.Configurations;
 ///     game rules.
 /// </summary>
 [UsedImplicitly]
-public sealed class StationEventRuleConfiguration : GameRuleConfiguration
+public class StationEventRuleConfiguration : GameRuleConfiguration
 {
     [DataField("id", required: true)]
     private string _id = default!;
index de1fd663382419f5875da6dda24c3c9d7e554641..2a66f985d3e846a3030f6d7d9ea7aa0bb42c1c44 100644 (file)
@@ -45,7 +45,7 @@ public sealed class HeadsetSystem : EntitySystem
             && TryComp(component.Headset, out HeadsetComponent? headset)
             && headset.Channels.Contains(args.Channel.ID))
         {
-            _radio.SendRadioMessage(uid, args.Message, args.Channel);
+            _radio.SendRadioMessage(uid, args.Message, args.Channel, component.Headset);
             args.Channel = null; // prevent duplicate messages from other listeners.
         }
     }
index b98e1427aa2ed293834b35f93f91a7a1b943c08f..fc2d89ddbb08c9634acc738fa857389cca824464 100644 (file)
@@ -194,7 +194,7 @@ public sealed class RadioDeviceSystem : EntitySystem
             return; // no feedback loops please.
 
         if (_recentlySent.Add((args.Message, args.Source)))
-            _radio.SendRadioMessage(args.Source, args.Message, _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel));
+            _radio.SendRadioMessage(args.Source, args.Message, _protoMan.Index<RadioChannelPrototype>(component.BroadcastChannel), uid);
     }
 
     private void OnAttemptListen(EntityUid uid, RadioMicrophoneComponent component, ListenAttemptEvent args)
index de6131bb9ddcee8469e1939ae4c1310400196ec3..e85014f1d9f1dfbad639c16d2397281e632fc66a 100644 (file)
@@ -2,6 +2,7 @@ using Content.Server.Administration.Logs;
 using Content.Server.Chat.Systems;
 using Content.Server.Radio.Components;
 using Content.Server.VoiceMask;
+using Content.Server.Popups;
 using Content.Shared.Chat;
 using Content.Shared.Database;
 using Content.Shared.Radio;
@@ -9,6 +10,7 @@ using Robust.Server.GameObjects;
 using Robust.Shared.Network;
 using Robust.Shared.Replays;
 using Robust.Shared.Utility;
+using Content.Shared.Popups;
 
 namespace Content.Server.Radio.EntitySystems;
 
@@ -20,6 +22,7 @@ public sealed class RadioSystem : EntitySystem
     [Dependency] private readonly INetManager _netMan = default!;
     [Dependency] private readonly IReplayRecordingManager _replay = default!;
     [Dependency] private readonly IAdminLogManager _adminLogger = default!;
+    [Dependency] private readonly PopupSystem _popupSystem = default!;
 
     // set used to prevent radio feedback loops.
     private readonly HashSet<string> _messages = new();
@@ -46,7 +49,7 @@ public sealed class RadioSystem : EntitySystem
             _netMan.ServerSendMessage(args.ChatMsg, actor.PlayerSession.ConnectedClient);
     }
 
-    public void SendRadioMessage(EntityUid source, string message, RadioChannelPrototype channel)
+    public void SendRadioMessage(EntityUid source, string message, RadioChannelPrototype channel, EntityUid? radioSource = null)
     {
         // TODO if radios ever garble / modify messages, feedback-prevention needs to be handled better than this.
         if (!_messages.Add(message))
@@ -66,8 +69,9 @@ public sealed class RadioSystem : EntitySystem
             EntityUid.Invalid);
         var chatMsg = new MsgChatMessage { Message = chat };
 
-        var ev = new RadioReceiveEvent(message, source, channel, chatMsg);
-        var attemptEv = new RadioReceiveAttemptEvent(message, source, channel);
+        var ev = new RadioReceiveEvent(message, source, channel, chatMsg, radioSource);
+        var attemptEv = new RadioReceiveAttemptEvent(message, source, channel, radioSource);
+        bool sentAtLeastOnce = false;
 
         foreach (var radio in EntityQuery<ActiveRadioComponent>())
         {
@@ -82,9 +86,11 @@ public sealed class RadioSystem : EntitySystem
                 attemptEv.Uncancel();
                 continue;
             }
-
+            sentAtLeastOnce = true;
             RaiseLocalEvent(radio.Owner, ev);
         }
+        if (!sentAtLeastOnce)
+            _popupSystem.PopupEntity(Loc.GetString("failed-to-send-message"), source, PopupType.MediumCaution);
 
         if (name != Name(source))
             _adminLogger.Add(LogType.Chat, LogImpact.Low, $"Radio message from {ToPrettyString(source):user} as {name} on {channel.LocalizedName}: {message}");
index f1b4e3d6cd754d643591ce69e67e3bb2c51b699e..f8d8240b8d27f131a7538f4b76ea7f43e5503c93 100644 (file)
@@ -9,13 +9,15 @@ public sealed class RadioReceiveEvent : EntityEventArgs
     public readonly EntityUid Source;
     public readonly RadioChannelPrototype Channel;
     public readonly MsgChatMessage ChatMsg;
+    public readonly EntityUid? RadioSource;
 
-    public RadioReceiveEvent(string message, EntityUid source, RadioChannelPrototype channel, MsgChatMessage chatMsg)
+    public RadioReceiveEvent(string message, EntityUid source, RadioChannelPrototype channel, MsgChatMessage chatMsg, EntityUid? radioSource)
     {
         Message = message;
         Source = source;
         Channel = channel;
         ChatMsg = chatMsg;
+        RadioSource = radioSource;
     }
 }
 
@@ -24,11 +26,13 @@ public sealed class RadioReceiveAttemptEvent : CancellableEntityEventArgs
     public readonly string Message;
     public readonly EntityUid Source;
     public readonly RadioChannelPrototype Channel;
+    public readonly EntityUid? RadioSource;
 
-    public RadioReceiveAttemptEvent(string message, EntityUid source, RadioChannelPrototype channel)
+    public RadioReceiveAttemptEvent(string message, EntityUid source, RadioChannelPrototype channel, EntityUid? radioSource)
     {
         Message = message;
         Source = source;
         Channel = channel;
+        RadioSource = radioSource;
     }
 }
diff --git a/Content.Server/StationEvents/Events/SolarFlare.cs b/Content.Server/StationEvents/Events/SolarFlare.cs
new file mode 100644 (file)
index 0000000..2b4d6d1
--- /dev/null
@@ -0,0 +1,73 @@
+using Content.Server.GameTicking.Rules.Configurations;
+using Content.Server.Radio.Components;
+using Content.Server.Radio;
+using Robust.Shared.Random;
+using Content.Server.Light.EntitySystems;
+using Content.Server.Light.Components;
+
+namespace Content.Server.StationEvents.Events;
+
+public sealed class SolarFlare : StationEventSystem
+{
+    [Dependency] private readonly PoweredLightSystem _poweredLight = default!;
+
+    public override string Prototype => "SolarFlare";
+
+    private SolarFlareEventRuleConfiguration _event = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<ActiveRadioComponent, RadioReceiveAttemptEvent>(OnRadioSendAttempt);
+    }
+
+    public override void Added()
+    {
+        base.Added();
+
+        if (Configuration is not SolarFlareEventRuleConfiguration ev)
+            return;
+
+        _event = ev;
+        _event.EndAfter = RobustRandom.Next(ev.MinEndAfter, ev.MaxEndAfter);
+    }
+
+    public override void Started()
+    {
+        base.Started();
+        MessLights();
+    }
+
+    private void MessLights()
+    {
+        foreach (var comp in EntityQuery<PoweredLightComponent>())
+        {
+            if (RobustRandom.Prob(_event.LightBreakChance))
+            {
+                var uid = comp.Owner;
+                _poweredLight.TryDestroyBulb(uid, comp);
+            }
+        }
+    }
+
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+
+        if (!RuleStarted)
+            return;
+
+        if (Elapsed > _event.EndAfter)
+        {
+            ForceEndSelf();
+            return;
+        }
+    }
+
+    private void OnRadioSendAttempt(EntityUid uid, ActiveRadioComponent component, RadioReceiveAttemptEvent args)
+    {
+        if (RuleStarted && _event.AffectedChannels.Contains(args.Channel.ID))
+            if (!_event.OnlyJamHeadsets || (HasComp<HeadsetComponent>(uid) || HasComp<HeadsetComponent>(args.RadioSource)))
+                args.Cancel();
+    }
+}
diff --git a/Resources/Locale/en-US/radio/radio-event.ftl b/Resources/Locale/en-US/radio/radio-event.ftl
new file mode 100644 (file)
index 0000000..63c264b
--- /dev/null
@@ -0,0 +1 @@
+failed-to-send-message = Failed to send message!
diff --git a/Resources/Locale/en-US/station-events/events/solar-flare.ftl b/Resources/Locale/en-US/station-events/events/solar-flare.ftl
new file mode 100644 (file)
index 0000000..5c88f82
--- /dev/null
@@ -0,0 +1,2 @@
+station-event-solar-flare-start-announcement = A solar flare has been detected near the station. Some communication channels may not function.
+station-event-solar-flare-end-announcement = The solar flare ended. Communication channels no longer affected.
index 2597006dfaf288cbe939ef705da04ef208c89525..9986cedd9bc3f1046960b965aa9e8d9b96df89aa 100644 (file)
     startAudio:
       path: /Audio/Announcements/attention.ogg
 
+- type: gameRule
+  id: SolarFlare
+  config: !type:SolarFlareEventRuleConfiguration
+    id: SolarFlare
+    weight: 10
+    startAnnouncement: station-event-solar-flare-start-announcement
+    endAnnouncement: station-event-solar-flare-end-announcement
+    startAudio:
+      path: /Audio/Announcements/attention.ogg
+    minEndAfter: 120
+    maxEndAfter: 240
+    onlyJamHeadsets: true
+    affectedChannels:
+    - Common
+    - Service
+    lightBreakChance: 0.05
+
 - type: gameRule
   id: VentClog
   config:
     earliestStart: 20
     minimumPlayers: 15
     weight: 5
-    endAfter: 60    
+    endAfter: 60
 
 - type: gameRule
   id: ZombieOutbreak