]> git.smokeofanarchy.ru Git - space-station-14.git/commitdiff
Adds signal control to portable generators (#24157)
authorSpeltIncorrectyl <66873282+SpeltIncorrectyl@users.noreply.github.com>
Mon, 29 Jan 2024 14:56:29 +0000 (14:56 +0000)
committerGitHub <noreply@github.com>
Mon, 29 Jan 2024 14:56:29 +0000 (15:56 +0100)
* added signal control to portable generators

* added documentation

* Discard changes to Content.Server/Radio/EntitySystems/HeadsetSystem.cs

* added DeviceNetworkComponent and WirelessNetworkConnectionComponent to generator prototype

* made GeneratorSignalControlComponent nicer

* implemented auto-revving

* added back necessary dependency

* can't send do-after event manually

* repeat now works with auto revving

* fixed

* removed vv

* stopping generating when it is revving now makes it stop revving

* Update Content.Shared/Power/Generator/ActiveGeneratorRevvingComponent.cs

Co-authored-by: Kara <lunarautomaton6@gmail.com>
* used resolve instead of TryComp

---------

Co-authored-by: Julian Giebel <juliangiebel@live.de>
Co-authored-by: Kara <lunarautomaton6@gmail.com>
Content.Client/Power/Generator/GeneratorWindow.xaml.cs
Content.Server/Power/Generator/GeneratorSignalControlComponent.cs [new file with mode: 0644]
Content.Server/Power/Generator/GeneratorSignalControlSystem.cs [new file with mode: 0644]
Content.Server/Power/Generator/PortableGeneratorSystem.cs
Content.Shared/Power/Generator/ActiveGeneratorRevvingComponent.cs [new file with mode: 0644]
Content.Shared/Power/Generator/ActiveGeneratorRevvingSystem.cs [new file with mode: 0644]
Content.Shared/Power/Generator/SharedPortableGeneratorSystem.cs
Resources/Prototypes/Entities/Structures/Power/Generation/portable_generator.yml

index d1c5f47b07bedaa23ac168f819e453bfb2fa826b..bd5b75de1dadddf89f3f0da52c83d0987c5aca38 100644 (file)
@@ -135,6 +135,14 @@ public sealed partial class GeneratorWindow : FancyWindow
 
     private bool TryGetStartProgress(out float progress)
     {
+        // Try to check progress of auto-revving first
+        if (_entityManager.TryGetComponent<ActiveGeneratorRevvingComponent>(_entity, out var activeGeneratorRevvingComponent) && _entityManager.TryGetComponent<PortableGeneratorComponent>(_entity, out var portableGeneratorComponent))
+        {
+            var calculatedProgress = activeGeneratorRevvingComponent.CurrentTime / portableGeneratorComponent.StartTime;
+            progress = (float) calculatedProgress;
+            return true;
+        }
+
         var doAfterSystem = _entityManager.EntitySysManager.GetEntitySystem<DoAfterSystem>();
         return doAfterSystem.TryFindActiveDoAfter<GeneratorStartedEvent>(_entity, out _, out _, out progress);
     }
diff --git a/Content.Server/Power/Generator/GeneratorSignalControlComponent.cs b/Content.Server/Power/Generator/GeneratorSignalControlComponent.cs
new file mode 100644 (file)
index 0000000..f16a09e
--- /dev/null
@@ -0,0 +1,29 @@
+using Content.Shared.DeviceLinking;
+using Robust.Shared.Prototypes;
+
+namespace Content.Server.Power.Generator;
+
+/// <summary>
+/// When attached to an entity with <see cref="FuelGeneratorComponent"/> it will allow the signal network to exert control over the generator.
+/// </summary>
+[RegisterComponent]
+public sealed partial class GeneratorSignalControlComponent: Component
+{
+    /// <summary>
+    /// The port that should be invoked when turning the generator on.
+    /// </summary>
+    [DataField]
+    public ProtoId<SinkPortPrototype> OnPort = "On";
+
+    /// <summary>
+    /// The port that should be invoked when turning the generator off.
+    /// </summary>
+    [DataField]
+    public ProtoId<SinkPortPrototype> OffPort = "Off";
+
+    /// <summary>
+    /// The port that should be invoked when toggling the generator.
+    /// </summary>
+    [DataField]
+    public ProtoId<SinkPortPrototype> TogglePort = "Toggle";
+}
diff --git a/Content.Server/Power/Generator/GeneratorSignalControlSystem.cs b/Content.Server/Power/Generator/GeneratorSignalControlSystem.cs
new file mode 100644 (file)
index 0000000..4a42bcf
--- /dev/null
@@ -0,0 +1,48 @@
+using System.ComponentModel;
+using Content.Server.DeviceLinking.Events;
+using Content.Shared.Power.Generator;
+
+namespace Content.Server.Power.Generator;
+
+public sealed class GeneratorSignalControlSystem: EntitySystem
+{
+    [Dependency] private readonly GeneratorSystem _generator = default!;
+    [Dependency] private readonly ActiveGeneratorRevvingSystem _revving = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<GeneratorSignalControlComponent, SignalReceivedEvent>(OnSignalReceived);
+    }
+
+    /// <summary>
+    /// Change the state of the generator depending on what signal is sent.
+    /// </summary>
+    private void OnSignalReceived(EntityUid uid, GeneratorSignalControlComponent component, SignalReceivedEvent args)
+    {
+        if (!TryComp<FuelGeneratorComponent>(uid, out var generator))
+            return;
+
+        if (args.Port == component.OnPort)
+        {
+            _revving.StartAutoRevving(uid);
+        }
+        else if (args.Port == component.OffPort)
+        {
+            _generator.SetFuelGeneratorOn(uid, false, generator);
+            _revving.StopAutoRevving(uid);
+        }
+        else if (args.Port == component.TogglePort)
+        {
+            if (generator.On)
+            {
+                _generator.SetFuelGeneratorOn(uid, false, generator);
+                _revving.StopAutoRevving(uid);
+            }
+            else
+            {
+                _revving.StartAutoRevving(uid);
+            }
+        }
+    }
+}
index 96016da5b09610606c77cbd0d873f73403166c95..e8e9c5b45e3cd5ad51798ed4a78c6801e1a81f3f 100644 (file)
@@ -27,6 +27,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
     [Dependency] private readonly IRobustRandom _random = default!;
     [Dependency] private readonly GeneratorSystem _generator = default!;
     [Dependency] private readonly PowerSwitchableSystem _switchable = default!;
