Adds signal control to portable generators (#24157)
* 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>
This commit is contained in:
@@ -135,6 +135,14 @@ public sealed partial class GeneratorWindow : FancyWindow
|
|||||||
|
|
||||||
private bool TryGetStartProgress(out float progress)
|
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>();
|
var doAfterSystem = _entityManager.EntitySysManager.GetEntitySystem<DoAfterSystem>();
|
||||||
return doAfterSystem.TryFindActiveDoAfter<GeneratorStartedEvent>(_entity, out _, out _, out progress);
|
return doAfterSystem.TryFindActiveDoAfter<GeneratorStartedEvent>(_entity, out _, out _, out progress);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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";
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -27,6 +27,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
|||||||
[Dependency] private readonly IRobustRandom _random = default!;
|
[Dependency] private readonly IRobustRandom _random = default!;
|
||||||
[Dependency] private readonly GeneratorSystem _generator = default!;
|
[Dependency] private readonly GeneratorSystem _generator = default!;
|
||||||
[Dependency] private readonly PowerSwitchableSystem _switchable = default!;
|
[Dependency] private readonly PowerSwitchableSystem _switchable = default!;
|
||||||
|
[Dependency] private readonly ActiveGeneratorRevvingSystem _revving = default!;
|
||||||
[Dependency] private readonly PowerNetSystem _powerNet = default!;
|
[Dependency] private readonly PowerNetSystem _powerNet = default!;
|
||||||
|
|
||||||
public override void Initialize()
|
public override void Initialize()
|
||||||
@@ -38,7 +39,8 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
|||||||
UpdatesAfter.Add(typeof(PowerNetSystem));
|
UpdatesAfter.Add(typeof(PowerNetSystem));
|
||||||
|
|
||||||
SubscribeLocalEvent<PortableGeneratorComponent, GetVerbsEvent<AlternativeVerb>>(GetAlternativeVerb);
|
SubscribeLocalEvent<PortableGeneratorComponent, GetVerbsEvent<AlternativeVerb>>(GetAlternativeVerb);
|
||||||
SubscribeLocalEvent<PortableGeneratorComponent, GeneratorStartedEvent>(GeneratorTugged);
|
SubscribeLocalEvent<PortableGeneratorComponent, GeneratorStartedEvent>(OnGeneratorStarted);
|
||||||
|
SubscribeLocalEvent<PortableGeneratorComponent, AutoGeneratorStartedEvent>(OnAutoGeneratorStarted);
|
||||||
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStartMessage>(GeneratorStartMessage);
|
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStartMessage>(GeneratorStartMessage);
|
||||||
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStopMessage>(GeneratorStopMessage);
|
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorStopMessage>(GeneratorStopMessage);
|
||||||
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorSwitchOutputMessage>(GeneratorSwitchOutputMessage);
|
SubscribeLocalEvent<PortableGeneratorComponent, PortableGeneratorSwitchOutputMessage>(GeneratorSwitchOutputMessage);
|
||||||
@@ -92,9 +94,30 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
|||||||
_generator.SetFuelGeneratorOn(uid, false);
|
_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;
|
return;
|
||||||
|
|
||||||
var fuelGenerator = Comp<FuelGeneratorComponent>(uid);
|
var fuelGenerator = Comp<FuelGeneratorComponent>(uid);
|
||||||
@@ -107,14 +130,23 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
|||||||
|
|
||||||
if (!clogged && !empty && _random.Prob(component.StartChance))
|
if (!clogged && !empty && _random.Prob(component.StartChance))
|
||||||
{
|
{
|
||||||
_popup.PopupEntity(Loc.GetString("portable-generator-start-success"), uid, args.User);
|
|
||||||
_generator.SetFuelGeneratorOn(uid, true, fuelGenerator);
|
_generator.SetFuelGeneratorOn(uid, true, fuelGenerator);
|
||||||
|
|
||||||
|
if (user is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_popup.PopupEntity(Loc.GetString("portable-generator-start-success"), uid, user.Value);
|
||||||
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_popup.PopupEntity(Loc.GetString("portable-generator-start-fail"), uid, args.User);
|
// try again bozo
|
||||||
// Try again bozo
|
repeat = true;
|
||||||
args.Repeat = true;
|
|
||||||
|
if (user is null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_popup.PopupEntity(Loc.GetString("portable-generator-start-fail"), uid, user.Value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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;
|
||||||
|
}
|
||||||
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -23,3 +23,12 @@ public sealed partial class GeneratorStartedEvent : DoAfterEvent
|
|||||||
return this;
|
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;
|
||||||
|
}
|
||||||
|
|||||||
@@ -90,6 +90,17 @@
|
|||||||
supplyRampRate: 500
|
supplyRampRate: 500
|
||||||
supplyRampTolerance: 500
|
supplyRampTolerance: 500
|
||||||
enabled: false
|
enabled: false
|
||||||
|
- type: DeviceLinkSink
|
||||||
|
ports:
|
||||||
|
- On
|
||||||
|
- Off
|
||||||
|
- Toggle
|
||||||
|
- type: GeneratorSignalControl
|
||||||
|
- type: DeviceNetwork
|
||||||
|
deviceNetId: Wireless
|
||||||
|
receiveFrequencyId: BasicDevice
|
||||||
|
- type: WirelessNetworkConnection
|
||||||
|
range: 200
|
||||||
|
|
||||||
- type: entity
|
- type: entity
|
||||||
abstract: true
|
abstract: true
|
||||||
|
|||||||
Reference in New Issue
Block a user