-<DefaultWindow xmlns="https://spacestation14.io"
+<DefaultWindow xmlns="https://spacestation14.io"
Title="{Loc 'ame-window-title'}"
MinSize="250 250">
- <BoxContainer Orientation="Vertical">
+ <GridContainer Columns="2">
<BoxContainer Orientation="Horizontal">
<Label Text="{Loc 'ame-window-engine-status-label'}" />
<Label Text=" " />
<Label Text=" " />
<Label Name="CoreCount" Text="0" />
</BoxContainer>
- </BoxContainer>
+ <BoxContainer></BoxContainer>
+ <BoxContainer Orientation="Horizontal">
+ <Label Text="{Loc 'ame-window-power-currentsupply-label'}" />
+ <Label Text=" " />
+ <Label Name="CurrentPowerSupply" Text="0" />
+ <Label Text=" kW" />
+ </BoxContainer>
+ <BoxContainer></BoxContainer>
+ <BoxContainer Orientation="Horizontal">
+ <Label Text="{Loc 'ame-window-power-targetsupply-label'}" />
+ <Label Text=" " />
+ <Label Name="TargetedPowerSupply" Text="0" />
+ <Label Text=" kW" />
+ </BoxContainer>
+ </GridContainer>
</DefaultWindow>
CoreCount.Text = $"{castState.CoreCount}";
InjectionAmount.Text = $"{castState.InjectionAmount}";
+ // format power statistics to pretty numbers
+ CurrentPowerSupply.Text = $"{castState.CurrentPowerSupply.ToString("N1")}";
+ TargetedPowerSupply.Text = $"{castState.TargetedPowerSupply.ToString("N1")}";
}
}
}
var safeFuelLimit = CoreCount * 2;
- // Note the float conversions. The maths will completely fail if not done using floats.
- // Oh, and don't ever stuff the result of this in an int. Seriously.
- var floatFuel = (float) fuel;
- var floatCores = (float) CoreCount;
- var powerOutput = 20000f * floatFuel * floatFuel / floatCores;
+ var powerOutput = CalculatePower(fuel, CoreCount);
if (fuel <= safeFuelLimit)
return powerOutput;
return powerOutput;
}
+ /// <summary>
+ /// Calculates the amount of power the AME can produce with the given settings
+ /// </summary>
+ public float CalculatePower(int fuel, int cores)
+ {
+ // Fuel is squared so more fuel vastly increases power and efficiency
+ // We divide by the number of cores so a larger AME is less efficient at the same fuel settings
+ // this results in all AMEs having the same efficiency at the same fuel-per-core setting
+ return 20000f * fuel * fuel / cores;
+ }
+
public int GetTotalStability()
{
if (CoreCount < 1)
[DataField("nextUpdate")]
public TimeSpan NextUpdate = default!;
+ /// <summary>
+ /// The next time this will try to update the controller UI.
+ /// </summary>
+ public TimeSpan NextUIUpdate = default!;
+
/// <summary>
/// The the amount of time that passes between injection attempts.
/// </summary>
[DataField("updatePeriod")]
[ViewVariables(VVAccess.ReadWrite)]
public TimeSpan UpdatePeriod = TimeSpan.FromSeconds(10.0);
+
+ /// <summary>
+ /// The maximum amount of time that passes between UI updates.
+ /// </summary>
+ [ViewVariables]
+ public TimeSpan UpdateUIPeriod = TimeSpan.FromSeconds(3.0);
}
{
if (controller.NextUpdate <= curTime)
UpdateController(uid, curTime, controller, nodes);
+ else if (controller.NextUIUpdate <= curTime)
+ UpdateUi(uid, controller);
}
}
controller.LastUpdate = curTime;
controller.NextUpdate = curTime + controller.UpdatePeriod;
+ // update the UI regardless of other factors to update the power readings
+ UpdateUi(uid, controller);
if (!controller.Injecting)
return;
var state = GetUiState(uid, controller);
_userInterfaceSystem.SetUiState(bui, state);
+
+ controller.NextUIUpdate = _gameTiming.CurTime + controller.UpdateUIPeriod;
}
private AmeControllerBoundUserInterfaceState GetUiState(EntityUid uid, AmeControllerComponent controller)
{
var powered = !TryComp<ApcPowerReceiverComponent>(uid, out var powerSource) || powerSource.Powered;
- var coreCount = TryGetAMENodeGroup(uid, out var group) ? group.CoreCount : 0;
+ var coreCount = 0;
+ // how much power can be produced at the current settings, in kW
+ // we don't use max. here since this is what is set in the Controller, not what the AME is actually producing
+ float targetedPowerSupply = 0;
+ if (TryGetAMENodeGroup(uid, out var group))
+ {
+ coreCount = group.CoreCount;
+ targetedPowerSupply = group.CalculatePower(controller.InjectionAmount, group.CoreCount) / 1000;
+ }
+
+ // set current power statistics in kW
+ float currentPowerSupply = 0;
+ if (TryComp<PowerSupplierComponent>(uid, out var powerOutlet) && coreCount > 0)
+ {
+ currentPowerSupply = powerOutlet.CurrentSupply / 1000;
+ }
var hasJar = Exists(controller.JarSlot.ContainedEntity);
if (!hasJar || !TryComp<AmeFuelContainerComponent>(controller.JarSlot.ContainedEntity, out var jar))
- return new AmeControllerBoundUserInterfaceState(powered, IsMasterController(uid), false, hasJar, 0, controller.InjectionAmount, coreCount);
+ return new AmeControllerBoundUserInterfaceState(powered, IsMasterController(uid), false, hasJar, 0, controller.InjectionAmount, coreCount, currentPowerSupply, targetedPowerSupply);
- return new AmeControllerBoundUserInterfaceState(powered, IsMasterController(uid), controller.Injecting, hasJar, jar.FuelAmount, controller.InjectionAmount, coreCount);
+ return new AmeControllerBoundUserInterfaceState(powered, IsMasterController(uid), controller.Injecting, hasJar, jar.FuelAmount, controller.InjectionAmount, coreCount, currentPowerSupply, targetedPowerSupply);
}
private bool IsMasterController(EntityUid uid)
-using Robust.Shared.Serialization;
+using Robust.Shared.Serialization;
namespace Content.Shared.Ame;
public readonly int FuelAmount;
public readonly int InjectionAmount;
public readonly int CoreCount;
+ public readonly float CurrentPowerSupply;
+ public readonly float TargetedPowerSupply;
- public AmeControllerBoundUserInterfaceState(bool hasPower, bool isMaster, bool injecting, bool hasFuelJar, int fuelAmount, int injectionAmount, int coreCount)
+ public AmeControllerBoundUserInterfaceState(bool hasPower, bool isMaster, bool injecting, bool hasFuelJar, int fuelAmount, int injectionAmount, int coreCount, float currentPowerSupply, float targetedPowerSupply)
{
HasPower = hasPower;
IsMaster = isMaster;
FuelAmount = fuelAmount;
InjectionAmount = injectionAmount;
CoreCount = coreCount;
+ CurrentPowerSupply = currentPowerSupply;
+ TargetedPowerSupply = targetedPowerSupply;
}
}
ame-window-injection-amount-label = Injection amount:
ame-window-refresh-parts-button = Refresh Parts
ame-window-core-count-label = Core count:
+ame-window-power-currentsupply-label = Current power supply:
+ame-window-power-targetsupply-label = Targeted power supply:
ame-window-toggle-injection-button = Toggle Injection
ame-window-eject-button = Eject
ame-window-increase-fuel-button = Increase