+    [Dependency] private readonly ActiveGeneratorRevvingSystem _revving = default!;
     [Dependency] private readonly PowerNetSystem _powerNet = default!;
 
     public override void Initialize()
@@ -38,7 +39,8 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
         UpdatesAfter.Add(typeof(PowerNetSystem));
 
         SubscribeLocalEvent<PortableGeneratorComponent, GetVerbsEvent<AlternativeVerb>>(GetAlternativeVerb);
-        SubscribeLocalEvent<PortableGeneratorComponent, GeneratorStartedEvent>(GeneratorTugged);
+        SubscribeLocalEvent<PortableGeneratorComponent, GeneratorStartedEvent>(OnGeneratorStarted);
+        SubscribeLocalEvent<PortableGeneratorComponent, AutoGeneratorStartedEvent>(OnAutoGeneratorStarted);
         SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStartMessage>(GeneratorStartMessage);
         SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStopMessage>(GeneratorStopMessage);
         SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorSwitchOutputMessage>(GeneratorSwitchOutputMessage);
@@ -92,9 +94,30 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
         _generator.SetFuelGeneratorOn(uid, false);
     }
 
-    private void GeneratorTugged(EntityUid uid, PortableGeneratorComponent component, GeneratorStartedEvent args)
+    private void OnGeneratorStarted(EntityUid uid, PortableGeneratorComponent component, GeneratorStartedEvent args)
     {
-        if (args.Cancelled || !Transform(uid).Anchored)
+        if (args.Cancelled)
+            return;
+
+        GeneratorTugged(uid, component, args.User, out args.Repeat);
+    }
+
+    private void OnAutoGeneratorStarted(EntityUid uid, PortableGeneratorComponent component, ref AutoGeneratorStartedEvent args)
+    {
+        GeneratorTugged(uid, component, null, out var repeat);
+
+        // restart the auto rev if it should be repeated
+        if (repeat)
+            _revving.StartAutoRevving(uid);
+        else
+            args.Started = true;
+    }
+
+    private void GeneratorTugged(EntityUid uid, PortableGeneratorComponent component, EntityUid? user, out bool repeat)
+    {
+        repeat = false;
+
+        if (!Transform(uid).Anchored)
             return;
 
         var fuelGenerator = Comp<FuelGeneratorComponent>(uid);
@@ -107,14 +130,23 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
 
         if (!clogged && !empty && _random.Prob(component.StartChance))
         {
-            _popup.PopupEntity(Loc.GetString("portable-generator-start-success"), uid, args.User);
             _generator.SetFuelGeneratorOn(uid, true, fuelGenerator);
+
+            if (user is null)
+                return;
+
+            _popup.PopupEntity(Loc.GetString("portable-generator-start-success"), uid, user.Value);
+
         }
         else
         {
-            _popup.PopupEntity(Loc.GetString("portable-generator-start-fail"), uid, args.User);
-            // Try again bozo
-            args.Repeat = true;
+            // try again bozo
+            repeat = true;
+
+            if (user is null)
+                return;
+
+            _popup.PopupEntity(Loc.GetString("portable-generator-start-fail"), uid, user.Value);
         }
     }
 
