Make PACMANs a little better (#24604)
* PACMAN generators show network load/supply. This gives more feedback to players that their PACMAN is properly connected and what the network status is (i.e. you don't have enough generators). * Buff JRPACMAN to 8 kW. Shifted all power values up by +3 kW. They're frequently too weak to power even single rooms so they deserve a buff. * Change unit format helpers number format. Always displays one digit of precision. This avoids jumping around when a value is changing live.
This commit is contained in:
committed by
GitHub
parent
41c0efeaf1
commit
f855cb2b00
@@ -1,8 +1,8 @@
|
||||
<controls:FancyWindow xmlns="https://spacestation14.io"
|
||||
xmlns:cc="clr-namespace:Content.Client.Administration.UI.CustomControls"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
MinSize="450 235"
|
||||
SetSize="450 235"
|
||||
MinSize="450 250"
|
||||
SetSize="450 250"
|
||||
Resizable="False"
|
||||
Title="{Loc 'portable-generator-ui-title'}">
|
||||
<BoxContainer Margin="4 0" Orientation="Horizontal">
|
||||
@@ -32,6 +32,11 @@
|
||||
</BoxContainer>
|
||||
<Label Name="OutputSwitchLabel" Text="{Loc 'portable-generator-ui-switch'}" Visible="False" />
|
||||
<Button Name="OutputSwitchButton" Visible="False" />
|
||||
<!-- Network stats menu -->
|
||||
<Label Text="{Loc 'portable-generator-ui-network-stats'}"/>
|
||||
<Control>
|
||||
<Label Name="NetworkStats" />
|
||||
</Control>
|
||||
</GridContainer>
|
||||
<Label Margin="2 0 0 0" Name="CloggedLabel" FontColorOverride="Red" Text="{Loc 'portable-generator-ui-clogged'}" />
|
||||
</BoxContainer>
|
||||
|
||||
@@ -115,6 +115,22 @@ public sealed partial class GeneratorWindow : FancyWindow
|
||||
}
|
||||
|
||||
CloggedLabel.Visible = state.Clogged;
|
||||
|
||||
if (state.NetworkStats is { } netStats)
|
||||
{
|
||||
NetworkStats.Text = Loc.GetString(
|
||||
"portable-generator-ui-network-stats-value",
|
||||
("load", netStats.Load),
|
||||
("supply", netStats.Supply));
|
||||
|
||||
var good = netStats.Load <= netStats.Supply;
|
||||
NetworkStats.SetOnlyStyleClass(good ? "Good" : "Caution");
|
||||
}
|
||||
else
|
||||
{
|
||||
NetworkStats.Text = Loc.GetString("portable-generator-ui-network-stats-not-connected");
|
||||
NetworkStats.StyleClasses.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
private bool TryGetStartProgress(out float progress)
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
using Content.Server.DoAfter;
|
||||
using Content.Server.NodeContainer.NodeGroups;
|
||||
using Content.Server.Popups;
|
||||
using Content.Server.Power.Components;
|
||||
using Content.Server.Power.EntitySystems;
|
||||
using Content.Shared.DoAfter;
|
||||
using Content.Shared.Power.Generator;
|
||||
using Content.Shared.Verbs;
|
||||
@@ -24,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 PowerNetSystem _powerNet = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -31,6 +35,7 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
||||
|
||||
// Update UI after main system runs.
|
||||
UpdatesAfter.Add(typeof(GeneratorSystem));
|
||||
UpdatesAfter.Add(typeof(PowerNetSystem));
|
||||
|
||||
SubscribeLocalEvent<PortableGeneratorComponent, GetVerbsEvent<AlternativeVerb>>(GetAlternativeVerb);
|
||||
SubscribeLocalEvent<PortableGeneratorComponent, GeneratorStartedEvent>(GeneratorTugged);
|
||||
@@ -175,15 +180,19 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
var query = EntityQueryEnumerator<PortableGeneratorComponent, FuelGeneratorComponent, AppearanceComponent>();
|
||||
var query = EntityQueryEnumerator<PortableGeneratorComponent, FuelGeneratorComponent, PowerSupplierComponent>();
|
||||
|
||||
while (query.MoveNext(out var uid, out var portGen, out var fuelGen, out var xform))
|
||||
while (query.MoveNext(out var uid, out var portGen, out var fuelGen, out var powerSupplier))
|
||||
{
|
||||
UpdateUI(uid, portGen, fuelGen);
|
||||
UpdateUI(uid, portGen, fuelGen, powerSupplier);
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateUI(EntityUid uid, PortableGeneratorComponent comp, FuelGeneratorComponent fuelComp)
|
||||
private void UpdateUI(
|
||||
EntityUid uid,
|
||||
PortableGeneratorComponent comp,
|
||||
FuelGeneratorComponent fuelComp,
|
||||
PowerSupplierComponent powerSupplier)
|
||||
{
|
||||
if (!_uiSystem.IsUiOpen(uid, GeneratorComponentUiKey.Key))
|
||||
return;
|
||||
@@ -191,9 +200,13 @@ public sealed class PortableGeneratorSystem : SharedPortableGeneratorSystem
|
||||
var fuel = _generator.GetFuel(uid);
|
||||
var clogged = _generator.GetIsClogged(uid);
|
||||
|
||||
(float, float)? networkStats = null;
|
||||
if (powerSupplier.Net is { IsConnectedNetwork: true } net)
|
||||
networkStats = (net.NetworkNode.LastCombinedLoad, net.NetworkNode.LastCombinedSupply);
|
||||
|
||||
_uiSystem.TrySetUiState(
|
||||
uid,
|
||||
GeneratorComponentUiKey.Key,
|
||||
new PortableGeneratorComponentBuiState(fuelComp, fuel, clogged));
|
||||
new PortableGeneratorComponentBuiState(fuelComp, fuel, clogged, networkStats));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ public abstract class BasePowerNet<TNetType> : BaseNetConnectorNodeGroup<TNetTyp
|
||||
PowerNetSystem = entMan.EntitySysManager.GetEntitySystem<PowerNetSystem>();
|
||||
}
|
||||
|
||||
public bool IsConnectedNetwork => NodeCount > 1;
|
||||
|
||||
public void AddConsumer(PowerConsumerComponent consumer)
|
||||
{
|
||||
DebugTools.Assert(consumer.NetworkLoad.LinkedNetwork == default);
|
||||
|
||||
@@ -5,6 +5,16 @@ namespace Content.Server.Power.NodeGroups
|
||||
{
|
||||
public interface IBasePowerNet
|
||||
{
|
||||
/// <summary>
|
||||
/// Indicates whether this network forms some form of connection (more than one node).
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Even "unconnected" power devices form a single-node power network all by themselves.
|
||||
/// To players, this doesn't look like they're connected to anything.
|
||||
/// This property accounts for this and forms a more intuitive check.
|
||||
/// </remarks>
|
||||
bool IsConnectedNetwork { get; }
|
||||
|
||||
void AddConsumer(PowerConsumerComponent consumer);
|
||||
|
||||
void RemoveConsumer(PowerConsumerComponent consumer);
|
||||
|
||||
@@ -98,12 +98,17 @@ public sealed class PortableGeneratorComponentBuiState : BoundUserInterfaceState
|
||||
{
|
||||
public float RemainingFuel;
|
||||
public bool Clogged;
|
||||
public (float Load, float Supply)? NetworkStats;
|
||||
public float TargetPower;
|
||||
public float MaximumPower;
|
||||
public float OptimalPower;
|
||||
public bool On;
|
||||
|
||||
public PortableGeneratorComponentBuiState(FuelGeneratorComponent component, float remainingFuel, bool clogged)
|
||||
public PortableGeneratorComponentBuiState(
|
||||
FuelGeneratorComponent component,
|
||||
float remainingFuel,
|
||||
bool clogged,
|
||||
(float Demand, float Supply)? networkStats)
|
||||
{
|
||||
RemainingFuel = remainingFuel;
|
||||
Clogged = clogged;
|
||||
@@ -111,6 +116,7 @@ public sealed class PortableGeneratorComponentBuiState : BoundUserInterfaceState
|
||||
MaximumPower = component.MaxTargetPower;
|
||||
OptimalPower = component.OptimalPower;
|
||||
On = component.On;
|
||||
NetworkStats = networkStats;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
### Special messages used by internal localizer stuff.
|
||||
|
||||
# Used internally by the PRESSURE() function.
|
||||
zzzz-fmt-pressure = { TOSTRING($divided, "G4") } { $places ->
|
||||
zzzz-fmt-pressure = { TOSTRING($divided, "F1") } { $places ->
|
||||
[0] kPa
|
||||
[1] MPa
|
||||
[2] GPa
|
||||
@@ -11,7 +11,7 @@ zzzz-fmt-pressure = { TOSTRING($divided, "G4") } { $places ->
|
||||
}
|
||||
|
||||
# Used internally by the POWERWATTS() function.
|
||||
zzzz-fmt-power-watts = { TOSTRING($divided, "G4") } { $places ->
|
||||
zzzz-fmt-power-watts = { TOSTRING($divided, "F1") } { $places ->
|
||||
[0] W
|
||||
[1] kW
|
||||
[2] MW
|
||||
@@ -23,7 +23,7 @@ zzzz-fmt-power-watts = { TOSTRING($divided, "G4") } { $places ->
|
||||
# Used internally by the POWERJOULES() function.
|
||||
# Reminder: 1 joule = 1 watt for 1 second (multiply watts by seconds to get joules).
|
||||
# Therefore 1 kilowatt-hour is equal to 3,600,000 joules (3.6MJ)
|
||||
zzzz-fmt-power-joules = { TOSTRING($divided, "G4") } { $places ->
|
||||
zzzz-fmt-power-joules = { TOSTRING($divided, "F1") } { $places ->
|
||||
[0] J
|
||||
[1] kJ
|
||||
[2] MJ
|
||||
|
||||
@@ -23,6 +23,9 @@ portable-generator-ui-eject = Eject
|
||||
portable-generator-ui-eta = (~{ $minutes } min)
|
||||
portable-generator-ui-unanchored = Unanchored
|
||||
portable-generator-ui-current-output = Current output: {$voltage}
|
||||
portable-generator-ui-network-stats = Network:
|
||||
portable-generator-ui-network-stats-value = { POWERWATTS($supply) } / { POWERWATTS($load) }
|
||||
portable-generator-ui-network-stats-not-connected = Not connected
|
||||
|
||||
power-switchable-generator-examine = The power output is set to {$voltage}.
|
||||
power-switchable-generator-switched = Switched output to {$voltage}!
|
||||
|
||||
@@ -232,11 +232,11 @@
|
||||
name: J.R.P.A.C.M.A.N.-type portable generator
|
||||
description: |-
|
||||
A small generator capable of powering individual rooms, in case of emergencies.
|
||||
Runs off welding fuel and is rated for up to 5 kW.
|
||||
Runs off welding fuel and is rated for up to 8 kW.
|
||||
Rated ages 3 and up.
|
||||
parent: PortableGeneratorBase
|
||||
id: PortableGeneratorJrPacman
|
||||
suffix: Welding Fuel, 5 kW
|
||||
suffix: Welding Fuel, 8 kW
|
||||
components:
|
||||
- type: AmbientSound
|
||||
range: 4
|
||||
@@ -276,10 +276,10 @@
|
||||
- type: Machine
|
||||
board: PortableGeneratorJrPacmanMachineCircuitboard
|
||||
- type: FuelGenerator
|
||||
targetPower: 2000
|
||||
minTargetPower: 1000
|
||||
optimalPower: 5000
|
||||
maxTargetPower: 5000
|
||||
targetPower: 5000
|
||||
minTargetPower: 4000
|
||||
optimalPower: 8000
|
||||
maxTargetPower: 8000
|
||||
# 7.5 minutes at full tank.
|
||||
optimalBurnRate: 0.11111111
|
||||
# Shallow curve that allows you to just barely eek out 12 minutes at lowest.
|
||||
|
||||
Reference in New Issue
Block a user