Files
Delta-v/Content.Client/_DV/Communications/DVCommunicationsConsoleMenu.xaml.cs
T
a635429d3e Communications console & screens overhaul (#5954)
* i'm going insane from screens

* some wiring

* screemes

* holy shit adhd lock-in

* incomplete

* its FUCKING DONE

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* zeta

* mrrrp

* test fix

* fix arrivals

* fix misnetwork

* Fix iteration outline. Fixed all headers showing if all options where hidden. Added access requirement to keycard auth mechnism. Added countdown. Fixed ninja and fugitive. Fixed AI and aghost.

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Vanessa <vanessalouwagie@gmail.com>
2026-08-27 13:37:40 -05:00

321 lines
13 KiB
C#

using System.Globalization;
using System.Numerics;
using Content.Client.UserInterface.Controls;
using Content.Shared._DV.Communications;
using Content.Shared._DV.KeycardAuthenticationDevice;
using Content.Shared._DV.Screens;
using Content.Shared.Humanoid;
using Content.Shared.Station;
using Robust.Client.AutoGenerated;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
using Robust.Shared.Timing;
using Robust.Shared.Utility;
namespace Content.Client._DV.Communications;
[GenerateTypedNameReferences]
public sealed partial class DVCommunicationsConsoleMenu : FancyWindow
{
[Dependency] private readonly IGameTiming _timing = default!;
[Dependency] private readonly IEntityManager _entity = default!;
private readonly SharedStationSystem _station;
private readonly BoxContainer[] _screens;
private readonly ButtonGroup _group;
public event Action<BoundUserInterfaceMessage>? OnMessage;
private Entity<DVCommunicationsConsoleComponent>? _console;
private Entity<DVStationKeycardAuthenticationDeviceComponent>? _stationKeycardAuthenticationDevice;
private EntityUid? _user;
private readonly Popup _alertLevelsPopup;
private readonly BoxContainer _alertLevels = new()
{
Orientation = BoxContainer.LayoutOrientation.Vertical,
};
private string _lastConfiguredLine1 = string.Empty;
private string _lastConfiguredLine2 = string.Empty;
public DVCommunicationsConsoleMenu()
{
RobustXamlLoader.Load(this);
IoCManager.InjectDependencies(this);
_station = _entity.System<SharedStationSystem>();
_group = new();
_screens = new[]
{
HomeScreen, AnnouncementScreen, ScreenScreen, ShuttlesScreen, AlertLevelScreen,
KeycardAuthenticationDeviceScreen,
};
HomeButton.OnPressed += _ => SetScreen(HomeScreen);
AnnouncementTab.OnPressed += _ => SetScreen(AnnouncementScreen);
ScreenTab.OnPressed += _ => SetScreen(ScreenScreen);
ShuttlesTab.OnPressed += _ => SetScreen(ShuttlesScreen);
AlertLevelTab.OnPressed += _ => SetScreen(AlertLevelScreen);
KeycardAuthenticationDeviceTab.OnPressed += _ => SetScreen(KeycardAuthenticationDeviceScreen);
foreach (var value in Enum.GetValues<DVScreenContent>())
{
ScreenContentsButton.AddItem(Loc.GetString($"comms-console-menu-screen-content.{value}"), (int)value);
}
AnnounceButton.OnPressed += OnAnnouncePressed;
ScreenUpdateTextButton.OnPressed += OnUpdateScreenText;
ScreenContentsButton.OnItemSelected += OnScreenContentsSelected;
ScreenAlertBorder.OnToggled += OnScreenAlertBorderToggled;
ShuttleEmergencyButton.OnPressed += OnEmergencyPressed;
ShuttleExfiltrationButton.OnPressed += OnExfiltrationPressed;
AlertLevelsDropdown.OnPressed += OnAlertLevelsDropdownPressed;
CallZeta.OnPressed += OnCallZetaPressed;
RequestCodes.OnPressed += OnRequestCodesPressed;
_alertLevelsPopup = new()
{
Children = { _alertLevels },
};
_alertLevelsPopup.OnPopupHide += () => _alertLevelsPopup.Orphan();
AnnounceInput.Placeholder = new Rope.Leaf(Loc.GetString("comms-console-menu-announcement-placeholder"));
}
private void OnAlertLevelsDropdownPressed(BaseButton.ButtonEventArgs args)
{
var globalPos = AlertLevelsDropdown.GlobalPosition;
globalPos.Y += AlertLevelsDropdown.Size.Y + 1; // Place it below us, with a safety margin.
_alertLevels.Measure(Window?.Size ?? Vector2Helpers.Infinity);
var (minX, minY) = _alertLevels.DesiredSize;
var box = UIBox2.FromDimensions(globalPos, new Vector2(Math.Max(minX, AlertLevelsDropdown.Width), minY));
_alertLevelsPopup.Orphan();
Root?.ModalRoot.AddChild(_alertLevelsPopup);
_alertLevelsPopup.Open(box);
}
protected override void FrameUpdate(FrameEventArgs args)
{
base.FrameUpdate(args);
if (_console is not { } console)
return;
AnnounceButton.Disabled = _timing.CurTime <= console.Comp.CanAnnounceAt;
AlertLevelsDropdown.Disabled = console.Comp.CanSetAlertAt is null || _timing.CurTime <= console.Comp.CanSetAlertAt;
if (AlertLevelsDropdown.Disabled)
_alertLevelsPopup.Close();
if (console.Comp.ExpectedEvacuationArrival is { } evacArrival)
{
var diff = MathHelper.Max(evacArrival - _timing.CurTime, TimeSpan.Zero);
var infoText = Loc.GetString($"comms-console-menu-shuttle-eta",
("time", diff.ToString(@"hh\:mm\:ss", CultureInfo.CurrentCulture)));
EmergencyStatus.Text = infoText;
}
else
{
EmergencyStatus.Text = Loc.GetString("comms-console-menu-shuttle-not-coming");
}
if (console.Comp.ExpectedExfiltrationArrival is { } exfiltrationArrival)
{
var diff = MathHelper.Max(exfiltrationArrival - _timing.CurTime, TimeSpan.Zero);
var infoText = Loc.GetString($"comms-console-menu-shuttle-eta",
("time", diff.ToString(@"hh\:mm\:ss", CultureInfo.CurrentCulture)));
ExfiltrationStatus.Text = infoText;
}
else
{
ExfiltrationStatus.Text = Loc.GetString("comms-console-menu-shuttle-not-coming");
}
UpdateKeycardAuthenticationDevice();
}
private void SetScreen(Control screen)
{
foreach (var other in _screens)
{
other.Visible = false;
}
screen.Visible = true;
HomeButton.Visible = screen != HomeScreen;
}
public void Update(Entity<DVCommunicationsConsoleComponent> console, EntityUid user)
{
_console = console;
_user = user;
if (_station.GetOwningStation(console) is { } station &&
_entity.TryGetComponent<DVStationKeycardAuthenticationDeviceComponent>(station,
out var keycardAuthenticationDevice))
{
_stationKeycardAuthenticationDevice = (station, keycardAuthenticationDevice);
}
// If they only have the ability to announce, there's no point in having a home button
if (console.Comp.CanAnnounce && !(console.Comp.CanAlertLevel || console.Comp.CanCallShuttles || console.Comp.CanConfigureScreens || console.Comp.CanKeycardAuthenticationDevice))
{
SetScreen(AnnouncementScreen);
HomeButton.Visible = false;
}
// Station
StationHeaderLabel.Visible = console.Comp.CanAnnounce || console.Comp.CanConfigureScreens || console.Comp.CanAlertLevel;
AnnouncementTab.Visible = console.Comp.CanAnnounce;
ScreenTab.Visible = console.Comp.CanConfigureScreens;
AlertLevelTab.Visible = console.Comp.CanAlertLevel;
// Shuttles
TransitHeaderLabel.Visible = console.Comp.CanCallShuttles; // Should be only hidden if all buttons under are also hidden.
ShuttlesTab.Visible = console.Comp.CanCallShuttles;
// Emergency
EmergencyHeaderLabel.Visible = console.Comp.CanKeycardAuthenticationDevice; // Should be only hidden if all buttons under are also hidden.
KeycardAuthenticationDeviceTab.Visible = console.Comp.CanKeycardAuthenticationDevice;
ShuttleEmergencyButton.Disabled = !console.Comp.ShuttlesCallable;
ShuttleExfiltrationButton.Disabled = !console.Comp.ShuttlesCallable;
ShuttleEmergencyButton.Text =
Loc.GetString($"comms-console-menu-call-emergency.{console.Comp.ExpectedEvacuationArrival is null}");
ShuttleExfiltrationButton.Text =
Loc.GetString($"comms-console-menu-call-exfiltration.{console.Comp.ExpectedExfiltrationArrival is null}");
_alertLevels.RemoveAllChildren();
foreach (var level in console.Comp.AlertLevels)
{
if (level.Id == console.Comp.CurrentAlertLevel)
{
AlertLevel.Text = Loc.GetString("comms-console-menu-current-alert-level",
("name", Loc.GetString(level.AlertLevel)),
("color", level.Color),
("description", Loc.GetString(level.Description)));
}
if (!level.CanSet)
continue;
var btn = new Button
{
Text = Loc.GetString(level.AlertLevel),
ToggleMode = true,
Group = _group,
Pressed = level.Id == console.Comp.CurrentAlertLevel,
};
_alertLevels.AddChild(btn);
btn.OnPressed += _ =>
{
_alertLevelsPopup.Close();
OnMessage?.Invoke(new DVCommunicationsConsoleAlertLevelMessage(level.Id));
};
}
if (console.Comp.LastConfiguredLine1 != _lastConfiguredLine1)
ScreenLine1.Text = console.Comp.LastConfiguredLine1;
if (console.Comp.LastConfiguredLine2 != _lastConfiguredLine2)
ScreenLine2.Text = console.Comp.LastConfiguredLine2;
ScreenContentsButton.SelectId((int)console.Comp.LastConfiguredContent);
ScreenAlertBorder.Pressed = console.Comp.LastConfiguredShowBorders;
_lastConfiguredLine1 = console.Comp.LastConfiguredLine1;
_lastConfiguredLine2 = console.Comp.LastConfiguredLine2;
UpdateKeycardAuthenticationDevice();
}
private void UpdateKeycardAuthenticationDevice()
{
if (_user is not { } user || _stationKeycardAuthenticationDevice is not { } station)
return;
var canCall = !_entity.HasComponent<DVStationKeycardAuthenticationDeviceAlreadySwipedComponent>(user)
&& _entity.HasComponent<HumanoidProfileComponent>(user) // Can't be AI or a borg
&& station.Comp.AccessibleAfter <= _timing.CurTime;
CallZeta.ForceDisabled = !(canCall && station.Comp.SwipingFor is null or DVStationKeycardAction.Mayday);
CallZeta.Disabled = CallZeta.ForceDisabled;
RequestCodes.ForceDisabled = !(canCall && station.Comp.SwipingFor is null or DVStationKeycardAction.Scuttling);
RequestCodes.Disabled = RequestCodes.ForceDisabled;
if (CallZeta.IsConfirming || RequestCodes.IsConfirming)
return;
// Kinda messy but it works
if (station.Comp.SwipesStartedAt is { } firstSwipeTime)
{
var countdown = firstSwipeTime + station.Comp.SwipeWindow;
var timeRemaining = countdown.Subtract(_timing.CurTime);
if (timeRemaining > TimeSpan.Zero && station.Comp.SwipingFor is DVStationKeycardAction.Mayday)
CallZeta.Text = $"{timeRemaining:ss\\.fff}";
if (timeRemaining > TimeSpan.Zero && station.Comp.SwipingFor is DVStationKeycardAction.Scuttling)
RequestCodes.Text = $"{timeRemaining:ss\\.fff}";
}
else
{
CallZeta.Text = Loc.GetString("comms-console-menu-declare-mayday.button");
RequestCodes.Text = Loc.GetString("comms-console-menu-request-codes.button");
}
}
private void OnAnnouncePressed(BaseButton.ButtonEventArgs args)
{
OnMessage?.Invoke(new DVCommunicationsConsoleAnnouncementMessage(Rope.Collapse(AnnounceInput.TextRope)));
}
private void UpdateScreens()
{
OnMessage?.Invoke(new DVCommunicationsConsoleScreenConfigurationMessage(
(DVScreenContent) ScreenContentsButton.SelectedId,
ScreenAlertBorder.Pressed,
ScreenLine1.Text,
ScreenLine2.Text));
}
private void OnUpdateScreenText(BaseButton.ButtonEventArgs buttonEventArgs)
{
UpdateScreens();
}
private void OnScreenContentsSelected(OptionButton.ItemSelectedEventArgs itemSelectedEventArgs)
{
ScreenContentsButton.SelectId(itemSelectedEventArgs.Id);
UpdateScreens();
}
private void OnScreenAlertBorderToggled(BaseButton.ButtonToggledEventArgs buttonToggledEventArgs)
{
UpdateScreens();
}
private void OnExfiltrationPressed(BaseButton.ButtonEventArgs args)
{
OnMessage?.Invoke(new DVCommunicationsConsoleExfiltrationShuttleMessage(_console?.Comp.ExpectedExfiltrationArrival is null));
}
private void OnEmergencyPressed(BaseButton.ButtonEventArgs args)
{
OnMessage?.Invoke(new DVCommunicationsConsoleEvacuationShuttleMessage(_console?.Comp.ExpectedEvacuationArrival is null));
}
private void OnCallZetaPressed(BaseButton.ButtonEventArgs obj)
{
OnMessage?.Invoke(new DVCommunicationsConsoleKeycardAuthenticationDeviceMessage(DVStationKeycardAction.Mayday));
}
private void OnRequestCodesPressed(BaseButton.ButtonEventArgs obj)
{
OnMessage?.Invoke(new DVCommunicationsConsoleKeycardAuthenticationDeviceMessage(DVStationKeycardAction.Scuttling));
}
}