using Content.Shared.Singularity.Components;
-using Robust.Client.GameObjects;
using Robust.Client.UserInterface;
namespace Content.Client.ParticleAccelerator.UI
base.Open();
_menu = this.CreateWindow<ParticleAcceleratorControlMenu>();
+ _menu.SetEntity(Owner);
+
_menu.OnOverallState += SendEnableMessage;
_menu.OnPowerState += SendPowerStateMessage;
- _menu.OnScanPartsRequested += SendScanPartsMessage;
+ _menu.OnScan += SendScanPartsMessage;
}
public void SendEnableMessage(bool enable)
+++ /dev/null
-using System.Numerics;
-using Content.Client.Resources;
-using Content.Client.Stylesheets;
-using Content.Client.UserInterface.Controls;
-using Content.Shared.Singularity.Components;
-using Robust.Client.Animations;
-using Robust.Client.Graphics;
-using Robust.Client.ResourceManagement;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
-using Robust.Client.UserInterface.CustomControls;
-using Robust.Shared.Noise;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Timing;
-using static Robust.Client.UserInterface.Controls.BoxContainer;
-
-namespace Content.Client.ParticleAccelerator.UI
-{
- public sealed class ParticleAcceleratorControlMenu : BaseWindow
- {
- [Dependency] private readonly IPrototypeManager _protoManager = default!;
- [Dependency] private readonly IResourceCache _cache = default!;
-
- private readonly ShaderInstance _greyScaleShader;
-
- private readonly Label _drawLabel;
- private readonly FastNoiseLite _drawNoiseGenerator;
- private readonly Button _onButton;
- private readonly Button _offButton;
- private readonly Button _scanButton;
- private readonly Label _statusLabel;
- private readonly SpinBox _stateSpinBox;
-
- private readonly BoxContainer _alarmControl;
- private readonly Animation _alarmControlAnimation;
-
- private readonly PASegmentControl _endCapTexture;
- private readonly PASegmentControl _fuelChamberTexture;
- private readonly PASegmentControl _controlBoxTexture;
- private readonly PASegmentControl _powerBoxTexture;
- private readonly PASegmentControl _emitterForeTexture;
- private readonly PASegmentControl _emitterPortTexture;
- private readonly PASegmentControl _emitterStarboardTexture;
-
- private float _time;
- private int _lastDraw;
- private int _lastReceive;
-
- private bool _blockSpinBox;
- private bool _assembled;
- private bool _shouldContinueAnimating;
- private int _maxStrength = 3;
-
- public event Action<bool>? OnOverallState;
- public event Action<ParticleAcceleratorPowerState>? OnPowerState;
- public event Action? OnScanPartsRequested;
-
- public ParticleAcceleratorControlMenu()
- {
- IoCManager.InjectDependencies(this);
- SetSize = new Vector2(400, 320);
- _greyScaleShader = _protoManager.Index<ShaderPrototype>("Greyscale").Instance();
-
- _drawNoiseGenerator = new();
- _drawNoiseGenerator.SetFractalType(FastNoiseLite.FractalType.FBm);
- _drawNoiseGenerator.SetFrequency(0.5f);
-
- var font = _cache.GetFont("/Fonts/Boxfont-round/Boxfont Round.ttf", 13);
- var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
-
- MouseFilter = MouseFilterMode.Stop;
-
- _alarmControlAnimation = new Animation
- {
- Length = TimeSpan.FromSeconds(1),
- AnimationTracks =
- {
- new AnimationTrackControlProperty
- {
- Property = nameof(Control.Visible),
- KeyFrames =
- {
- new AnimationTrackProperty.KeyFrame(true, 0),
- new AnimationTrackProperty.KeyFrame(false, 0.75f),
- }
- }
- }
- };
-
- var back = new StyleBoxTexture
- {
- Texture = panelTex,
- Modulate = Color.FromHex("#25252A"),
- };
- back.SetPatchMargin(StyleBox.Margin.All, 10);
-
- var back2 = new StyleBoxTexture(back)
- {
- Modulate = Color.FromHex("#202023")
- };
-
- AddChild(new PanelContainer
- {
- PanelOverride = back,
- MouseFilter = MouseFilterMode.Pass
- });
-
- _stateSpinBox = new SpinBox { Value = 0, IsValid = StrengthSpinBoxValid };
- _stateSpinBox.InitDefaultButtons();
- _stateSpinBox.ValueChanged += PowerStateChanged;
- _stateSpinBox.LineEditDisabled = true;
-
- _offButton = new Button
- {
- ToggleMode = false,
- Text = Loc.GetString("particle-accelerator-control-menu-off-button"),
- StyleClasses = { StyleBase.ButtonOpenRight },
- };
-
- _offButton.OnPressed += args => OnOverallState?.Invoke(false);
-
- _onButton = new Button
- {
- ToggleMode = false,
- Text = Loc.GetString("particle-accelerator-control-menu-on-button"),
- StyleClasses = { StyleBase.ButtonOpenLeft },
- };
- _onButton.OnPressed += args => OnOverallState?.Invoke(true);
-
- var closeButton = new TextureButton
- {
- StyleClasses = { "windowCloseButton" },
- HorizontalAlignment = HAlignment.Right,
- Margin = new Thickness(0, 0, 8, 0)
- };
- closeButton.OnPressed += args => Close();
-
- var serviceManual = new Label
- {
- HorizontalAlignment = HAlignment.Center,
- StyleClasses = { StyleBase.StyleClassLabelSubText },
- Text = Loc.GetString("particle-accelerator-control-menu-service-manual-reference")
- };
- _drawLabel = new Label();
- var imgSize = new Vector2(32, 32);
- AddChild(new BoxContainer
- {
- Orientation = LayoutOrientation.Vertical,
- Children =
- {
- new Control
- {
- Margin = new Thickness(2, 2, 0, 0),
- Children =
- {
- new Label
- {
- Text = Loc.GetString("particle-accelerator-control-menu-device-version-label"),
- FontOverride = font,
- FontColorOverride = StyleNano.NanoGold,
- },
- closeButton
- }
- },
- new PanelContainer
- {
- PanelOverride = new StyleBoxFlat {BackgroundColor = StyleNano.NanoGold},
- MinSize = new Vector2(0, 2),
- },
- new Control
- {
- MinSize = new Vector2(0, 4)
- },
-
- new BoxContainer
- {
- Orientation = LayoutOrientation.Horizontal,
- VerticalExpand = true,
- Children =
- {
- new BoxContainer
- {
- Orientation = LayoutOrientation.Vertical,
- Margin = new Thickness(4, 0, 0, 0),
- HorizontalExpand = true,
- Children =
- {
- new BoxContainer
- {
- Orientation = LayoutOrientation.Horizontal,
- Children =
- {
- new Label
- {
- Text = Loc.GetString("particle-accelerator-control-menu-power-label") + " ",
- HorizontalExpand = true,
- HorizontalAlignment = HAlignment.Left,
- },
- _offButton,
- _onButton
- }
- },
- new BoxContainer
- {
- Orientation = LayoutOrientation.Horizontal,
- Children =
- {
- new Label
- {
- Text = Loc.GetString("particle-accelerator-control-menu-strength-label") + " ",
- HorizontalExpand = true,
- HorizontalAlignment = HAlignment.Left,
- },
- _stateSpinBox
- }
- },
- new Control
- {
- MinSize = new Vector2(0, 10),
- },
- _drawLabel,
- new Control
- {
- VerticalExpand = true,
- },
- (_alarmControl = new BoxContainer
- {
- Orientation = LayoutOrientation.Vertical,
- Children =
- {
- new Label
- {
- Text = Loc.GetString("particle-accelerator-control-menu-alarm-control"),
- FontColorOverride = Color.Red,
- Align = Label.AlignMode.Center
- },
- serviceManual
- },
- Visible = false,
- }),
- }
- },
- new BoxContainer
- {
- Orientation = LayoutOrientation.Vertical,
- MinSize = new Vector2(186, 0),
- Children =
- {
- (_statusLabel = new Label
- {
- HorizontalAlignment = HAlignment.Center
- }),
- new Control
- {
- MinSize = new Vector2(0, 20)
- },
- new PanelContainer
- {
- HorizontalAlignment = HAlignment.Center,
- PanelOverride = back2,
- Children =
- {
- new GridContainer
- {
- Columns = 3,
- VSeparationOverride = 0,
- HSeparationOverride = 0,
- Children =
- {
- new Control {MinSize = imgSize},
- (_endCapTexture = Segment("end_cap")),
- new Control {MinSize = imgSize},
- (_controlBoxTexture = Segment("control_box")),
- (_fuelChamberTexture = Segment("fuel_chamber")),
- new Control {MinSize = imgSize},
- new Control {MinSize = imgSize},
- (_powerBoxTexture = Segment("power_box")),
- new Control {MinSize = imgSize},
- (_emitterStarboardTexture = Segment("emitter_starboard")),
- (_emitterForeTexture = Segment("emitter_fore")),
- (_emitterPortTexture = Segment("emitter_port")),
- }
- }
- }
- },
- (_scanButton = new Button
- {
- Text = Loc.GetString("particle-accelerator-control-menu-scan-parts-button"),
- HorizontalAlignment = HAlignment.Center
- })
- }
- }
- }
- },
- new StripeBack
- {
- Children =
- {
- new Label
- {
- Margin = new Thickness(4, 4, 0, 4),
- Text = Loc.GetString("particle-accelerator-control-menu-check-containment-field-warning"),
- HorizontalAlignment = HAlignment.Center,
- StyleClasses = {StyleBase.StyleClassLabelSubText},
- }
- }
- },
- new BoxContainer
- {
- Orientation = LayoutOrientation.Horizontal,
- Margin = new Thickness(12, 0, 0, 0),
- Children =
- {
- new Label
- {
- Text = Loc.GetString("particle-accelerator-control-menu-foo-bar-baz"),
- StyleClasses = {StyleBase.StyleClassLabelSubText}
- }
- }
- },
- }
- });
-
- _scanButton.OnPressed += args => OnScanPartsRequested?.Invoke();
-
- _alarmControl.AnimationCompleted += s =>
- {
- if (_shouldContinueAnimating)
- {
- _alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
- }
- else
- {
- _alarmControl.Visible = false;
- }
- };
-
- PASegmentControl Segment(string name)
- {
- return new(this, _cache, name);
- }
-
- UpdateUI(false, false, false, false);
- }
-
- private bool StrengthSpinBoxValid(int n)
- {
- return n >= 0 && n <= _maxStrength && !_blockSpinBox;
- }
-
- private void PowerStateChanged(ValueChangedEventArgs e)
- {
- ParticleAcceleratorPowerState newState;
- switch (e.Value)
- {
- case 0:
- newState = ParticleAcceleratorPowerState.Standby;
- break;
- case 1:
- newState = ParticleAcceleratorPowerState.Level0;
- break;
- case 2:
- newState = ParticleAcceleratorPowerState.Level1;
- break;
- case 3:
- newState = ParticleAcceleratorPowerState.Level2;
- break;
- case 4:
- newState = ParticleAcceleratorPowerState.Level3;
- break;
- default:
- return;
- }
-
- _stateSpinBox.SetButtonDisabled(true);
- OnPowerState?.Invoke(newState);
- }
-
- protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
- {
- return DragMode.Move;
- }
-
- public void DataUpdate(ParticleAcceleratorUIState uiState)
- {
- _assembled = uiState.Assembled;
- UpdateUI(uiState.Assembled, uiState.InterfaceBlock, uiState.Enabled,
- uiState.WirePowerBlock);
- _statusLabel.Text = Loc.GetString("particle-accelerator-control-menu-status-label",
- ("status", Loc.GetString(uiState.Assembled ? "particle-accelerator-control-menu-status-operational" :
- "particle-accelerator-control-menu-status-incomplete")));
- UpdatePowerState(uiState.State, uiState.Enabled, uiState.Assembled,
- uiState.MaxLevel);
- UpdatePreview(uiState);
- _lastDraw = uiState.PowerDraw;
- _lastReceive = uiState.PowerReceive;
- }
-
- private void UpdatePowerState(ParticleAcceleratorPowerState state, bool enabled, bool assembled,
- ParticleAcceleratorPowerState maxState)
- {
- _stateSpinBox.OverrideValue(state switch
- {
- ParticleAcceleratorPowerState.Standby => 0,
- ParticleAcceleratorPowerState.Level0 => 1,
- ParticleAcceleratorPowerState.Level1 => 2,
- ParticleAcceleratorPowerState.Level2 => 3,
- ParticleAcceleratorPowerState.Level3 => 4,
- _ => 0
- });
-
-
- _maxStrength = maxState == ParticleAcceleratorPowerState.Level3 ? 4 : 3;
- if (_maxStrength > 3 && enabled && assembled)
- {
- _shouldContinueAnimating = true;
- if (!_alarmControl.HasRunningAnimation("warningAnim"))
- _alarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
- }
- else
- _shouldContinueAnimating = false;
- }
-
- private void UpdateUI(bool assembled, bool blocked, bool enabled, bool powerBlock)
- {
- _onButton.Pressed = enabled;
- _offButton.Pressed = !enabled;
-
- var cantUse = !assembled || blocked || powerBlock;
- _onButton.Disabled = cantUse;
- _offButton.Disabled = cantUse;
- _scanButton.Disabled = blocked;
-
- var cantChangeLevel = !assembled || blocked;
- _stateSpinBox.SetButtonDisabled(cantChangeLevel);
- _blockSpinBox = cantChangeLevel;
- }
-
- private void UpdatePreview(ParticleAcceleratorUIState updateMessage)
- {
- _endCapTexture.SetPowerState(updateMessage, updateMessage.EndCapExists);
- _controlBoxTexture.SetPowerState(updateMessage, true);
- _fuelChamberTexture.SetPowerState(updateMessage, updateMessage.FuelChamberExists);
- _powerBoxTexture.SetPowerState(updateMessage, updateMessage.PowerBoxExists);
- _emitterStarboardTexture.SetPowerState(updateMessage, updateMessage.EmitterStarboardExists);
- _emitterForeTexture.SetPowerState(updateMessage, updateMessage.EmitterForeExists);
- _emitterPortTexture.SetPowerState(updateMessage, updateMessage.EmitterPortExists);
- }
-
- protected override void FrameUpdate(FrameEventArgs args)
- {
- base.FrameUpdate(args);
-
- if (!_assembled)
- {
- _drawLabel.Text = Loc.GetString("particle-accelerator-control-menu-draw-not-available");
- return;
- }
-
- _time += args.DeltaSeconds;
-
- var watts = 0;
- if (_lastDraw != 0)
- {
- var val = _drawNoiseGenerator.GetNoise(_time, 0f);
- watts = (int) (_lastDraw + val * 5);
- }
-
- _drawLabel.Text = Loc.GetString("particle-accelerator-control-menu-draw",
- ("watts", $"{watts:##,##0}"),
- ("lastReceive", $"{_lastReceive:##,##0}"));
- }
-
- private sealed class PASegmentControl : Control
- {
- private readonly ParticleAcceleratorControlMenu _menu;
- private readonly string _baseState;
- private readonly TextureRect _base;
- private readonly TextureRect _unlit;
- private readonly RSI _rsi;
-
- public PASegmentControl(ParticleAcceleratorControlMenu menu, IResourceCache cache, string name)
- {
- _menu = menu;
- _baseState = name;
- _rsi = cache.GetResource<RSIResource>($"/Textures/Structures/Power/Generation/PA/{name}.rsi").RSI;
-
- AddChild(_base = new TextureRect { Texture = _rsi[$"completed"].Frame0 });
- AddChild(_unlit = new TextureRect());
- MinSize = _rsi.Size;
- }
-
- public void SetPowerState(ParticleAcceleratorUIState state, bool exists)
- {
- _base.ShaderOverride = exists ? null : _menu._greyScaleShader;
- _base.ModulateSelfOverride = exists ? null : new Color(127, 127, 127);
-
- if (!state.Enabled || !exists)
- {
- _unlit.Visible = false;
- return;
- }
-
- _unlit.Visible = true;
-
- var suffix = state.State switch
- {
- ParticleAcceleratorPowerState.Standby => "_unlitp",
- ParticleAcceleratorPowerState.Level0 => "_unlitp0",
- ParticleAcceleratorPowerState.Level1 => "_unlitp1",
- ParticleAcceleratorPowerState.Level2 => "_unlitp2",
- ParticleAcceleratorPowerState.Level3 => "_unlitp3",
- _ => ""
- };
-
- if (!_rsi.TryGetState(_baseState + suffix, out var rState))
- {
- _unlit.Visible = false;
- return;
- }
-
- _unlit.Texture = rState.Frame0;
- }
- }
- }
-}
--- /dev/null
+<controls:FancyWindow xmlns="https://spacestation14.io"
+ xmlns:gfx="clr-namespace:Robust.Client.Graphics;assembly=Robust.Client"
+ xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
+ xmlns:ui="clr-namespace:Content.Client.ParticleAccelerator.UI"
+ xmlns:customControls="clr-namespace:Content.Client.Administration.UI.CustomControls"
+ Title="{Loc 'particle-accelerator-control-menu-device-version-label'}"
+ MinSize="420 320"
+ SetSize="420 320">
+ <BoxContainer Orientation="Vertical" VerticalExpand="True" Margin="0 10 0 0">
+ <BoxContainer Orientation="Horizontal" VerticalExpand="True">
+ <BoxContainer Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" Margin="10 0 10 5">
+ <BoxContainer Orientation="Horizontal">
+ <RichTextLabel Name="StatusLabel" HorizontalExpand="True"/>
+ <RichTextLabel Name="StatusStateLabel"/>
+ </BoxContainer>
+ <Control MinHeight="5"/>
+ <BoxContainer Orientation="Horizontal">
+ <RichTextLabel Name="PowerLabel" Margin="0 0 20 0" HorizontalExpand="True" VerticalAlignment="Center"/>
+ <Button Name="OffButton" ToggleMode="False" Text="{Loc 'particle-accelerator-control-menu-off-button'}" StyleClasses="OpenRight"/>
+ <Button Name="OnButton" ToggleMode="False" Text="{Loc 'particle-accelerator-control-menu-on-button'}" StyleClasses="OpenLeft"/>
+ </BoxContainer>
+ <Control MinHeight="5"/>
+ <BoxContainer Orientation="Horizontal">
+ <RichTextLabel Name="StrengthLabel" Margin="0 0 20 0" HorizontalExpand="True" HorizontalAlignment="Left" VerticalAlignment="Center"/>
+ <SpinBox Name="StateSpinBox" Value="0"/>
+ </BoxContainer>
+ <Control MinHeight="5"/>
+ <BoxContainer Orientation="Horizontal">
+ <RichTextLabel Name="DrawLabel" HorizontalExpand="True"/>
+ <RichTextLabel Name="DrawValueLabel"/>
+ </BoxContainer>
+ <Control MinHeight="10" VerticalExpand="True"/>
+ <BoxContainer Name="AlarmControl" Orientation="Vertical" VerticalAlignment="Center" Visible="False">
+ <RichTextLabel Name="BigAlarmLabel" HorizontalAlignment="Center"/>
+ <RichTextLabel Name="BigAlarmLabelTwo" HorizontalAlignment="Center"/>
+ <Label Text="{Loc 'particle-accelerator-control-menu-service-manual-reference'}" HorizontalAlignment="Center" StyleClasses="LabelSubText"/>
+ </BoxContainer>
+ <Control MinHeight="10" VerticalExpand="True"/>
+ </BoxContainer>
+ <customControls:VSeparator Margin="0 0 0 10"/>
+ <BoxContainer Orientation="Vertical" Margin="20 0 20 0" VerticalAlignment="Center">
+ <PanelContainer Name="BackPanel" HorizontalAlignment="Center">
+ <PanelContainer.PanelOverride>
+ <gfx:StyleBoxTexture Modulate="#202023" PatchMarginBottom="10" PatchMarginLeft="10" PatchMarginRight="10" PatchMarginTop="10"/>
+ </PanelContainer.PanelOverride>
+ <BoxContainer Orientation="Vertical" HorizontalExpand="True" HorizontalAlignment="Center" VerticalExpand="True">
+ <GridContainer Columns="3" VSeparationOverride="0" HSeparationOverride="0" HorizontalAlignment="Center">
+ <Control/>
+ <ui:PASegmentControl Name="EndCapTexture" BaseState="end_cap"/>
+ <Control/>
+ <ui:PASegmentControl Name="ControlBoxTexture" BaseState="control_box"/>
+ <ui:PASegmentControl Name="FuelChamberTexture" BaseState="fuel_chamber"/>
+ <Control/>
+ <Control/>
+ <ui:PASegmentControl Name="PowerBoxTexture" BaseState="power_box"/>
+ <Control/>
+ <ui:PASegmentControl Name="EmitterStarboardTexture" BaseState="emitter_starboard"/>
+ <ui:PASegmentControl Name="EmitterForeTexture" BaseState="emitter_fore"/>
+ <ui:PASegmentControl Name="EmitterPortTexture" BaseState="emitter_port"/>
+ </GridContainer>
+ <Control MinHeight="5"/>
+ <Button Name="ScanButton" Text="{Loc 'particle-accelerator-control-menu-scan-parts-button'}" HorizontalAlignment="Center"/>
+ </BoxContainer>
+ </PanelContainer>
+ </BoxContainer>
+ </BoxContainer>
+ <controls:StripeBack>
+ <Label Text="{Loc 'particle-accelerator-control-menu-check-containment-field-warning'}" HorizontalAlignment="Center" StyleClasses="LabelSubText" Margin="4 4 0 4"/>
+ </controls:StripeBack>
+ <BoxContainer Orientation="Horizontal" Margin="12 0 0 0">
+ <Label Text="{Loc 'particle-accelerator-control-menu-foo-bar-baz'}" StyleClasses="LabelSubText"/>
+ </BoxContainer>
+ </BoxContainer>
+</controls:FancyWindow>
--- /dev/null
+using System.Numerics;
+using Content.Client.Message;
+using Content.Client.Resources;
+using Content.Client.UserInterface.Controls;
+using Content.Shared.Singularity.Components;
+using Robust.Client.Animations;
+using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
+using Robust.Client.ResourceManagement;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Noise;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Timing;
+
+namespace Content.Client.ParticleAccelerator.UI;
+
+[GenerateTypedNameReferences]
+public sealed partial class ParticleAcceleratorControlMenu : FancyWindow
+{
+ [Dependency] private readonly IResourceCache _cache = default!;
+
+ private readonly FastNoiseLite _drawNoiseGenerator;
+
+ private readonly Animation _alarmControlAnimation;
+
+ private float _time;
+ private int _lastDraw;
+ private int _lastReceive;
+
+ private bool _assembled;
+ private bool _shouldContinueAnimating;
+ private int _maxStrength = 3;
+
+ public event Action<bool>? OnOverallState;
+ public event Action? OnScan;
+ public event Action<ParticleAcceleratorPowerState>? OnPowerState;
+
+ private EntityUid _entity;
+
+ public ParticleAcceleratorControlMenu()
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ _drawNoiseGenerator = new();
+ _drawNoiseGenerator.SetFractalType(FastNoiseLite.FractalType.FBm);
+ _drawNoiseGenerator.SetFrequency(0.5f);
+
+ var panelTex = _cache.GetTexture("/Textures/Interface/Nano/button.svg.96dpi.png");
+
+ MouseFilter = MouseFilterMode.Stop;
+
+ _alarmControlAnimation = new Animation
+ {
+ Length = TimeSpan.FromSeconds(1),
+ AnimationTracks =
+ {
+ new AnimationTrackControlProperty
+ {
+ Property = nameof(Visible),
+ KeyFrames =
+ {
+ new AnimationTrackProperty.KeyFrame(true, 0),
+ new AnimationTrackProperty.KeyFrame(false, 0.75f),
+ }
+ }
+ }
+ };
+
+ if (BackPanel.PanelOverride is StyleBoxTexture tex)
+ tex.Texture = panelTex;
+
+ StatusLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-status-label"));
+ StatusStateLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-status-unknown"));
+ PowerLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-power-label"));
+ StrengthLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-strength-label"));
+ BigAlarmLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-alarm-control-1"));
+ BigAlarmLabelTwo.SetMarkup(Loc.GetString("particle-accelerator-control-menu-alarm-control-2"));
+ DrawLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-draw"));
+
+ StateSpinBox.IsValid = StrengthSpinBoxValid;
+ StateSpinBox.InitDefaultButtons();
+ StateSpinBox.ValueChanged += PowerStateChanged;
+ StateSpinBox.LineEditDisabled = true;
+
+ OffButton.OnPressed += _ =>
+ {
+ OnOverallState?.Invoke(false);
+ };
+
+ OnButton.OnPressed += _ =>
+ {
+ OnOverallState?.Invoke(true);
+ };
+
+ ScanButton.OnPressed += _ =>
+ {
+ OnScan?.Invoke();
+ };
+
+ AlarmControl.AnimationCompleted += _ =>
+ {
+ if (_shouldContinueAnimating)
+ {
+ AlarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
+ }
+ else
+ {
+ AlarmControl.Visible = false;
+ }
+ };
+
+ UpdateUI(false, false, false, false);
+ }
+
+ public void SetEntity(EntityUid uid)
+ {
+ _entity = uid;
+ }
+
+ private void PowerStateChanged(ValueChangedEventArgs e)
+ {
+ ParticleAcceleratorPowerState newState;
+ switch (e.Value)
+ {
+ case 0:
+ newState = ParticleAcceleratorPowerState.Standby;
+ break;
+ case 1:
+ newState = ParticleAcceleratorPowerState.Level0;
+ break;
+ case 2:
+ newState = ParticleAcceleratorPowerState.Level1;
+ break;
+ case 3:
+ newState = ParticleAcceleratorPowerState.Level2;
+ break;
+ case 4:
+ newState = ParticleAcceleratorPowerState.Level3;
+ break;
+ default:
+ return;
+ }
+
+ StateSpinBox.SetButtonDisabled(true);
+ OnPowerState?.Invoke(newState);
+ }
+
+ private bool StrengthSpinBoxValid(int n)
+ {
+ return n >= 0 && n <= _maxStrength ;
+ }
+
+ protected override DragMode GetDragModeFor(Vector2 relativeMousePos)
+ {
+ return DragMode.Move;
+ }
+
+ public void DataUpdate(ParticleAcceleratorUIState uiState)
+ {
+ _assembled = uiState.Assembled;
+ UpdateUI(uiState.Assembled,
+ uiState.InterfaceBlock,
+ uiState.Enabled,
+ uiState.WirePowerBlock);
+ StatusStateLabel.SetMarkup(Loc.GetString(uiState.Assembled
+ ? "particle-accelerator-control-menu-status-operational"
+ : "particle-accelerator-control-menu-status-incomplete"));
+ UpdatePowerState(uiState.State, uiState.Enabled, uiState.Assembled, uiState.MaxLevel);
+ UpdatePreview(uiState);
+ _lastDraw = uiState.PowerDraw;
+ _lastReceive = uiState.PowerReceive;
+ }
+
+ private void UpdatePowerState(ParticleAcceleratorPowerState state, bool enabled, bool assembled, ParticleAcceleratorPowerState maxState)
+ {
+ var value = state switch
+ {
+ ParticleAcceleratorPowerState.Standby => 0,
+ ParticleAcceleratorPowerState.Level0 => 1,
+ ParticleAcceleratorPowerState.Level1 => 2,
+ ParticleAcceleratorPowerState.Level2 => 3,
+ ParticleAcceleratorPowerState.Level3 => 4,
+ _ => 0
+ };
+
+ StateSpinBox.OverrideValue(value);
+
+ _maxStrength = maxState == ParticleAcceleratorPowerState.Level3 ? 4 : 3;
+ if (_maxStrength > 3 && enabled && assembled)
+ {
+ _shouldContinueAnimating = true;
+ if (!AlarmControl.HasRunningAnimation("warningAnim"))
+ AlarmControl.PlayAnimation(_alarmControlAnimation, "warningAnim");
+ }
+ else
+ _shouldContinueAnimating = false;
+ }
+
+ private void UpdateUI(bool assembled, bool blocked, bool enabled, bool powerBlock)
+ {
+ OnButton.Pressed = enabled;
+ OffButton.Pressed = !enabled;
+
+ var cantUse = !assembled || blocked || powerBlock;
+ OnButton.Disabled = cantUse;
+ OffButton.Disabled = cantUse;
+ ScanButton.Disabled = blocked;
+
+ var cantChangeLevel = !assembled || blocked || !enabled || cantUse;
+ StateSpinBox.SetButtonDisabled(cantChangeLevel);
+ }
+
+ private void UpdatePreview(ParticleAcceleratorUIState updateMessage)
+ {
+ EndCapTexture.SetPowerState(updateMessage, updateMessage.EndCapExists);
+ ControlBoxTexture.SetPowerState(updateMessage, true);
+ FuelChamberTexture.SetPowerState(updateMessage, updateMessage.FuelChamberExists);
+ PowerBoxTexture.SetPowerState(updateMessage, updateMessage.PowerBoxExists);
+ EmitterStarboardTexture.SetPowerState(updateMessage, updateMessage.EmitterStarboardExists);
+ EmitterForeTexture.SetPowerState(updateMessage, updateMessage.EmitterForeExists);
+ EmitterPortTexture.SetPowerState(updateMessage, updateMessage.EmitterPortExists);
+ }
+
+ protected override void FrameUpdate(FrameEventArgs args)
+ {
+ base.FrameUpdate(args);
+
+ if (!_assembled)
+ {
+ DrawValueLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-draw-not-available"));
+ return;
+ }
+
+ _time += args.DeltaSeconds;
+
+ var watts = 0;
+ if (_lastDraw != 0)
+ {
+ var val = _drawNoiseGenerator.GetNoise(_time, 0f);
+ watts = (int) (_lastDraw + val * 5);
+ }
+
+ DrawValueLabel.SetMarkup(Loc.GetString("particle-accelerator-control-menu-draw-value",
+ ("watts", $"{watts:##,##0}"),
+ ("lastReceive", $"{_lastReceive:##,##0}")));
+ }
+}
+
+public sealed class PASegmentControl : Control
+{
+ private readonly ShaderInstance _greyScaleShader;
+ private readonly TextureRect _base;
+ private readonly TextureRect _unlit;
+ private RSI? _rsi;
+
+ public string BaseState { get; set; } = "control_box";
+
+ public PASegmentControl()
+ {
+ _greyScaleShader = IoCManager.Resolve<IPrototypeManager>().Index<ShaderPrototype>("Greyscale").Instance();
+
+ AddChild(_base = new TextureRect());
+ AddChild(_unlit = new TextureRect());
+ }
+
+ protected override void EnteredTree()
+ {
+ base.EnteredTree();
+ _rsi = IoCManager.Resolve<IResourceCache>().GetResource<RSIResource>($"/Textures/Structures/Power/Generation/PA/{BaseState}.rsi").RSI;
+ MinSize = _rsi.Size;
+ _base.Texture = _rsi["completed"].Frame0;
+ }
+
+ public void SetPowerState(ParticleAcceleratorUIState state, bool exists)
+ {
+ _base.ShaderOverride = exists ? null : _greyScaleShader;
+ _base.ModulateSelfOverride = exists ? null : new Color(127, 127, 127);
+
+ if (!state.Enabled || !exists)
+ {
+ _unlit.Visible = false;
+ return;
+ }
+
+ _unlit.Visible = true;
+
+ var suffix = state.State switch
+ {
+ ParticleAcceleratorPowerState.Standby => "_unlitp",
+ ParticleAcceleratorPowerState.Level0 => "_unlitp0",
+ ParticleAcceleratorPowerState.Level1 => "_unlitp1",
+ ParticleAcceleratorPowerState.Level2 => "_unlitp2",
+ ParticleAcceleratorPowerState.Level3 => "_unlitp3",
+ _ => ""
+ };
+
+ if (_rsi == null)
+ return;
+
+ if (!_rsi.TryGetState(BaseState + suffix, out var rState))
+ {
+ _unlit.Visible = false;
+ return;
+ }
+
+ _unlit.Texture = rState.Frame0;
+ }
+}
-using Content.Shared.Singularity.Components;
+using Robust.Shared.Prototypes;
namespace Content.Server.ParticleAccelerator.Components;
[RegisterComponent]
public sealed partial class ParticleAcceleratorEmitterComponent : Component
{
- [DataField("emittedPrototype")]
- [ViewVariables(VVAccess.ReadWrite)]
- public string EmittedPrototype = "ParticlesProjectile";
+ [DataField]
+ public EntProtoId EmittedPrototype = "ParticlesProjectile";
[DataField("emitterType")]
[ViewVariables(VVAccess.ReadWrite)]
_adminLogger.Add(LogType.Action, LogImpact.Low, $"{ToPrettyString(player):player} has turned {ToPrettyString(uid)} off");
comp.Enabled = false;
+ SetStrength(uid, ParticleAcceleratorPowerState.Standby, user, comp);
UpdatePowerDraw(uid, comp);
PowerOff(uid, comp);
UpdateUI(uid, comp);
var pos = Transform(uid);
if (_timing.CurTime > comp.EffectCooldown)
{
- _chat.SendAdminAlert(player, Loc.GetString("particle-accelerator-admin-power-strength-warning",
+ _chat.SendAdminAlert(player,
+ Loc.GetString("particle-accelerator-admin-power-strength-warning",
("machine", ToPrettyString(uid)),
- ("powerState", strength),
+ ("powerState", GetPANumericalLevel(strength)),
("coordinates", pos.Coordinates)));
_audio.PlayGlobal("/Audio/Misc/adminlarm.ogg",
- Filter.Empty().AddPlayers(_adminManager.ActiveAdmins), false,
+ Filter.Empty().AddPlayers(_adminManager.ActiveAdmins),
+ false,
AudioParams.Default.WithVolume(-8f));
comp.EffectCooldown = _timing.CurTime + comp.CooldownDuration;
}
powerConsumer.DrawRate = powerDraw;
}
- private void UpdateUI(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
+ public void UpdateUI(EntityUid uid, ParticleAcceleratorControlBoxComponent? comp = null)
{
if (!Resolve(uid, ref comp))
return;
receive = powerConsumer.ReceivedPower;
}
- _uiSystem.SetUiState(uid, ParticleAcceleratorControlBoxUiKey.Key, new ParticleAcceleratorUIState(
+ _uiSystem.SetUiState(uid,
+ ParticleAcceleratorControlBoxUiKey.Key,
+ new ParticleAcceleratorUIState(
comp.Assembled,
comp.Enabled,
comp.SelectedStrength,
UpdateUI(uid, comp);
}
+
+ public static int GetPANumericalLevel(ParticleAcceleratorPowerState state)
+ {
+ return state switch
+ {
+ ParticleAcceleratorPowerState.Level0 => 1,
+ ParticleAcceleratorPowerState.Level1 => 2,
+ ParticleAcceleratorPowerState.Level2 => 3,
+ ParticleAcceleratorPowerState.Level3 => 4,
+ _ => 0
+ };
+ }
}
using System.Diagnostics.CodeAnalysis;
-using System.Numerics;
using Content.Server.ParticleAccelerator.Components;
using JetBrains.Annotations;
using Robust.Shared.Map.Components;
using Robust.Shared.Physics.Events;
-using Robust.Shared.Player;
namespace Content.Server.ParticleAccelerator.EntitySystems;
if (controller.CurrentlyRescanning)
return;
- SwitchOff(uid, user, controller);
-
var partQuery = GetEntityQuery<ParticleAcceleratorPartComponent>();
foreach (var part in AllParts(uid, controller))
{
var xformQuery = GetEntityQuery<TransformComponent>();
if (!xformQuery.TryGetComponent(uid, out var xform) || !xform.Anchored)
+ {
+ SwitchOff(uid, user, controller);
return;
+ }
var gridUid = xform.GridUid;
if (gridUid == null || gridUid != xform.ParentUid || !TryComp<MapGridComponent>(gridUid, out var grid))
+ {
+ SwitchOff(uid, user, controller);
return;
+ }
// Find fuel chamber first by scanning cardinals.
var fuelQuery = GetEntityQuery<ParticleAcceleratorFuelChamberComponent>();
foreach (var adjacent in _mapSystem.GetCardinalNeighborCells(gridUid.Value, grid, xform.Coordinates))
{
if (fuelQuery.HasComponent(adjacent)
- && partQuery.TryGetComponent(adjacent, out var partState)
- && partState.Master == null)
+ && partQuery.TryGetComponent(adjacent, out var partState)
+ && partState.Master == null)
{
controller.FuelChamber = adjacent;
break;
if (controller.FuelChamber == null)
{
- UpdateUI(uid, controller);
+ SwitchOff(uid, user, controller);
return;
}
var positionForeEmitter = positionFuelChamber + offsetVect * 2;
var positionStarboardEmitter = positionFuelChamber + offsetVect * 2 - orthoOffsetVect;
- ScanPart<ParticleAcceleratorEndCapComponent>(gridUid!.Value, positionEndCap, rotation, out controller.EndCap, out var _, grid);
- ScanPart<ParticleAcceleratorPowerBoxComponent>(gridUid!.Value, positionPowerBox, rotation, out controller.PowerBox, out var _, grid);
+ ScanPart<ParticleAcceleratorEndCapComponent>(gridUid.Value, positionEndCap, rotation, out controller.EndCap, out _, grid);
+ ScanPart<ParticleAcceleratorPowerBoxComponent>(gridUid.Value, positionPowerBox, rotation, out controller.PowerBox, out _, grid);
- if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionPortEmitter, rotation, out controller.PortEmitter, out var portEmitter, grid)
- || portEmitter!.Type != ParticleAcceleratorEmitterType.Port)
+ if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionPortEmitter, rotation, out controller.PortEmitter, out var portEmitter, grid)
+ || portEmitter.Type != ParticleAcceleratorEmitterType.Port)
controller.PortEmitter = null;
- if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionForeEmitter, rotation, out controller.ForeEmitter, out var foreEmitter, grid)
- || foreEmitter!.Type != ParticleAcceleratorEmitterType.Fore)
+ if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionForeEmitter, rotation, out controller.ForeEmitter, out var foreEmitter, grid)
+ || foreEmitter.Type != ParticleAcceleratorEmitterType.Fore)
controller.ForeEmitter = null;
- if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid!.Value, positionStarboardEmitter, rotation, out controller.StarboardEmitter, out var starboardEmitter, grid)
- || starboardEmitter!.Type != ParticleAcceleratorEmitterType.Starboard)
+ if (!ScanPart<ParticleAcceleratorEmitterComponent>(gridUid.Value, positionStarboardEmitter, rotation, out controller.StarboardEmitter, out var starboardEmitter, grid)
+ || starboardEmitter.Type != ParticleAcceleratorEmitterType.Starboard)
controller.StarboardEmitter = null;
controller.Assembled =
private void OnComponentShutdown(EntityUid uid, ParticleAcceleratorPartComponent comp, ComponentShutdown args)
{
- if (EntityManager.EntityExists(comp.Master))
+ if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
private void BodyTypeChanged(EntityUid uid, ParticleAcceleratorPartComponent comp, ref PhysicsBodyTypeChangedEvent args)
{
- if (EntityManager.EntityExists(comp.Master))
+ if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
private void OnMoveEvent(EntityUid uid, ParticleAcceleratorPartComponent comp, ref MoveEvent args)
{
- if (EntityManager.EntityExists(comp.Master))
+ if (Exists(comp.Master))
RescanParts(comp.Master!.Value);
}
}
using Content.Server.ParticleAccelerator.Components;
+using Content.Server.ParticleAccelerator.EntitySystems;
using Content.Server.Wires;
using Content.Shared.Singularity.Components;
using Content.Shared.Wires;
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.InterfaceDisabled = true;
+ var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.InterfaceDisabled = false;
+ var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
using Content.Shared.Popups;
using Content.Shared.Singularity.Components;
using Content.Shared.Wires;
-using Robust.Shared.Player;
namespace Content.Server.ParticleAccelerator.Wires;
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.MaxStrength = ParticleAcceleratorPowerState.Level3;
+ var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
// Since that blocks SetStrength().
var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
paSystem.SetStrength(wire.Owner, controller.MaxStrength, user, controller);
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override void Pulse(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
- EntityManager.System<PopupSystem>().PopupEntity(
+ EntityManager.System<PopupSystem>()
+ .PopupEntity(
Loc.GetString("particle-accelerator-control-box-component-wires-update-limiter-on-pulse"),
user,
PopupType.SmallCaution
public override bool Cut(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.StrengthLocked = true;
+ var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
public override bool Mend(EntityUid user, Wire wire, ParticleAcceleratorControlBoxComponent controller)
{
controller.StrengthLocked = false;
+ var paSystem = EntityManager.System<ParticleAcceleratorSystem>();
+ paSystem.UpdateUI(wire.Owner, controller);
return true;
}
particle-accelerator-control-menu-off-button = Off
particle-accelerator-control-menu-service-manual-reference = Refer to p.132 of service manual
particle-accelerator-control-menu-device-version-label = Mark 2 Particle Accelerator
-particle-accelerator-control-menu-power-label = Power:
-particle-accelerator-control-menu-strength-label = Strength:
-particle-accelerator-control-menu-alarm-control = PARTICLE STRENGTH
- LIMITER FAILURE
+particle-accelerator-control-menu-power-label = [bold]Power:[/bold]
+particle-accelerator-control-menu-strength-label = [bold]Strength:[/bold]
+particle-accelerator-control-menu-alarm-control-1 = [bold][color=red]PARTICLE STRENGTH[/bold][/color]
+particle-accelerator-control-menu-alarm-control-2 = [bold][color=red]LIMITER FAILURE[/bold][/color]
particle-accelerator-control-menu-scan-parts-button = Scan Parts
particle-accelerator-control-menu-check-containment-field-warning = Ensure containment field is active before operation
particle-accelerator-control-menu-foo-bar-baz = FOO-BAR-BAZ
-particle-accelerator-control-menu-status-label = Status: {$status}
-particle-accelerator-control-menu-status-operational = Operational
-particle-accelerator-control-menu-status-incomplete = Incomplete
-particle-accelerator-control-menu-draw-not-available = Draw: N/A
-particle-accelerator-control-menu-draw = Draw: {$watts}/{$lastReceive}
\ No newline at end of file
+particle-accelerator-control-menu-status-label = [bold]Status:[/bold]
+particle-accelerator-control-menu-status-unknown = [font="Monospace"][color=red]Unknown[/color][/bold]
+particle-accelerator-control-menu-status-operational = [font="Monospace"][color=green]Operational[/color][/bold]
+particle-accelerator-control-menu-status-incomplete = [font="Monospace"][color=red]Incomplete[/color][/bold]
+particle-accelerator-control-menu-draw = [bold]Draw:[/bold]
+particle-accelerator-control-menu-draw-value = [font="Monospace"]{$watts}/{$lastReceive}[/font]
+particle-accelerator-control-menu-draw-not-available = [font="Monospace"][color=gray]N/A[/color][/font]
+
+particle-accelerator-radio-message-on = PA power has been switched on.
+particle-accelerator-radio-message-off = PA power has been switched off.
+particle-accelerator-radio-message-num = PA strength has been set to level {$level}.