diff --git a/Content.Shared/Power/Generator/ActiveGeneratorRevvingComponent.cs b/Content.Shared/Power/Generator/ActiveGeneratorRevvingComponent.cs
new file mode 100644 (file)
index 0000000..25f97dc
--- /dev/null
@@ -0,0 +1,10 @@
+using Robust.Shared.GameStates;
+
+namespace Content.Shared.Power.Generator;
+
+[RegisterComponent, NetworkedComponent, AutoGenerateComponentState]
+public sealed partial class ActiveGeneratorRevvingComponent: Component
+{
+    [DataField, ViewVariables(VVAccess.ReadOnly), AutoNetworkedField]
+    public TimeSpan CurrentTime = TimeSpan.Zero;
+}
diff --git a/Content.Shared/Power/Generator/ActiveGeneratorRevvingSystem.cs b/Content.Shared/Power/Generator/ActiveGeneratorRevvingSystem.cs
new file mode 100644 (file)
index 0000000..1c39997
--- /dev/null
@@ -0,0 +1,86 @@
+using Content.Shared.DoAfter;
+
+namespace Content.Shared.Power.Generator;
+
+public sealed class ActiveGeneratorRevvingSystem: EntitySystem
+{
+    [Dependency] private readonly SharedDoAfterSystem _doAfter = default!;
+    [Dependency] private readonly EntityManager _entity = default!;
+
+    public override void Initialize()
+    {
+        base.Initialize();
+        SubscribeLocalEvent<ActiveGeneratorRevvingComponent, AnchorStateChangedEvent>(OnAnchorStateChanged);
+    }
+
+    /// <summary>
+    /// Handles the AnchorStateChangedEvent to stop auto-revving when unanchored.
+    /// </summary>
+    private void OnAnchorStateChanged(EntityUid uid, ActiveGeneratorRevvingComponent component, AnchorStateChangedEvent args)
+    {
+        if (!args.Anchored)
+            StopAutoRevving(uid);
+    }
+
+    /// <summary>
+    /// Start revving a generator entity automatically, without another entity doing a do-after.
+    /// Used for remotely activating a generator.
+    /// </summary>
+    /// <param name="uid">Uid of the generator entity.</param>
+    /// <param name="component">ActiveGeneratorRevvingComponent of the generator entity.</param>
+    public void StartAutoRevving(EntityUid uid, ActiveGeneratorRevvingComponent? component = null)
+    {
+        if (Resolve(uid, ref component))
+        {
+            // reset the revving
+            component.CurrentTime = TimeSpan.FromSeconds(0);
+            return;
+        }
+
+        AddComp(uid, new ActiveGeneratorRevvingComponent());
+    }
+
+    /// <summary>
+    /// Stop revving a generator entity.
+    /// </summary>
+    /// <param name="uid">Uid of the generator entity.</param>
+    /// <returns>True if the auto-revving was cancelled, false if it was never revving in the first place.</returns>
+    public bool StopAutoRevving(EntityUid uid)
+    {
+        return RemComp<ActiveGeneratorRevvingComponent>(uid);
+    }
+
+    /// <summary>
+    /// Raise an event on a generator entity to start it.
+    /// </summary>
+    /// <remarks>This is not the same as revving it, when this is called the generator will start producing power.</remarks>
+    /// <param name="uid">Uid of the generator entity.</param>
+    /// <returns>True if the generator was successfully started, false otherwise.</returns>
+    private bool StartGenerator(EntityUid uid)
+    {
+        var ev = new AutoGeneratorStartedEvent();
+        RaiseLocalEvent(uid, ref ev);
+        return ev.Started;
+    }
+
+    /// <summary>
+    /// Updates the timers on ActiveGeneratorRevvingComponent(s), and stops them when they are finished.
+    /// </summary>
+    public override void Update(float frameTime)
+    {
+        base.Update(frameTime);
+        var query = EntityQueryEnumerator<ActiveGeneratorRevvingComponent, PortableGeneratorComponent>();
+
+        while (query.MoveNext(out var uid, out var activeGeneratorRevvingComponent, out var portableGeneratorComponent))
+        {
+            activeGeneratorRevvingComponent.CurrentTime += TimeSpan.FromSeconds(frameTime);
+            Dirty(uid, activeGeneratorRevvingComponent);
+
+            if (activeGeneratorRevvingComponent.CurrentTime < portableGeneratorComponent.StartTime)
+                continue;
+
+            if (StartGenerator(uid))
+                StopAutoRevving(uid);
+        }
+    }
+}
index e30c8eced6a96bc6a0f38bb53cc46383cf00d777..e8ccc8516690c395958b4b084168fc549cb39a83 100644 (file)
@@ -23,3 +23,12 @@ public sealed partial class GeneratorStartedEvent : DoAfterEvent
         return this;
     }
 }
+
+/// <summary>
+/// Used to start a portable generator. This is like <see cref="GeneratorStartedEvent"/> except it isn't a do-after.
+/// </summary>
+[ByRefEvent]
+public sealed partial class AutoGeneratorStartedEvent
+{
+    public bool Started = false;
+}
index 2fc6c1f5120760b2a8e132bc15f7bf455ac9d912..b606c01f1ddce3988b46b33dfd30c6a9204f77ab 100644 (file)
       supplyRampRate: 500
       supplyRampTolerance: 500
       enabled: false
+    - type: DeviceLinkSink
+      ports:
+      - On
+      - Off
+      - Toggle
+    - type: GeneratorSignalControl
+    - type: DeviceNetwork
+      deviceNetId: Wireless
+      receiveFrequencyId: BasicDevice
+    - type: WirelessNetworkConnection
+      range: 200
 
 - type: entity
   abstract: true