Merge 42083d4eae into c7e1c980b6
|
|
@ -28,7 +28,6 @@ namespace Content.Client.Communications.UI
|
|||
_menu.OnBroadcast += BroadcastButtonPressed;
|
||||
_menu.OnAlertLevel += AlertLevelSelected;
|
||||
_menu.OnEmergencyLevel += EmergencyShuttleButtonPressed;
|
||||
_menu.OnExfiltrationLevel += ExfiltrationShuttleButtonPressed; // DeltaV - Exfiltration shuttle
|
||||
}
|
||||
|
||||
public void AlertLevelSelected(string level)
|
||||
|
|
@ -48,13 +47,6 @@ namespace Content.Client.Communications.UI
|
|||
CallShuttle();
|
||||
}
|
||||
|
||||
// Begin DeltaV - Exfiltration Shuttle
|
||||
public void ExfiltrationShuttleButtonPressed()
|
||||
{
|
||||
SendMessage(new CommunicationsConsoleExfiltrationShuttleMessage(!_menu!.CountdownStarted));
|
||||
}
|
||||
// End DeltaV - Exfiltration Shuttle
|
||||
|
||||
public void AnnounceButtonPressed(string message)
|
||||
{
|
||||
var maxLength = _cfg.GetCVar(CCVars.ChatMaxAnnouncementLength);
|
||||
|
|
@ -94,13 +86,6 @@ namespace Content.Client.Communications.UI
|
|||
_menu.CurrentLevel = commsState.CurrentAlert;
|
||||
_menu.CountdownEnd = commsState.ExpectedCountdownEnd;
|
||||
|
||||
|
||||
// Begin DeltaV - Exfiltration Shuttle
|
||||
_menu.CanExfiltrate = commsState.CanCall;
|
||||
_menu.ExfiltrationCountdownEnd = commsState.ExpectedExfiltrationCountdownEnd;
|
||||
_menu.ExfiltrationShuttleButton.Disabled = !_menu.CanExfiltrate;
|
||||
// End DeltaV - Exfiltration Shuttle
|
||||
|
||||
_menu.UpdateCountdown();
|
||||
_menu.UpdateAlertLevels(commsState.AlertLevels, _menu.CurrentLevel);
|
||||
_menu.AlertLevelButton.Disabled = !_menu.AlertLevelSelectable;
|
||||
|
|
|
|||
|
|
@ -52,19 +52,10 @@
|
|||
|
||||
<RichTextLabel Name="CountdownLabel"/>
|
||||
|
||||
<!-- DeltaV - Exfiltration Shuttle -->
|
||||
<RichTextLabel Name="ExfiltrationCountdownLabel"/>
|
||||
|
||||
<Button Name="EmergencyShuttleButton"
|
||||
Access="Public"
|
||||
Text="Placeholder Text"
|
||||
ToolTip="{Loc 'comms-console-menu-emergency-shuttle-button-tooltip'}"/>
|
||||
|
||||
<!-- DeltaV - Exfiltration Shuttle -->
|
||||
<Button Name="ExfiltrationShuttleButton"
|
||||
Access="Public"
|
||||
Text="Placeholder Text"
|
||||
ToolTip="{Loc 'comms-console-menu-exfiltration-shuttle-button-tooltip'}"/>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
|
|
|
|||
|
|
@ -29,12 +29,6 @@ namespace Content.Client.Communications.UI
|
|||
public event Action<string>? OnAnnounce;
|
||||
public event Action<string>? OnBroadcast;
|
||||
|
||||
// Begin DeltaV - Exfiltration Shuttle
|
||||
public bool CanExfiltrate;
|
||||
public TimeSpan? ExfiltrationCountdownEnd;
|
||||
public event Action? OnExfiltrationLevel;
|
||||
// End DeltaV - Exfiltration Shuttle
|
||||
|
||||
public CommunicationsConsoleMenu()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
|
@ -78,18 +72,12 @@ namespace Content.Client.Communications.UI
|
|||
|
||||
EmergencyShuttleButton.OnPressed += _ => OnEmergencyLevel?.Invoke();
|
||||
EmergencyShuttleButton.Disabled = !CanCall;
|
||||
|
||||
// Begin DeltaV - Exfiltration Shuttle
|
||||
ExfiltrationShuttleButton.OnPressed += _ => OnExfiltrationLevel?.Invoke();
|
||||
ExfiltrationShuttleButton.Disabled = !CanExfiltrate;
|
||||
// End DeltaV - Exfiltration Shuttle
|
||||
}
|
||||
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
base.FrameUpdate(args);
|
||||
UpdateCountdown();
|
||||
UpdateExfiltrationCountdown(); // DeltaV - Exfiltration shuttle
|
||||
}
|
||||
|
||||
// The current alert could make levels unselectable, so we need to ensure that the UI reacts properly.
|
||||
|
|
@ -129,25 +117,6 @@ namespace Content.Client.Communications.UI
|
|||
}
|
||||
}
|
||||
|
||||
// Begin DeltaV - Exfiltration Shuttle
|
||||
public void UpdateExfiltrationCountdown()
|
||||
{
|
||||
if (ExfiltrationCountdownEnd is null)
|
||||
{
|
||||
ExfiltrationCountdownLabel.SetMessage(string.Empty);
|
||||
ExfiltrationShuttleButton.Text = Loc.GetString("comms-console-menu-call-exfiltration");
|
||||
return;
|
||||
}
|
||||
|
||||
var exfiltrationDiff = MathHelper.Max((ExfiltrationCountdownEnd - _timing.CurTime) ?? TimeSpan.Zero, TimeSpan.Zero);
|
||||
ExfiltrationShuttleButton.Text = Loc.GetString("comms-console-menu-recall-exfiltration");
|
||||
|
||||
var exfiltrationInfoText = Loc.GetString("comms-console-menu-exfiltration-time-remaining",
|
||||
("time", exfiltrationDiff.ToString(@"hh\:mm\:ss", CultureInfo.CurrentCulture)));
|
||||
ExfiltrationCountdownLabel.SetMessage(exfiltrationInfoText);
|
||||
}
|
||||
// End DeltaV - Exfiltration Shuttle
|
||||
|
||||
public void UpdateCountdown()
|
||||
{
|
||||
if (!CountdownStarted)
|
||||
|
|
|
|||
|
|
@ -70,6 +70,11 @@ public sealed class ConfirmButton : Button
|
|||
[ViewVariables]
|
||||
public bool IsConfirming = false;
|
||||
|
||||
// Begin DeltaV
|
||||
[ViewVariables]
|
||||
public bool ForceDisabled = false;
|
||||
// End DeltaV
|
||||
|
||||
public ConfirmButton()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
|
@ -87,7 +92,7 @@ public sealed class ConfirmButton : Button
|
|||
}
|
||||
|
||||
if (Disabled && _gameTiming.CurTime > _nextCooldown)
|
||||
Disabled = false;
|
||||
Disabled = ForceDisabled; // DeltaV
|
||||
}
|
||||
|
||||
protected override void DrawModeChanged()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,30 @@
|
|||
using Content.Shared._DV.Communications;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client._DV.Communications;
|
||||
|
||||
public sealed class DVCommunicationsConsoleBoundUserInterface : BoundUserInterface
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entity = default!;
|
||||
|
||||
private DVCommunicationsConsoleMenu? _menu;
|
||||
|
||||
public DVCommunicationsConsoleBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
|
||||
{
|
||||
}
|
||||
|
||||
protected override void Open()
|
||||
{
|
||||
base.Open();
|
||||
|
||||
_menu = this.CreateWindow<DVCommunicationsConsoleMenu>();
|
||||
_menu.OnMessage += SendMessage;
|
||||
if (_entity.TryGetComponent<DVCommunicationsConsoleComponent>(Owner, out var comp))
|
||||
Update((Owner, comp));
|
||||
}
|
||||
|
||||
public void Update(Entity<DVCommunicationsConsoleComponent> ent)
|
||||
{
|
||||
_menu?.Update(ent, PlayerManager.LocalEntity!.Value);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,117 @@
|
|||
<controls:FancyWindow
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:controls="clr-namespace:Content.Client.UserInterface.Controls"
|
||||
Title="{Loc 'comms-console-menu-title'}"
|
||||
MinSize="400 300">
|
||||
|
||||
<BoxContainer Name="HomeScreen" Orientation="Vertical" Margin="8">
|
||||
<Label Text="{Loc 'comms-console-menu-station-title'}" StyleClasses="LabelKeyText" />
|
||||
<Button Name="AnnouncementTab" Text="{Loc 'comms-console-menu-tab.Announcement'}" />
|
||||
<Button Name="ScreenTab" Text="{Loc 'comms-console-menu-tab.Screen'}" />
|
||||
<Button Name="AlertLevelTab" Text="{Loc 'comms-console-menu-tab.AlertLevel'}" />
|
||||
|
||||
<Label Text="{Loc 'comms-console-menu-transit-title'}" StyleClasses="LabelKeyText" Margin="0 8 0 0" />
|
||||
<Button Name="ShuttlesTab" Text="{Loc 'comms-console-menu-tab.Shuttles'}" />
|
||||
|
||||
<Label Text="{Loc 'comms-console-menu-emergency-title'}" StyleClasses="LabelKeyText" Margin="0 8 0 0" />
|
||||
<Button Name="KeycardAuthenticationDeviceTab" Text="{Loc 'comms-console-menu-tab.KeycardAuthenticationDevice'}" />
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<Button Name="HomeButton" Text="{Loc 'comms-console-menu-home'}" Visible="False" />
|
||||
|
||||
<BoxContainer Name="AnnouncementScreen" Visible="False" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SeparationOverride="8" Margin="8">
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True" VerticalExpand="True">
|
||||
<BoxContainer SeparationOverride="8" Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-announcement-text'}" StyleClasses="LabelKeyText" />
|
||||
<TextEdit Name="AnnounceInput"
|
||||
VerticalExpand="True"
|
||||
HorizontalExpand="True"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"
|
||||
MinHeight="100" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True">
|
||||
<Button Name="AnnounceButton" Margin="8" Text="{Loc 'comms-console-menu-send-announcement'}" />
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Name="ScreenScreen" Visible="False" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SeparationOverride="8" Margin="8">
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True">
|
||||
<BoxContainer SeparationOverride="8" Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-screen-configuration'}" StyleClasses="LabelKeyText" />
|
||||
|
||||
<BoxContainer>
|
||||
<Label Text="{Loc 'comms-console-menu-screen-contents'}" HorizontalExpand="True" />
|
||||
<OptionButton Name="ScreenContentsButton" />
|
||||
</BoxContainer>
|
||||
<BoxContainer>
|
||||
<Label Text="{Loc 'comms-console-menu-alert-level-border'}" HorizontalExpand="True" />
|
||||
<Button Name="ScreenAlertBorder" Text="{Loc 'comms-console-menu-enable-border'}" ToggleMode="True" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="PanelDark">
|
||||
<BoxContainer Margin="8" Orientation="Vertical" SeparationOverride="4">
|
||||
<Label Text="{Loc 'comms-console-menu-screen-text'}" StyleClasses="LabelKeyText" />
|
||||
|
||||
<GridContainer Columns="2" HorizontalExpand="True">
|
||||
<Label Text="{Loc 'comms-console-menu-line-1'}" />
|
||||
<LineEdit Name="ScreenLine1" HorizontalExpand="True" StyleClasses="comms-console-display" />
|
||||
<Label Text="{Loc 'comms-console-menu-line-2'}" />
|
||||
<LineEdit Name="ScreenLine2" HorizontalExpand="True" StyleClasses="comms-console-display" />
|
||||
</GridContainer>
|
||||
|
||||
<Button Name="ScreenUpdateTextButton" Text="{Loc 'comms-console-menu-update-screen-text'}" HorizontalAlignment="Right" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Name="ShuttlesScreen" Visible="False" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SeparationOverride="8" Margin="8">
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True">
|
||||
<BoxContainer Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-emergency-shuttle'}" StyleClasses="LabelKeyText" />
|
||||
<RichTextLabel Name="EmergencyStatus" Text="{Loc 'comms-console-menu-shuttle-not-coming'}" />
|
||||
<Button Name="ShuttleEmergencyButton" Text="{Loc 'comms-console-menu-call-emergency.True'}" HorizontalAlignment="Right" Margin="0 8 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True">
|
||||
<BoxContainer Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-exfiltration-shuttle'}" StyleClasses="LabelKeyText" />
|
||||
<RichTextLabel Name="ExfiltrationStatus" Text="{Loc 'comms-console-menu-shuttle-not-coming'}" />
|
||||
<Button Name="ShuttleExfiltrationButton" Text="{Loc 'comms-console-menu-call-exfiltration.True'}" HorizontalAlignment="Right" Margin="0 8 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Name="AlertLevelScreen" Visible="False" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SeparationOverride="8" Margin="8">
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True" MaxWidth="400">
|
||||
<BoxContainer Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-alert-level'}" StyleClasses="LabelKeyText" />
|
||||
<RichTextLabel Name="AlertLevel" HorizontalExpand="True" />
|
||||
<Button Name="AlertLevelsDropdown" Text="{Loc 'comms-console-menu-change-alert-level'}" HorizontalAlignment="Right" Margin="0 8 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
|
||||
<BoxContainer Name="KeycardAuthenticationDeviceScreen" Visible="False" Orientation="Vertical" HorizontalExpand="True" VerticalExpand="True" SeparationOverride="8" Margin="8">
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True" MaxWidth="400">
|
||||
<BoxContainer Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-declare-mayday.title'}" StyleClasses="LabelKeyText" />
|
||||
<RichTextLabel Text="{Loc 'comms-console-menu-declare-mayday.desc'}" />
|
||||
<controls:ConfirmButton Name="CallZeta" Text="{Loc 'comms-console-menu-declare-mayday.button'}" HorizontalAlignment="Right" Margin="0 8 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
|
||||
<PanelContainer StyleClasses="PanelDark" HorizontalExpand="True" MaxWidth="400">
|
||||
<BoxContainer Margin="8" HorizontalExpand="True" Orientation="Vertical">
|
||||
<Label Text="{Loc 'comms-console-menu-request-codes.title'}" StyleClasses="LabelKeyText" />
|
||||
<RichTextLabel Text="{Loc 'comms-console-menu-request-codes.desc'}" />
|
||||
<controls:ConfirmButton Name="RequestCodes" Text="{Loc 'comms-console-menu-request-codes.button'}" HorizontalAlignment="Right" Margin="0 8 0 0" />
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</controls:FancyWindow>
|
||||
|
|
@ -0,0 +1,289 @@
|
|||
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.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 (console.Comp.CanAnnounce && !(console.Comp.CanAlertLevel || console.Comp.CanCallShuttles || console.Comp.CanConfigureScreens || console.Comp.CanKeycardAuthenticationDevice))
|
||||
{
|
||||
SetScreen(AnnouncementScreen);
|
||||
HomeButton.Visible = false;
|
||||
}
|
||||
|
||||
AnnouncementTab.Visible = console.Comp.CanAnnounce;
|
||||
ScreenTab.Visible = console.Comp.CanConfigureScreens;
|
||||
ShuttlesTab.Visible = console.Comp.CanCallShuttles;
|
||||
AlertLevelTab.Visible = console.Comp.CanAlertLevel;
|
||||
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)
|
||||
&& 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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
using Content.Shared._DV.Communications;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client._DV.Communications;
|
||||
|
||||
public sealed class DVCommunicationsConsoleSystem : SharedDVCommunicationsConsoleSystem
|
||||
{
|
||||
[Dependency] private readonly UserInterfaceSystem _userInterface = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DVCommunicationsConsoleComponent, AfterAutoHandleStateEvent>(OnHandleState);
|
||||
}
|
||||
|
||||
private void OnHandleState(Entity<DVCommunicationsConsoleComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
if (!_userInterface.TryGetOpenUi<DVCommunicationsConsoleBoundUserInterface>(ent.Owner,
|
||||
DVCommunicationsConsoleUi.Key,
|
||||
out var bui))
|
||||
return;
|
||||
|
||||
bui.Update(ent);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
using Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
|
||||
namespace Content.Client._DV.KeycardAuthenticationDevice;
|
||||
|
||||
public sealed class DVStationKeycardAuthenticationDeviceSystem : SharedDVStationKeycardAuthenticationDeviceSystem;
|
||||
|
|
@ -0,0 +1,95 @@
|
|||
using System.Globalization;
|
||||
using Content.Client.GameTicking.Managers;
|
||||
using Content.Client.TextScreen;
|
||||
using Content.Shared._DV.Screens;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client._DV.Screens;
|
||||
|
||||
public sealed class DVScreenSystem : DVSharedScreenSystem
|
||||
{
|
||||
[Dependency] private readonly DVTextVisualsSystem _textVisuals = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly ClientGameTicker _ticker = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DVScreenComponent, AfterAutoHandleStateEvent>(OnScreenState);
|
||||
}
|
||||
|
||||
public override void FrameUpdate(float frameTime)
|
||||
{
|
||||
base.FrameUpdate(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<DVScreenComponent>();
|
||||
while (query.MoveNext(out var uid, out var screen))
|
||||
{
|
||||
switch (screen.Content)
|
||||
{
|
||||
case DVScreenContent.Text:
|
||||
break;
|
||||
case DVScreenContent.CurrentTime:
|
||||
CurrentTime((uid, screen));
|
||||
break;
|
||||
case DVScreenContent.EstimatedTimeOfArrival:
|
||||
EstimatedTimeOfArrival((uid, screen));
|
||||
break;
|
||||
case DVScreenContent.AlertLevel:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnScreenState(Entity<DVScreenComponent> ent, ref AfterAutoHandleStateEvent args)
|
||||
{
|
||||
UpdateVisuals(ent);
|
||||
|
||||
switch (ent.Comp.Content)
|
||||
{
|
||||
case DVScreenContent.Text:
|
||||
Text(ent);
|
||||
break;
|
||||
case DVScreenContent.CurrentTime:
|
||||
CurrentTime(ent);
|
||||
break;
|
||||
case DVScreenContent.EstimatedTimeOfArrival:
|
||||
EstimatedTimeOfArrival(ent);
|
||||
break;
|
||||
case DVScreenContent.AlertLevel:
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException();
|
||||
}
|
||||
}
|
||||
|
||||
private void Text(Entity<DVScreenComponent> ent)
|
||||
{
|
||||
_textVisuals.SetText(ent.Owner, ent.Comp.Line1, ent.Comp.Line2);
|
||||
}
|
||||
|
||||
private void CurrentTime(Entity<DVScreenComponent> ent)
|
||||
{
|
||||
var time = (_timing.CurTime - _ticker.RoundStartTimeSpan).Duration();
|
||||
_textVisuals.SetText(ent.Owner, Loc.GetString("status-display-time"), time.ToString("hh\\:mm"));
|
||||
}
|
||||
|
||||
private void EstimatedTimeOfArrival(Entity<DVScreenComponent> ent)
|
||||
{
|
||||
if (ent.Comp.TargetTime <= _timing.CurTime)
|
||||
{
|
||||
_textVisuals.SetText(ent.Owner, string.Empty, string.Empty);
|
||||
return;
|
||||
}
|
||||
|
||||
var time = (_timing.CurTime - ent.Comp.TargetTime).Duration();
|
||||
var formatted = time.ToString("mm\\:ss");
|
||||
Log.Debug($"{_timing.CurTime} - {ent.Comp.TargetTime} = {time}");
|
||||
var title = ent.Comp.ScreenIsAtDestination ? Loc.GetString("status-display-etd") : Loc.GetString("status-display-eta");
|
||||
|
||||
_textVisuals.SetText(ent.Owner, title, formatted);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
namespace Content.Client._DV.Screens;
|
||||
|
||||
[UsedImplicitly]
|
||||
public sealed class DVTextRenderingOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
private readonly SpriteSystem _sprite;
|
||||
private readonly AnimationPlayerSystem _animationPlayer;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.ScreenSpaceBelowWorld;
|
||||
|
||||
private readonly Queue<(Entity<DVTextVisualsComponent> Entity, Font Font, CancellationToken Cancellation)> _queue = new();
|
||||
|
||||
public const string MarqueeKey = "dv-text-screen-marquee";
|
||||
|
||||
public DVTextRenderingOverlay(SpriteSystem sprite, AnimationPlayerSystem animationPlayer)
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_sprite = sprite;
|
||||
_animationPlayer = animationPlayer;
|
||||
|
||||
ZIndex = -100; // this needs to render before almost everything
|
||||
}
|
||||
|
||||
public CancellationTokenSource QueueRender(
|
||||
Entity<DVTextVisualsComponent> ent,
|
||||
Font font)
|
||||
{
|
||||
var source = new CancellationTokenSource();
|
||||
_queue.Enqueue((ent, font, source.Token));
|
||||
|
||||
return source;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
var screenHandle = args.ScreenHandle;
|
||||
|
||||
while (_queue.TryDequeue(out var queued))
|
||||
{
|
||||
if (queued.Cancellation.IsCancellationRequested)
|
||||
continue;
|
||||
|
||||
var font = queued.Font;
|
||||
foreach (var row in queued.Entity.Comp.Rows)
|
||||
{
|
||||
if (row.Text == string.Empty)
|
||||
{
|
||||
_sprite.LayerSetTexture(queued.Entity.Owner, row.Layer, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
var dimensions = screenHandle.GetDimensions(queued.Font, row.Text, 1f);
|
||||
var dimensionsInt = new Vector2i((int)MathF.Round(dimensions.X), (int)MathF.Round(dimensions.Y));
|
||||
|
||||
if (row.Texture is null || row.Texture.Size != dimensionsInt)
|
||||
{
|
||||
row.Texture = _clyde.CreateRenderTarget(dimensionsInt,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8),
|
||||
name: $"dv-text-visuals-{queued.Entity.Owner.Id}");
|
||||
|
||||
_sprite.LayerSetTexture(queued.Entity.Owner, row.Layer, row.Texture.Texture);
|
||||
_sprite.LayerSetOffset(queued.Entity.Owner, row.Layer, row.Offset);
|
||||
}
|
||||
|
||||
args.DrawingHandle.RenderInRenderTarget(row.Texture,
|
||||
() =>
|
||||
{
|
||||
screenHandle.DrawString(font, Vector2.Zero, row.Text);
|
||||
},
|
||||
Color.Transparent);
|
||||
}
|
||||
|
||||
_animationPlayer.Stop(queued.Entity.Owner, MarqueeKey);
|
||||
if (CreateMarqueeAnimation(queued.Entity) is { } animation)
|
||||
{
|
||||
queued.Entity.Comp.Animation = animation;
|
||||
_animationPlayer.Play(queued.Entity.Owner, animation, MarqueeKey);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Animation? CreateMarqueeAnimation(Entity<DVTextVisualsComponent> ent)
|
||||
{
|
||||
var largestRowWidth = ent.Comp.Rows.Aggregate(0, (i, row) => Math.Max(i, row.Texture?.Size.X ?? 0));
|
||||
var animationTime = ent.Comp.MarqueeRate * largestRowWidth;
|
||||
var marqueeWidth = new Vector2((float)ent.Comp.MarqueeWidth / EyeManager.PixelsPerMeter, 0);
|
||||
|
||||
var animation = new Animation
|
||||
{
|
||||
Length = animationTime,
|
||||
};
|
||||
|
||||
foreach (var row in ent.Comp.Rows)
|
||||
{
|
||||
if (row.Texture is null)
|
||||
continue;
|
||||
|
||||
var rowHalfWidth = new Vector2(row.Texture.Size.X / 2f / EyeManager.PixelsPerMeter, 0f);
|
||||
|
||||
if (row.Texture.Size.X <= ent.Comp.MarqueeWidth)
|
||||
continue;
|
||||
|
||||
animation.AnimationTracks.Add(new AnimationTrackLayerOffset()
|
||||
{
|
||||
Layer = row.Layer,
|
||||
KeyFrames =
|
||||
{
|
||||
new AnimationTrackProperty.KeyFrame(row.Offset + rowHalfWidth + marqueeWidth, 0f),
|
||||
new AnimationTrackProperty.KeyFrame(row.Offset - rowHalfWidth - marqueeWidth, (float)animationTime.TotalSeconds),
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return animation.AnimationTracks.Count > 0 ? animation : null;
|
||||
}
|
||||
|
||||
public sealed class AnimationTrackLayerOffset : AnimationTrackProperty
|
||||
{
|
||||
public required Enum Layer;
|
||||
private readonly SpriteSystem _sprite = IoCManager.Resolve<IEntityManager>().System<SpriteSystem>();
|
||||
|
||||
protected override void ApplyProperty(object context, object value)
|
||||
{
|
||||
if (value is not Vector2 vector)
|
||||
throw new InvalidOperationException("Value must be a .");
|
||||
|
||||
_sprite.LayerSetOffset((EntityUid) context, Layer, vector);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,43 @@
|
|||
using System.Numerics;
|
||||
using System.Threading;
|
||||
using Content.Shared._DV.Screens;
|
||||
using Robust.Client.Animations;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client._DV.Screens;
|
||||
|
||||
[RegisterComponent]
|
||||
[Access(typeof(DVTextVisualsSystem), typeof(DVTextRenderingOverlay))]
|
||||
public sealed partial class DVTextVisualsComponent : Component
|
||||
{
|
||||
[DataField(required: true)]
|
||||
public List<DVTextVisualsRow> Rows;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan MarqueeRate = TimeSpan.FromSeconds(0.045f);
|
||||
|
||||
[DataField]
|
||||
public int MarqueeWidth = 24;
|
||||
|
||||
[DataField]
|
||||
public int MarqueePadding = 8;
|
||||
|
||||
public Animation? Animation;
|
||||
|
||||
public CancellationTokenSource? Token;
|
||||
}
|
||||
|
||||
[DataDefinition]
|
||||
public sealed partial class DVTextVisualsRow
|
||||
{
|
||||
public IRenderTexture? Texture;
|
||||
|
||||
[DataField]
|
||||
public string Text;
|
||||
|
||||
[DataField]
|
||||
public Vector2 Offset;
|
||||
|
||||
[DataField(required: true)]
|
||||
public Enum Layer = DVTextScreenVisualLayers.Line1;
|
||||
}
|
||||
|
|
@ -0,0 +1,73 @@
|
|||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.ResourceManagement;
|
||||
|
||||
namespace Content.Client._DV.Screens;
|
||||
|
||||
public sealed class DVTextVisualsSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlay = default!;
|
||||
[Dependency] private readonly IResourceCache _resource = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
|
||||
|
||||
private DVTextRenderingOverlay _textRendering = default!;
|
||||
|
||||
private Font _font = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_textRendering = new(_sprite, _animationPlayer);
|
||||
_overlay.AddOverlay(_textRendering);
|
||||
_font = new VectorFont(_resource.GetResource<FontResource>("/Fonts/_DV/TinyUnicode.ttf"), 12);
|
||||
|
||||
SubscribeLocalEvent<DVTextVisualsComponent, ComponentInit>(OnComponentInit);
|
||||
SubscribeLocalEvent<DVTextVisualsComponent, ComponentShutdown>(OnComponentShutdown);
|
||||
|
||||
SubscribeLocalEvent<DVTextVisualsComponent, AnimationCompletedEvent>(OnAnimationComplete);
|
||||
}
|
||||
|
||||
public override void Shutdown()
|
||||
{
|
||||
_overlay.RemoveOverlay(_textRendering);
|
||||
}
|
||||
|
||||
private void OnComponentInit(Entity<DVTextVisualsComponent> ent, ref ComponentInit args)
|
||||
{
|
||||
ent.Comp.Token = _textRendering.QueueRender(ent, _font);
|
||||
}
|
||||
|
||||
private void OnComponentShutdown(Entity<DVTextVisualsComponent> ent, ref ComponentShutdown args)
|
||||
{
|
||||
foreach (var row in ent.Comp.Rows)
|
||||
{
|
||||
row.Texture?.Dispose();
|
||||
}
|
||||
ent.Comp.Token?.Cancel();
|
||||
}
|
||||
|
||||
private void OnAnimationComplete(Entity<DVTextVisualsComponent> ent, ref AnimationCompletedEvent args)
|
||||
{
|
||||
if (args.Key != DVTextRenderingOverlay.MarqueeKey || !args.Finished || ent.Comp.Animation is not { } animation)
|
||||
return;
|
||||
|
||||
_animationPlayer.Play(ent.Owner, animation, DVTextRenderingOverlay.MarqueeKey);
|
||||
}
|
||||
|
||||
public void SetText(Entity<DVTextVisualsComponent?> ent, params string[] rows)
|
||||
{
|
||||
if (!Resolve(ent, ref ent.Comp))
|
||||
return;
|
||||
|
||||
var count = Math.Min(rows.Length, ent.Comp.Rows.Count);
|
||||
for (var i = 0; i < count; i++)
|
||||
{
|
||||
ent.Comp.Rows[i].Text = rows[i];
|
||||
}
|
||||
|
||||
ent.Comp.Token?.Cancel();
|
||||
ent.Comp.Token = _textRendering.QueueRender((ent, ent.Comp), _font);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
using Content.Client.Resources;
|
||||
using Content.Client.Stylesheets;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using static Content.Client.Stylesheets.StylesheetHelpers;
|
||||
|
||||
namespace Content.Client._DV.Stylesheets.Sheetlets;
|
||||
|
||||
[CommonSheetlet]
|
||||
public sealed class DVLineEditSheetlet : Sheetlet<PalettedStylesheet>
|
||||
{
|
||||
public override StyleRule[] GetRules(PalettedStylesheet sheet, object config)
|
||||
{
|
||||
var tinyUnicode = ResCache.GetFont("/Fonts/_DV/TinyUnicode.ttf", size: 24);
|
||||
|
||||
return
|
||||
[
|
||||
E<LineEdit>()
|
||||
.Class("comms-console-display")
|
||||
.Font(tinyUnicode),
|
||||
];
|
||||
}
|
||||
}
|
||||
|
|
@ -23,7 +23,7 @@ using Robust.Shared.Configuration;
|
|||
|
||||
namespace Content.Server.Communications
|
||||
{
|
||||
public sealed partial class CommunicationsConsoleSystem : EntitySystem // DeltaV - Partial Class
|
||||
public sealed class CommunicationsConsoleSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly AccessReaderSystem _accessReaderSystem = default!;
|
||||
[Dependency] private readonly AlertLevelSystem _alertLevelSystem = default!;
|
||||
|
|
@ -53,8 +53,6 @@ namespace Content.Server.Communications
|
|||
SubscribeLocalEvent<CommunicationsConsoleComponent, CommunicationsConsoleCallEmergencyShuttleMessage>(OnCallShuttleMessage);
|
||||
SubscribeLocalEvent<CommunicationsConsoleComponent, CommunicationsConsoleRecallEmergencyShuttleMessage>(OnRecallShuttleMessage);
|
||||
|
||||
InitializeExfiltration(); // DeltaV - Exfiltration shuttle
|
||||
|
||||
// On console init, set cooldown
|
||||
SubscribeLocalEvent<CommunicationsConsoleComponent, MapInitEvent>(OnCommunicationsConsoleMapInit);
|
||||
}
|
||||
|
|
@ -138,7 +136,6 @@ namespace Content.Server.Communications
|
|||
List<string>? levels = null;
|
||||
string currentLevel = default!;
|
||||
float currentDelay = 0;
|
||||
TimeSpan? exfiltrationTime = null; // DeltaV - exfiltration shuttle
|
||||
|
||||
if (stationUid != null)
|
||||
{
|
||||
|
|
@ -160,12 +157,6 @@ namespace Content.Server.Communications
|
|||
currentLevel = alertComp.CurrentLevel;
|
||||
currentDelay = _alertLevelSystem.GetAlertLevelDelay(stationUid.Value, alertComp);
|
||||
}
|
||||
// Begin DeltaV - exfiltration shuttle
|
||||
if (TryComp<StationExfiltrationComponent>(stationUid, out var exfiltration))
|
||||
{
|
||||
exfiltrationTime = exfiltration.ArrivalTime;
|
||||
}
|
||||
// End DeltaV - exfiltration shuttle
|
||||
}
|
||||
|
||||
_uiSystem.SetUiState(uid, CommunicationsConsoleUiKey.Key, new CommunicationsConsoleInterfaceState(
|
||||
|
|
@ -174,8 +165,7 @@ namespace Content.Server.Communications
|
|||
levels,
|
||||
currentLevel,
|
||||
currentDelay,
|
||||
_roundEndSystem.ExpectedCountdownEnd,
|
||||
exfiltrationTime // DeltaV - exfiltration shuttle
|
||||
_roundEndSystem.ExpectedCountdownEnd
|
||||
));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,6 +30,17 @@ public sealed partial class EmergencyLightComponent : SharedEmergencyLightCompon
|
|||
[DataField("chargingEfficiency")]
|
||||
public float ChargingEfficiency = 0.85f;
|
||||
|
||||
// Begin DeltaV Additions
|
||||
[DataField]
|
||||
public float MaydayRadius = 10f;
|
||||
|
||||
[DataField]
|
||||
public float MaydayFalloff = 0f;
|
||||
|
||||
[DataField]
|
||||
public float MaydayEnergy = 0.7f;
|
||||
// End DeltaV Additions
|
||||
|
||||
public Dictionary<EmergencyLightState, string> BatteryStateText = new()
|
||||
{
|
||||
{ EmergencyLightState.Full, "emergency-light-component-light-state-full" },
|
||||
|
|
|
|||
|
|
@ -1,32 +0,0 @@
|
|||
using Content.Server._DV.Station.Components;
|
||||
using Content.Server._DV.Station.Systems;
|
||||
using Content.Shared._DV.Communications;
|
||||
|
||||
namespace Content.Server.Communications;
|
||||
|
||||
public sealed partial class CommunicationsConsoleSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly StationExfiltrationSystem _stationExfiltration = default!;
|
||||
|
||||
private void InitializeExfiltration()
|
||||
{
|
||||
SubscribeLocalEvent<CommunicationsConsoleComponent, CommunicationsConsoleExfiltrationShuttleMessage>(OnExfiltrationMessage);
|
||||
}
|
||||
|
||||
private void OnExfiltrationMessage(Entity<CommunicationsConsoleComponent> ent, ref CommunicationsConsoleExfiltrationShuttleMessage args)
|
||||
{
|
||||
if (_stationSystem.GetOwningStation(ent) is not { } station)
|
||||
return;
|
||||
|
||||
if (!CanUse(args.Actor, ent))
|
||||
{
|
||||
_popupSystem.PopupEntity(Loc.GetString("comms-console-permission-denied"), ent, args.Actor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (args.Call)
|
||||
_stationExfiltration.Call(station);
|
||||
else
|
||||
_stationExfiltration.Recall(station);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
using Content.Server._DV.Station.Components;
|
||||
using Content.Server._DV.Station.Systems;
|
||||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Communications;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Server.Shuttles.Systems;
|
||||
using Content.Shared._DV.Communications;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.Station;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._DV.Communications;
|
||||
|
||||
public sealed class DVCommunicationsConsoleSystem : SharedDVCommunicationsConsoleSystem
|
||||
{
|
||||
[Dependency] private readonly SharedStationSystem _station = default!;
|
||||
[Dependency] private readonly EmergencyShuttleSystem _emergencyShuttle = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
||||
[Dependency] private readonly IConfigurationManager _configuration = default!;
|
||||
[Dependency] private readonly AlertLevelSystem _alertLevel = default!;
|
||||
[Dependency] private readonly StationExfiltrationSystem _stationExfiltration = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<RoundEndSystemChangedEvent>(OnRoundEndChanged);
|
||||
SubscribeLocalEvent<StationExfiltrationChangedEvent>(OnExfiltrationChanged);
|
||||
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
||||
}
|
||||
|
||||
private void OnAlertLevelChanged(AlertLevelChangedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DVCommunicationsConsoleComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
if (_station.GetOwningStation(uid) != ev.Station)
|
||||
continue;
|
||||
|
||||
var alertLevel = Comp<AlertLevelComponent>(ev.Station);
|
||||
comp.CanSetAlertAt = Timing.CurTime + TimeSpan.FromSeconds(alertLevel.CurrentDelay);
|
||||
comp.CurrentAlertLevel = ev.AlertLevel;
|
||||
if (alertLevel.IsLevelLocked)
|
||||
comp.CanSetAlertAt = null;
|
||||
Dirty(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnExfiltrationChanged(ref StationExfiltrationChangedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DVCommunicationsConsoleComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
if (_station.GetOwningStation(uid) != ev.Station)
|
||||
continue;
|
||||
|
||||
comp.ExpectedExfiltrationArrival = ev.Station.Comp.ArrivalTime;
|
||||
Dirty(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnRoundEndChanged(RoundEndSystemChangedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DVCommunicationsConsoleComponent>();
|
||||
while (query.MoveNext(out var uid, out var comp))
|
||||
{
|
||||
comp.ExpectedEvacuationArrival = _roundEnd.ExpectedCountdownEnd;
|
||||
comp.ExpectedEvacuationDuration = _roundEnd.ExpectedShuttleLength;
|
||||
comp.ShuttlesCallable = ShuttlesCallable();
|
||||
Dirty(uid, comp);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnMapInit(Entity<DVCommunicationsConsoleComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
base.OnMapInit(ent, ref args);
|
||||
|
||||
if (_station.GetOwningStation(ent) is not { } station)
|
||||
return;
|
||||
|
||||
if (!TryComp<AlertLevelComponent>(station, out var alertLevel))
|
||||
return;
|
||||
|
||||
ent.Comp.CurrentAlertLevel = alertLevel.CurrentLevel;
|
||||
var proto = _prototype.Index<AlertLevelPrototype>(alertLevel.AlertLevelPrototype);
|
||||
foreach (var (name, detail) in proto.Levels)
|
||||
{
|
||||
ent.Comp.AlertLevels.Add(new($"alert-level-{name}", $"alert-level-{name}-announcement", name, !detail.DisableSelection, detail.Color));
|
||||
}
|
||||
ent.Comp.CanSetAlertAt = Timing.CurTime + TimeSpan.FromSeconds(alertLevel.CurrentDelay);
|
||||
if (alertLevel.IsLevelLocked)
|
||||
ent.Comp.CanSetAlertAt = null;
|
||||
ent.Comp.ShuttlesCallable = ShuttlesCallable();
|
||||
|
||||
ent.Comp.ExpectedEvacuationArrival = _roundEnd.ExpectedCountdownEnd;
|
||||
ent.Comp.ExpectedEvacuationDuration = _roundEnd.ExpectedShuttleLength;
|
||||
if (TryComp<StationExfiltrationComponent>(station, out var exfiltration))
|
||||
ent.Comp.ExpectedExfiltrationArrival = exfiltration.ArrivalTime;
|
||||
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private bool ShuttlesCallable()
|
||||
{
|
||||
// Defer to what the round end system thinks we should be able to do.
|
||||
if (_emergencyShuttle.EmergencyShuttleArrived || !_roundEnd.CanCallOrRecall())
|
||||
return false;
|
||||
|
||||
// Calling shuttle checks
|
||||
if (_roundEnd.ExpectedCountdownEnd is null)
|
||||
return true;
|
||||
|
||||
// Recalling shuttle checks
|
||||
var recallThreshold = _configuration.GetCVar(CCVars.EmergencyRecallTurningPoint);
|
||||
|
||||
// shouldn't really be happening if we got here
|
||||
if (_roundEnd.ShuttleTimeLeft is not { } left
|
||||
|| _roundEnd.ExpectedShuttleLength is not { } expected)
|
||||
return false;
|
||||
|
||||
return !(left.TotalSeconds / expected.TotalSeconds < recallThreshold);
|
||||
}
|
||||
|
||||
protected override void OnAlertLevel(Entity<DVCommunicationsConsoleComponent> ent, ref DVCommunicationsConsoleAlertLevelMessage args)
|
||||
{
|
||||
base.OnAlertLevel(ent, ref args);
|
||||
|
||||
if (!AccessReader.IsAllowed(ent, args.Actor))
|
||||
return;
|
||||
|
||||
if (_station.GetOwningStation(ent) is not { } station)
|
||||
return;
|
||||
|
||||
_alertLevel.SetLevel(station, args.AlertLevel, true, true);
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Actor):player} has set the alert level to {args.AlertLevel:level} on {ToPrettyString(station):station} using {ToPrettyString(ent):console}");
|
||||
}
|
||||
|
||||
protected override void OnEvacuationShuttle(Entity<DVCommunicationsConsoleComponent> ent, ref DVCommunicationsConsoleEvacuationShuttleMessage args)
|
||||
{
|
||||
base.OnEvacuationShuttle(ent, ref args);
|
||||
|
||||
if (!AccessReader.IsAllowed(ent, args.Actor))
|
||||
return;
|
||||
|
||||
if (args.Call)
|
||||
{
|
||||
var ev = new CommunicationConsoleCallShuttleAttemptEvent(ent, default!, args.Actor);
|
||||
RaiseLocalEvent(ref ev);
|
||||
|
||||
_roundEnd.RequestRoundEnd(args.Actor);
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Actor):player} has called the evacuation shuttle using {ToPrettyString(ent):console}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_roundEnd.CancelRoundEndCountdown(args.Actor);
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Actor):player} has recalled the evacuation shuttle using {ToPrettyString(ent):console}");
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnExfiltrationShuttle(Entity<DVCommunicationsConsoleComponent> ent, ref DVCommunicationsConsoleExfiltrationShuttleMessage args)
|
||||
{
|
||||
base.OnExfiltrationShuttle(ent, ref args);
|
||||
|
||||
if (!AccessReader.IsAllowed(ent, args.Actor))
|
||||
return;
|
||||
|
||||
if (_station.GetOwningStation(ent) is not { } station)
|
||||
return;
|
||||
|
||||
if (args.Call)
|
||||
{
|
||||
_stationExfiltration.Call(station);
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Actor):player} has called the exfiltration shuttle using {ToPrettyString(ent):console}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_stationExfiltration.Recall(station);
|
||||
AdminLog.Add(LogType.Action, LogImpact.High, $"{ToPrettyString(args.Actor):player} has recalled the exfiltration shuttle using {ToPrettyString(ent):console}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Audio.Jukebox;
|
||||
using Content.Server.Instruments;
|
||||
using Content.Server.Light.Components;
|
||||
using Content.Server.Light.EntitySystems;
|
||||
using Content.Server.Nuke;
|
||||
using Content.Server.RoundEnd;
|
||||
using Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
using Content.Shared.Audio.Jukebox;
|
||||
using Content.Shared.Light.Components;
|
||||
using Robust.Server.GameObjects;
|
||||
using Robust.Shared.Prototypes;
|
||||
|
||||
namespace Content.Server._DV.KeycardAuthenticationDevice;
|
||||
|
||||
public sealed class DVStationKeycardAuthenticationDeviceSystem : SharedDVStationKeycardAuthenticationDeviceSystem
|
||||
{
|
||||
[Dependency] private readonly NukeCodePaperSystem _nukeCodePaper = default!;
|
||||
[Dependency] private readonly AlertLevelSystem _alertLevel = default!;
|
||||
[Dependency] private readonly RoundEndSystem _roundEnd = default!;
|
||||
[Dependency] private readonly IPrototypeManager _prototype = default!;
|
||||
[Dependency] private readonly PoweredLightSystem _poweredLight = default!;
|
||||
[Dependency] private readonly PointLightSystem _pointLight = default!;
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _userInterface = default!;
|
||||
[Dependency] private readonly JukeboxSystem _jukebox = default!;
|
||||
|
||||
protected override void Mayday(Entity<DVStationKeycardAuthenticationDeviceComponent> station)
|
||||
{
|
||||
base.Mayday(station);
|
||||
|
||||
_alertLevel.SetLevel(station, "zeta", true, true, true, true);
|
||||
var alertLevel = Comp<AlertLevelComponent>(station);
|
||||
var level = _prototype.Index<AlertLevelPrototype>(alertLevel.AlertLevelPrototype).Levels[alertLevel.CurrentLevel];
|
||||
_roundEnd.RequestRoundEnd(level.ShuttleTime, null, null, false, cantRecall: true);
|
||||
|
||||
var bulbQuery = GetEntityQuery<LightBulbComponent>();
|
||||
var tubeQuery = EntityQueryEnumerator<PoweredLightComponent>();
|
||||
while (tubeQuery.MoveNext(out var uid, out var light))
|
||||
{
|
||||
if (Station.GetOwningStation(uid) != station.Owner)
|
||||
continue;
|
||||
|
||||
if (_poweredLight.GetBulb(uid, light) is not { } bulb || !bulbQuery.TryComp(bulb, out var bulbComp))
|
||||
continue;
|
||||
|
||||
bulbComp.LightEnergy /= 2;
|
||||
bulbComp.PowerUse /= 2;
|
||||
|
||||
_poweredLight.SetState(uid, light.On, light);
|
||||
}
|
||||
|
||||
var emergencyQuery = EntityQueryEnumerator<EmergencyLightComponent, PointLightComponent>();
|
||||
while (emergencyQuery.MoveNext(out var uid, out var emergency, out var light))
|
||||
{
|
||||
if (Station.GetOwningStation(uid) != station.Owner)
|
||||
continue;
|
||||
|
||||
_pointLight.SetEnergy(uid, emergency.MaydayEnergy, light);
|
||||
_pointLight.SetRadius(uid, emergency.MaydayRadius, light);
|
||||
_pointLight.SetFalloff(uid, emergency.MaydayFalloff, light);
|
||||
}
|
||||
|
||||
var instrumentQuery = EntityQueryEnumerator<InstrumentComponent>();
|
||||
while (instrumentQuery.MoveNext(out var uid, out _))
|
||||
{
|
||||
if (Station.GetOwningStation(uid) != station.Owner)
|
||||
continue;
|
||||
|
||||
_userInterface.CloseUis(uid);
|
||||
}
|
||||
|
||||
var jukeboxQuery = EntityQueryEnumerator<JukeboxComponent>();
|
||||
while (jukeboxQuery.MoveNext(out var uid, out var jukebox))
|
||||
{
|
||||
if (Station.GetOwningStation(uid) != station.Owner)
|
||||
continue;
|
||||
|
||||
_jukebox.Stop((uid, jukebox));
|
||||
}
|
||||
}
|
||||
|
||||
protected override void Scuttling(Entity<DVStationKeycardAuthenticationDeviceComponent> station)
|
||||
{
|
||||
base.Scuttling(station);
|
||||
|
||||
_nukeCodePaper.SendNukeCodes(station);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
using Content.Server.AlertLevel;
|
||||
using Content.Server.Screens.Components;
|
||||
using Content.Shared._DV.Communications;
|
||||
using Content.Shared._DV.Screens;
|
||||
using Content.Shared.DeviceNetwork.Events;
|
||||
using Content.Shared.Station;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Server._DV.Screens;
|
||||
|
||||
public sealed class DVScreenSystem : DVSharedScreenSystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] private readonly SharedStationSystem _station = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DVScreenComponent, DeviceNetworkPacketEvent>(OnPacket);
|
||||
SubscribeLocalEvent<AlertLevelChangedEvent>(OnAlertLevelChanged);
|
||||
}
|
||||
|
||||
private void OnPacket(Entity<DVScreenComponent> ent, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
if (args.Data.TryGetValue(ShuttleTimerMasks.ShuttleMap, out _))
|
||||
OnShuttlePacket(ent, ref args);
|
||||
if (args.Data.TryGetValue(DVScreenPackets.Text, out (string, string)? text))
|
||||
OnTextPacket(ent, text.Value, ref args);
|
||||
if (args.Data.TryGetValue(DVScreenPackets.ShowBorders, out bool? showBorders))
|
||||
OnBordersPacket(ent, showBorders.Value, ref args);
|
||||
if (args.Data.TryGetValue(DVScreenPackets.Content, out DVScreenContent? content))
|
||||
OnContentPacket(ent, content.Value, ref args);
|
||||
}
|
||||
|
||||
private void OnShuttlePacket(Entity<DVScreenComponent> ent, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
var xform = Transform(ent);
|
||||
|
||||
args.Data.TryGetValue(ShuttleTimerMasks.ShuttleMap, out EntityUid? shuttleMap);
|
||||
args.Data.TryGetValue(ShuttleTimerMasks.SourceMap, out EntityUid? source);
|
||||
args.Data.TryGetValue(ShuttleTimerMasks.DestMap, out EntityUid? dest);
|
||||
args.Data.TryGetValue(ShuttleTimerMasks.Docked, out bool docked);
|
||||
var screenIsAtDestination = docked;
|
||||
string key;
|
||||
|
||||
switch (xform.MapUid)
|
||||
{
|
||||
// sometimes the timer transforms on FTL shuttles have a hyperspace mapuid, so matching by grid works as a fallback.
|
||||
case var local when local == shuttleMap || xform.GridUid == shuttleMap:
|
||||
key = ShuttleTimerMasks.ShuttleTime;
|
||||
break;
|
||||
case var origin when origin == source:
|
||||
key = ShuttleTimerMasks.SourceTime;
|
||||
break;
|
||||
case var remote when remote == dest:
|
||||
key = ShuttleTimerMasks.DestTime;
|
||||
screenIsAtDestination = false;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
if (!args.Data.TryGetValue(key, out TimeSpan duration))
|
||||
return;
|
||||
|
||||
ent.Comp.ScreenIsAtDestination = screenIsAtDestination;
|
||||
ent.Comp.TargetTime = _timing.CurTime + duration;
|
||||
Dirty(ent);
|
||||
UpdateVisuals(ent);
|
||||
}
|
||||
|
||||
private void OnTextPacket(Entity<DVScreenComponent> ent, (string, string) text, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
ent.Comp.Line1 = text.Item1;
|
||||
ent.Comp.Line2 = text.Item2;
|
||||
|
||||
Dirty(ent);
|
||||
UpdateVisuals(ent);
|
||||
}
|
||||
|
||||
private void OnBordersPacket(Entity<DVScreenComponent> ent, bool showBorders, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
ent.Comp.ShowAlertBorder = showBorders;
|
||||
|
||||
Dirty(ent);
|
||||
UpdateVisuals(ent);
|
||||
}
|
||||
|
||||
private void OnContentPacket(Entity<DVScreenComponent> ent, DVScreenContent content, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
ent.Comp.Content = content;
|
||||
|
||||
Dirty(ent);
|
||||
UpdateVisuals(ent);
|
||||
}
|
||||
|
||||
private void OnAlertLevelChanged(AlertLevelChangedEvent ev)
|
||||
{
|
||||
var query = EntityQueryEnumerator<DVScreenComponent>();
|
||||
while (query.MoveNext(out var uid, out var screen))
|
||||
{
|
||||
if (_station.GetOwningStation(uid) != ev.Station)
|
||||
continue;
|
||||
|
||||
screen.AlertLevel = ev.AlertLevel;
|
||||
Dirty(uid, screen);
|
||||
UpdateVisuals((uid, screen));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,7 +32,6 @@ public sealed class StationExfiltrationSystem : EntitySystem
|
|||
[Dependency] private readonly ShuttleSystem _shuttle = default!;
|
||||
[Dependency] private readonly StationSystem _station = default!;
|
||||
[Dependency] private readonly NavMapSystem _navMap = default!;
|
||||
[Dependency] private readonly CommunicationsConsoleSystem _communicationsConsole = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
|
|
@ -169,7 +168,8 @@ public sealed class StationExfiltrationSystem : EntitySystem
|
|||
_chat.DispatchStationAnnouncement(ent, Loc.GetString(ent.Comp.CalledAnnouncement, ("time", ent.Comp.TravelTime.TotalSeconds), ("station", Name(ent))), sender: Loc.GetString(ent.Comp.Sender), colorOverride: Color.Gold);
|
||||
}
|
||||
|
||||
_communicationsConsole.UpdateCommsConsoleInterface();
|
||||
var evt = new StationExfiltrationChangedEvent((ent, ent.Comp), true);
|
||||
RaiseLocalEvent(ref evt);
|
||||
}
|
||||
|
||||
public void Recall(Entity<StationExfiltrationComponent?> ent)
|
||||
|
|
@ -180,6 +180,10 @@ public sealed class StationExfiltrationSystem : EntitySystem
|
|||
ent.Comp.ArrivalTime = null;
|
||||
_chat.DispatchStationAnnouncement(ent, Loc.GetString(ent.Comp.RecalledAnnouncement, ("station", Name(ent))), sender: Loc.GetString(ent.Comp.Sender), colorOverride: Color.Gold);
|
||||
|
||||
_communicationsConsole.UpdateCommsConsoleInterface();
|
||||
var evt = new StationExfiltrationChangedEvent((ent, ent.Comp), false);
|
||||
RaiseLocalEvent(ref evt);
|
||||
}
|
||||
}
|
||||
|
||||
[ByRefEvent]
|
||||
public readonly record struct StationExfiltrationChangedEvent(Entity<StationExfiltrationComponent> Station, bool Exfiltrating);
|
||||
|
|
|
|||
|
|
@ -18,9 +18,8 @@ namespace Content.Shared.Communications
|
|||
public List<string>? AlertLevels;
|
||||
public string CurrentAlert;
|
||||
public float CurrentAlertDelay;
|
||||
public readonly TimeSpan? ExpectedExfiltrationCountdownEnd;
|
||||
|
||||
public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canCall, List<string>? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd, TimeSpan? expectedExfiltrationCountdownEnd) // DeltaV - Exfiltration Shuttle
|
||||
public CommunicationsConsoleInterfaceState(bool canAnnounce, bool canCall, List<string>? alertLevels, string currentAlert, float currentAlertDelay, TimeSpan? expectedCountdownEnd)
|
||||
{
|
||||
CanAnnounce = canAnnounce;
|
||||
CanCall = canCall;
|
||||
|
|
@ -29,7 +28,6 @@ namespace Content.Shared.Communications
|
|||
AlertLevels = alertLevels;
|
||||
CurrentAlert = currentAlert;
|
||||
CurrentAlertDelay = currentAlertDelay;
|
||||
ExpectedExfiltrationCountdownEnd = expectedExfiltrationCountdownEnd; // DeltaV - Exfiltration Shuttle
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Communications;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class CommunicationsConsoleExfiltrationShuttleMessage(bool call) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly bool Call = call;
|
||||
}
|
||||
|
|
@ -0,0 +1,136 @@
|
|||
using Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
using Content.Shared._DV.Screens;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Communications;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true)]
|
||||
[Access(typeof(SharedDVCommunicationsConsoleSystem))]
|
||||
public sealed partial class DVCommunicationsConsoleComponent : Component
|
||||
{
|
||||
[DataField]
|
||||
public LocId AnnouncementTitle = "comms-console-announcement-title-station";
|
||||
|
||||
[DataField]
|
||||
public Color AnnouncementColor = Color.Gold;
|
||||
|
||||
[DataField]
|
||||
public SoundSpecifier AnnouncementSound = new SoundPathSpecifier("/Audio/Announcements/announce.ogg");
|
||||
|
||||
[DataField]
|
||||
public bool GlobalAnnouncements;
|
||||
|
||||
[DataField]
|
||||
public bool CanAnnounce = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanAlertLevel = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanCallShuttles = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanConfigureScreens = true;
|
||||
|
||||
[DataField]
|
||||
public bool CanKeycardAuthenticationDevice = true;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan CanAnnounceAt = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan AnnouncementInterval = TimeSpan.FromSeconds(90f);
|
||||
|
||||
[DataField]
|
||||
public TimeSpan InitialAnnouncementDelay = TimeSpan.FromSeconds(30f);
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public string CurrentAlertLevel = string.Empty;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public List<DVCommunicationsConsoleAlertLevel> AlertLevels = new();
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan? CanSetAlertAt = TimeSpan.Zero;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool ShuttlesCallable = true;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan? ExpectedEvacuationArrival;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan? ExpectedEvacuationDuration;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public TimeSpan? ExpectedExfiltrationArrival;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public DVScreenContent LastConfiguredContent = DVScreenContent.Text;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool LastConfiguredShowBorders;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public string LastConfiguredLine1 = string.Empty;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public string LastConfiguredLine2 = string.Empty;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public readonly record struct DVCommunicationsConsoleAlertLevel(LocId AlertLevel, LocId Description, string Id, bool CanSet, Color Color);
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleEvacuationShuttleMessage(bool call) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly bool Call = call;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleExfiltrationShuttleMessage(bool call) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly bool Call = call;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleKeycardAuthenticationDeviceMessage(DVStationKeycardAction action) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly DVStationKeycardAction Action = action;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleAnnouncementMessage(string announcement) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string Announcement = announcement;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleAlertLevelMessage(string alertLevel) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly string AlertLevel = alertLevel;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public sealed class DVCommunicationsConsoleScreenConfigurationMessage(DVScreenContent content, bool showBorder, string line1, string line2) : BoundUserInterfaceMessage
|
||||
{
|
||||
public readonly DVScreenContent Content = content;
|
||||
public readonly bool ShowBorder = showBorder;
|
||||
public readonly string Line1 = line1;
|
||||
public readonly string Line2 = line2;
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DVCommunicationsConsoleUi : byte
|
||||
{
|
||||
Key,
|
||||
}
|
||||
|
||||
public static class DVScreenPackets
|
||||
{
|
||||
public const string Content = "dv-screen-content";
|
||||
public const string ShowBorders = "dv-screen-borders";
|
||||
public const string Text = "dv-screen-text";
|
||||
}
|
||||
|
|
@ -0,0 +1,148 @@
|
|||
using Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
using Content.Shared._DV.Screens;
|
||||
using Content.Shared.Access.Systems;
|
||||
using Content.Shared.Administration.Logs;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Database;
|
||||
using Content.Shared.DeviceNetwork;
|
||||
using Content.Shared.DeviceNetwork.Events;
|
||||
using Content.Shared.DeviceNetwork.Systems;
|
||||
using Content.Shared.IdentityManagement;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._DV.Communications;
|
||||
|
||||
public abstract class SharedDVCommunicationsConsoleSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedDeviceNetworkSystem _deviceNetwork = default!;
|
||||
[Dependency] protected readonly IGameTiming Timing = default!;
|
||||
[Dependency] private readonly SharedChatSystem _chat = default!;
|
||||
[Dependency] protected readonly AccessReaderSystem AccessReader = default!;
|
||||
[Dependency] protected readonly ISharedAdminLogManager AdminLog = default!;
|
||||
[Dependency] private readonly SharedDVStationKeycardAuthenticationDeviceSystem _stationKeycardAuthenticationDevice = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<DVCommunicationsConsoleComponent, MapInitEvent>(OnMapInit);
|
||||
SubscribeLocalEvent<DVCommunicationsConsoleComponent, DeviceNetworkPacketEvent>(OnPacketReceive);
|
||||
Subs.BuiEvents<DVCommunicationsConsoleComponent>(DVCommunicationsConsoleUi.Key,
|
||||
subs =>
|
||||
{
|
||||
subs.Event<DVCommunicationsConsoleEvacuationShuttleMessage>(OnEvacuationShuttle);
|
||||
subs.Event<DVCommunicationsConsoleExfiltrationShuttleMessage>(OnExfiltrationShuttle);
|
||||
subs.Event<DVCommunicationsConsoleScreenConfigurationMessage>(OnConfiguration);
|
||||
subs.Event<DVCommunicationsConsoleAnnouncementMessage>(OnAnnouncement);
|
||||
subs.Event<DVCommunicationsConsoleAlertLevelMessage>(OnAlertLevel);
|
||||
subs.Event<DVCommunicationsConsoleKeycardAuthenticationDeviceMessage>(OnKeycardAuthenticationDevice);
|
||||
});
|
||||
}
|
||||
|
||||
private void OnPacketReceive(Entity<DVCommunicationsConsoleComponent> ent, ref DeviceNetworkPacketEvent args)
|
||||
{
|
||||
if (args.Data.TryGetValue(DVScreenPackets.Text, out (string, string)? text))
|
||||
{
|
||||
ent.Comp.LastConfiguredLine1 = text.Value.Item1;
|
||||
ent.Comp.LastConfiguredLine2 = text.Value.Item2;
|
||||
Dirty(ent);
|
||||
}
|
||||
if (args.Data.TryGetValue(DVScreenPackets.ShowBorders, out bool? showBorders))
|
||||
{
|
||||
ent.Comp.LastConfiguredShowBorders = showBorders.Value;
|
||||
Dirty(ent);
|
||||
}
|
||||
if (args.Data.TryGetValue(DVScreenPackets.Content, out DVScreenContent? content))
|
||||
{
|
||||
ent.Comp.LastConfiguredContent = content.Value;
|
||||
Dirty(ent);
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void OnMapInit(Entity<DVCommunicationsConsoleComponent> ent, ref MapInitEvent args)
|
||||
{
|
||||
ent.Comp.CanAnnounceAt = Timing.CurTime + ent.Comp.InitialAnnouncementDelay;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnAnnouncement(Entity<DVCommunicationsConsoleComponent> ent, ref DVCommunicationsConsoleAnnouncementMessage args)
|
||||
{
|
||||
if (!ent.Comp.CanAnnounce)
|
||||
return;
|
||||
|
||||
if (Timing.CurTime <= ent.Comp.CanAnnounceAt)
|
||||
return;
|
||||
|
||||
if (!AccessReader.IsAllowed(args.Actor, ent))
|
||||
return;
|
||||
|
||||
var identity = new TryGetIdentityShortInfoEvent(ent, args.Actor);
|
||||
RaiseLocalEvent(identity);
|
||||
|
||||
Loc.TryGetString(ent.Comp.AnnouncementTitle, out var title);
|
||||
title ??= ent.Comp.AnnouncementTitle;
|
||||
|
||||
var msg = args.Announcement;
|
||||
msg += "\n" + Loc.GetString("comms-console-announcement-sent-by") + " " + identity.Title;
|
||||
|
||||
if (ent.Comp.GlobalAnnouncements)
|
||||
{
|
||||
_chat.DispatchGlobalAnnouncement(msg, title, announcementSound: ent.Comp.AnnouncementSound, colorOverride: ent.Comp.AnnouncementColor);
|
||||
AdminLog.Add(LogType.Chat, LogImpact.Low, $"{ToPrettyString(args.Actor):player} sent the following global announcement using {ToPrettyString(ent):console}: {msg:message}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_chat.DispatchStationAnnouncement(ent, msg, title, announcementSound: ent.Comp.AnnouncementSound, colorOverride: ent.Comp.AnnouncementColor);
|
||||
AdminLog.Add(LogType.Chat, LogImpact.Low, $"{ToPrettyString(args.Actor):player} sent the following station announcement using {ToPrettyString(ent):console}: {msg:message}");
|
||||
}
|
||||
|
||||
ent.Comp.CanAnnounceAt = Timing.CurTime + ent.Comp.AnnouncementInterval;
|
||||
Dirty(ent);
|
||||
}
|
||||
|
||||
private void OnConfiguration(Entity<DVCommunicationsConsoleComponent> ent, ref DVCommunicationsConsoleScreenConfigurationMessage args)
|
||||
{
|
||||
if (!ent.Comp.CanConfigureScreens)
|
||||
return;
|
||||
|
||||
if (!AccessReader.IsAllowed(args.Actor, ent))
|
||||
return;
|
||||
|
||||
ent.Comp.LastConfiguredLine1 = args.Line1;
|
||||
ent.Comp.LastConfiguredLine2 = args.Line2;
|
||||
ent.Comp.LastConfiguredShowBorders = args.ShowBorder;
|
||||
ent.Comp.LastConfiguredContent = args.Content;
|
||||
Dirty(ent);
|
||||
|
||||
var payload = new NetworkPayload
|
||||
{
|
||||
[DVScreenPackets.Content] = args.Content,
|
||||
[DVScreenPackets.ShowBorders] = args.ShowBorder,
|
||||
[DVScreenPackets.Text] = (args.Line1, args.Line2),
|
||||
};
|
||||
|
||||
AdminLog.Add(LogType.Chat, LogImpact.Low, $"{ToPrettyString(args.Actor):player} configured the following text using {ToPrettyString(ent):console}: {args.Line1:line1} {args.Line2:line2}");
|
||||
_deviceNetwork.QueuePacket(ent, null, payload);
|
||||
}
|
||||
|
||||
protected virtual void OnExfiltrationShuttle(Entity<DVCommunicationsConsoleComponent> ent,
|
||||
ref DVCommunicationsConsoleExfiltrationShuttleMessage args)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnEvacuationShuttle(Entity<DVCommunicationsConsoleComponent> ent,
|
||||
ref DVCommunicationsConsoleEvacuationShuttleMessage args)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void OnAlertLevel(Entity<DVCommunicationsConsoleComponent> ent,
|
||||
ref DVCommunicationsConsoleAlertLevelMessage args)
|
||||
{
|
||||
}
|
||||
|
||||
private void OnKeycardAuthenticationDevice(Entity<DVCommunicationsConsoleComponent> ent,
|
||||
ref DVCommunicationsConsoleKeycardAuthenticationDeviceMessage args)
|
||||
{
|
||||
_stationKeycardAuthenticationDevice.TrySwipe(args.Actor, ent, args.Action);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
using Robust.Shared.GameStates;
|
||||
|
||||
namespace Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
|
||||
[RegisterComponent, NetworkedComponent]
|
||||
[Access(typeof(SharedDVStationKeycardAuthenticationDeviceSystem))]
|
||||
public sealed partial class DVStationKeycardAuthenticationDeviceAlreadySwipedComponent : Component;
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom;
|
||||
|
||||
namespace Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState, AutoGenerateComponentPause]
|
||||
[Access(typeof(SharedDVStationKeycardAuthenticationDeviceSystem))]
|
||||
public sealed partial class DVStationKeycardAuthenticationDeviceComponent : Component
|
||||
{
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan AccessibleAfter = TimeSpan.Zero;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan FailureDelay = TimeSpan.FromMinutes(2);
|
||||
|
||||
[DataField(customTypeSerializer: typeof(TimeOffsetSerializer)), AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan? SwipesStartedAt = null;
|
||||
|
||||
[DataField]
|
||||
public TimeSpan SwipeWindow = TimeSpan.FromSeconds(10);
|
||||
|
||||
[DataField(required: true)]
|
||||
public Dictionary<DVStationKeycardAction, int> ActionThresholds;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public int Swipes;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public DVStationKeycardAction? SwipingFor;
|
||||
|
||||
[DataField]
|
||||
public LocId FailureAnnouncementSender = "keycard-authentication-device-sender";
|
||||
|
||||
[DataField]
|
||||
public LocId FailureAnnouncement = "keycard-authentication-device-warning";
|
||||
|
||||
[DataField]
|
||||
public Color FailureAnnouncementColor = Color.FromHex("#e93a9a");
|
||||
|
||||
[DataField]
|
||||
public TimeSpan FailureElectrocutionDuration = TimeSpan.FromSeconds(5);
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DVStationKeycardAction
|
||||
{
|
||||
Mayday,
|
||||
Scuttling,
|
||||
}
|
||||
|
|
@ -0,0 +1,118 @@
|
|||
using Content.Shared.Chat;
|
||||
using Content.Shared.Electrocution;
|
||||
using Content.Shared.Station;
|
||||
using Robust.Shared.Audio;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Shared._DV.KeycardAuthenticationDevice;
|
||||
|
||||
public abstract class SharedDVStationKeycardAuthenticationDeviceSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
[Dependency] protected readonly SharedStationSystem Station = default!;
|
||||
[Dependency] private readonly SharedElectrocutionSystem _electrocution = default!;
|
||||
[Dependency] private readonly SharedChatSystem _chat = default!;
|
||||
|
||||
public override void Update(float frameTime)
|
||||
{
|
||||
base.Update(frameTime);
|
||||
|
||||
var query = EntityQueryEnumerator<DVStationKeycardAuthenticationDeviceComponent>();
|
||||
while (query.MoveNext(out var uid, out var keycard))
|
||||
{
|
||||
if (keycard.SwipesStartedAt is not { } startedAt || _timing.CurTime <= startedAt + keycard.SwipeWindow)
|
||||
continue;
|
||||
|
||||
StopSwipes((uid, keycard), true);
|
||||
}
|
||||
}
|
||||
|
||||
private void StopSwipes(Entity<DVStationKeycardAuthenticationDeviceComponent> station, bool failed)
|
||||
{
|
||||
station.Comp.SwipesStartedAt = null;
|
||||
station.Comp.Swipes = 0;
|
||||
station.Comp.SwipingFor = null;
|
||||
if (failed)
|
||||
{
|
||||
station.Comp.AccessibleAfter = _timing.CurTime + station.Comp.FailureDelay;
|
||||
_chat.DispatchStationAnnouncement(station,
|
||||
Loc.GetString(station.Comp.FailureAnnouncement),
|
||||
Loc.GetString(station.Comp.FailureAnnouncementSender),
|
||||
announcementSound: new SoundPathSpecifier("/Audio/_DV/Announcements/attention.ogg"),
|
||||
colorOverride: station.Comp.FailureAnnouncementColor);
|
||||
}
|
||||
Dirty(station);
|
||||
|
||||
var query = EntityQueryEnumerator<DVStationKeycardAuthenticationDeviceAlreadySwipedComponent>();
|
||||
while (query.MoveNext(out var uid, out _))
|
||||
{
|
||||
if (failed)
|
||||
{
|
||||
_electrocution.TryDoElectrocution(uid,
|
||||
null,
|
||||
10,
|
||||
station.Comp.FailureElectrocutionDuration,
|
||||
true,
|
||||
ignoreInsulation: true);
|
||||
}
|
||||
RemCompDeferred<DVStationKeycardAuthenticationDeviceAlreadySwipedComponent>(uid);
|
||||
}
|
||||
}
|
||||
|
||||
private void Swipe(Entity<DVStationKeycardAuthenticationDeviceComponent> station, EntityUid user, DVStationKeycardAction action)
|
||||
{
|
||||
if (!station.Comp.ActionThresholds.TryGetValue(action, out var threshold))
|
||||
return;
|
||||
|
||||
station.Comp.SwipesStartedAt ??= _timing.CurTime;
|
||||
station.Comp.SwipingFor = action;
|
||||
station.Comp.Swipes++;
|
||||
AddComp<DVStationKeycardAuthenticationDeviceAlreadySwipedComponent>(user);
|
||||
Dirty(station);
|
||||
|
||||
if (station.Comp.Swipes >= threshold)
|
||||
{
|
||||
StopSwipes(station, false);
|
||||
DoAction(station, action);
|
||||
}
|
||||
}
|
||||
|
||||
private void DoAction(Entity<DVStationKeycardAuthenticationDeviceComponent> station, DVStationKeycardAction action)
|
||||
{
|
||||
switch (action)
|
||||
{
|
||||
case DVStationKeycardAction.Mayday:
|
||||
Mayday(station);
|
||||
break;
|
||||
|
||||
case DVStationKeycardAction.Scuttling:
|
||||
Scuttling(station);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
protected virtual void Mayday(Entity<DVStationKeycardAuthenticationDeviceComponent> station)
|
||||
{
|
||||
}
|
||||
|
||||
protected virtual void Scuttling(Entity<DVStationKeycardAuthenticationDeviceComponent> station)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrySwipe(EntityUid user, EntityUid console, DVStationKeycardAction action)
|
||||
{
|
||||
if (HasComp<DVStationKeycardAuthenticationDeviceAlreadySwipedComponent>(console))
|
||||
return;
|
||||
|
||||
if (Station.GetOwningStation(user) is not { } station || !TryComp<DVStationKeycardAuthenticationDeviceComponent>(station, out var keycard))
|
||||
return;
|
||||
|
||||
if (keycard.SwipingFor is { } swipingFor && swipingFor != action)
|
||||
return;
|
||||
|
||||
if (_timing.CurTime <= keycard.AccessibleAfter)
|
||||
return;
|
||||
|
||||
Swipe((station, keycard), user, action);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Screens;
|
||||
|
||||
[RegisterComponent, NetworkedComponent, AutoGenerateComponentState(true), AutoGenerateComponentPause]
|
||||
[Access(typeof(DVSharedScreenSystem))]
|
||||
public sealed partial class DVScreenComponent : Component
|
||||
{
|
||||
[DataField, AutoNetworkedField]
|
||||
public string? AlertLevel; // I don't like this but uhhh the prototype isn't client-accessible
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool ShowAlertBorder;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public DVScreenContent Content = DVScreenContent.Text;
|
||||
|
||||
#region Text Screens
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public string Line1 = string.Empty;
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public string Line2 = string.Empty;
|
||||
|
||||
#endregion
|
||||
|
||||
#region ETA Screens
|
||||
|
||||
[DataField, AutoNetworkedField]
|
||||
public bool ScreenIsAtDestination;
|
||||
|
||||
[DataField, AutoNetworkedField, AutoPausedField]
|
||||
public TimeSpan TargetTime = TimeSpan.Zero;
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DVScreenVisuals : byte
|
||||
{
|
||||
AlertLevel,
|
||||
ShowAlertBorder,
|
||||
Content,
|
||||
}
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DVScreenContent : byte
|
||||
{
|
||||
Text,
|
||||
CurrentTime,
|
||||
EstimatedTimeOfArrival,
|
||||
AlertLevel,
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
namespace Content.Shared._DV.Screens;
|
||||
|
||||
public abstract class DVSharedScreenSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
|
||||
protected void UpdateVisuals(Entity<DVScreenComponent> ent)
|
||||
{
|
||||
_appearance.SetData(ent.Owner, DVScreenVisuals.AlertLevel, ent.Comp.AlertLevel ?? string.Empty);
|
||||
_appearance.SetData(ent.Owner, DVScreenVisuals.ShowAlertBorder, ent.Comp.ShowAlertBorder);
|
||||
_appearance.SetData(ent.Owner, DVScreenVisuals.Content, ent.Comp.Content);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
using Robust.Shared.Serialization;
|
||||
|
||||
namespace Content.Shared._DV.Screens;
|
||||
|
||||
[Serializable, NetSerializable]
|
||||
public enum DVTextScreenVisualLayers : byte
|
||||
{
|
||||
Line1,
|
||||
Line2,
|
||||
}
|
||||
|
|
@ -1,5 +1,60 @@
|
|||
comms-console-announcement-title-unauthorized = Unauthorized
|
||||
comms-console-menu-call-exfiltration = Call exfiltration shuttle
|
||||
comms-console-menu-exfiltration-shuttle-button-tooltip = Calls or recalls the exfiltration shuttle.
|
||||
comms-console-menu-exfiltration-time-remaining = ETA of exfiltration shuttle: {$time}
|
||||
comms-console-menu-recall-exfiltration = Recall exfiltration shuttle
|
||||
|
||||
comms-console-menu-screen-content =
|
||||
.Text = Text
|
||||
.CurrentTime = Current Time
|
||||
.EstimatedTimeOfArrival = ETA / ETD
|
||||
.AlertLevel = Alert Level
|
||||
|
||||
comms-console-menu-tab =
|
||||
.Announcement = Make an announcement
|
||||
.Screen = Configure status displays
|
||||
.Shuttles = Manage shuttles
|
||||
.AlertLevel = Set the alert level
|
||||
.KeycardAuthenticationDevice = Keycard Authentication Device
|
||||
|
||||
comms-console-menu-line-1 = Line 1:
|
||||
comms-console-menu-line-2 = Line 2:
|
||||
comms-console-menu-alert-level-border = Alert level border:
|
||||
comms-console-menu-alert-level = Alert level
|
||||
comms-console-menu-screen-contents = Screen contents:
|
||||
comms-console-menu-send-announcement = Send announcement
|
||||
comms-console-menu-update-screen-text = Update text
|
||||
comms-console-menu-enable-border = Enable alert level border
|
||||
comms-console-menu-home = Home
|
||||
comms-console-menu-emergency-shuttle = Emergency shuttle
|
||||
comms-console-menu-exfiltration-shuttle = Exfiltration shuttle
|
||||
comms-console-menu-shuttle-not-coming = This shuttle is not currently requested.
|
||||
comms-console-menu-shuttle-eta = This shuttle will arrive in {$time}.
|
||||
comms-console-menu-screen-text = Screen text
|
||||
comms-console-menu-screen-configuration = Screen options
|
||||
|
||||
comms-console-menu-current-alert-level = The current alert level is [color={$color}]{$name}[/color]. {$description}
|
||||
comms-console-menu-change-alert-level = Change alert level
|
||||
|
||||
comms-console-menu-station-title = Station
|
||||
comms-console-menu-transit-title = Transit
|
||||
comms-console-menu-emergency-title = Emergency
|
||||
|
||||
comms-console-menu-declare-mayday =
|
||||
.title = Declare mayday
|
||||
.desc = Declare the station unfit for life and send out a distress signal to all nearby vessels. Requires two simultaneous authorizations.
|
||||
.button = Declare Code Sigma
|
||||
|
||||
comms-console-menu-request-codes =
|
||||
.title = Scuttle the station
|
||||
.desc = Order the destruction of the station to prevent capture, containment breach, or further threats to the sector. Requires three simultaneous authorizations.
|
||||
.button = Request nuclear authorization codes
|
||||
|
||||
comms-console-menu-call-emergency =
|
||||
.True = Call emergency shuttle
|
||||
.False = Recall emergency shuttle
|
||||
|
||||
comms-console-menu-call-exfiltration =
|
||||
.True = Call exfiltration shuttle
|
||||
.False = Recall exfiltration shuttle
|
||||
|
||||
comms-console-menu-announcement-text = Announcement text
|
||||
|
|
|
|||
|
|
@ -0,0 +1,2 @@
|
|||
keycard-authentication-device-sender = Keycard Authentication Device
|
||||
keycard-authentication-device-warning = Unauthorized user(s) of the keycard authentication device detected. Administering deterrence measures and initiating cooldown.
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
status-display-eta = -ETA-
|
||||
status-display-etd = -ETD-
|
||||
status-display-time = TIME
|
||||
|
|
@ -1,3 +0,0 @@
|
|||
alert-level-orange = Orange
|
||||
alert-level-orange-announcement = There is a critical station-wide structural or atmospheric threat and recovery is unlikely. Engineering staff are advised to minimize hazards and secure the Evacuation Dock. Crewmembers are advised to stay away from hazardous areas, and prepare for Evacuation. MAYDAY signals have been activated
|
||||
alert-level-orange-instructions = Avoid hazards and prepare for Evacuation.
|
||||
|
|
@ -45,3 +45,7 @@ alert-level-octarine = Octarine
|
|||
alert-level-octarine-announcement = A cataclysmic noospheric event threatens to envelop realspace. Station crew are to contain the event if possible, or else evacuate.
|
||||
alert-level-octarine-instructions = Crewmembers are advised to listen to heads of staff for more information.
|
||||
|
||||
## DeltaV - Zeta
|
||||
alert-level-zeta = Zeta
|
||||
alert-level-zeta-announcement = The station is unrecoverable, and all important assets and crewmembers are to be evacuated. A distress signal has been sent to all nearby vessels. Security and Engineering staff are advised to minimize hazards and secure the Evacuation Dock. Crewmembers are advised to disembark the station by any means necessary. Godspeed.
|
||||
alert-level-zeta-instructions = Avoid hazards and prepare for Evacuation.
|
||||
|
|
|
|||
|
|
@ -28978,8 +28978,6 @@ entities:
|
|||
- type: Transform
|
||||
pos: 12.5,39.5
|
||||
parent: 8
|
||||
- type: CommunicationsConsole
|
||||
announcementCooldownRemaining: -0.0166666
|
||||
- proto: ComputerCrewMonitoring
|
||||
entities:
|
||||
- uid: 678
|
||||
|
|
|
|||
|
|
@ -250,4 +250,8 @@ BoxPerformer: BoxPerformerDV
|
|||
|
||||
# 2026-07-04
|
||||
SpawnPointMedicalBorg: SpawnPointBorg
|
||||
SpawnPointSecurityBorg: SpawnPointBorg
|
||||
SpawnPointSecurityBorg: SpawnPointBorg
|
||||
|
||||
# 2026-06-02
|
||||
Screen: StatusDisplay
|
||||
ArrivalsShuttleTimer: StatusDisplayShuttle
|
||||
|
|
|
|||
|
|
@ -43,17 +43,6 @@
|
|||
emergencyLightColor: Red
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 600 #No reduction in time as we don't have swiping for red alert like in /tg/. Shuttle times are intended to create friction, so having a way to brainlessly bypass that would be dumb.
|
||||
# Begin Starlight Additions
|
||||
orange:
|
||||
announcement: alert-level-orange-announcement
|
||||
selectable: true
|
||||
sound:
|
||||
path: /Audio/_Starlight/misc/orange.ogg
|
||||
color: "#ff8119"
|
||||
emergencyLightColor: "#ff8119"
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 480
|
||||
# End Starlight Additions
|
||||
gamma:
|
||||
announcement: alert-level-gamma-announcement
|
||||
selectable: false
|
||||
|
|
@ -90,3 +79,13 @@
|
|||
emergencyLightColor: CadetBlue
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 600
|
||||
zeta: # DeltaV - zeta
|
||||
announcement: alert-level-zeta-announcement
|
||||
selectable: false
|
||||
disableSelection: true
|
||||
sound:
|
||||
path: /Audio/_DV/Announcements/Alerts/code_zeta.ogg
|
||||
color: "#fe8401"
|
||||
emergencyLightColor: "#fe8401"
|
||||
forceEnableEmergencyLights: true
|
||||
shuttleTime: 480
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
- BaseStationStockMarket
|
||||
- BaseStationLavaland
|
||||
- BaseStationExfiltration
|
||||
- BaseStationKeycardAuthenticationDevice
|
||||
# End DeltaV - Station additions
|
||||
categories: [ HideSpawnMenu ]
|
||||
components:
|
||||
|
|
|
|||
|
|
@ -695,17 +695,22 @@
|
|||
state: generic_panel_open
|
||||
- type: AccessReader
|
||||
access: [[ "Command" ]]
|
||||
- type: CommunicationsConsole
|
||||
title: comms-console-announcement-title-station
|
||||
# Begin DeltaV Removals - our own thing
|
||||
# - type: CommunicationsConsole
|
||||
# title: comms-console-announcement-title-station
|
||||
# End DeltaV Removals - our own thing
|
||||
- type: DVCommunicationsConsole # DeltaV - new functionality
|
||||
announcementTitle: comms-console-announcement-title-station
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
transmitFrequencyId: ShuttleTimer
|
||||
receiveFrequencyId: ShuttleTimer # DeltaV - new functionality
|
||||
- type: ActivatableUI
|
||||
key: enum.CommunicationsConsoleUiKey.Key
|
||||
key: enum.DVCommunicationsConsoleUi.Key # DeltaV - new UI
|
||||
- type: UserInterface
|
||||
interfaces:
|
||||
enum.CommunicationsConsoleUiKey.Key:
|
||||
type: CommunicationsConsoleBoundUserInterface
|
||||
enum.DVCommunicationsConsoleUi.Key: # DeltaV - new UI
|
||||
type: DVCommunicationsConsoleBoundUserInterface
|
||||
enum.WiresUiKey.Key:
|
||||
type: WiresBoundUserInterface
|
||||
- type: Computer
|
||||
|
|
@ -741,13 +746,25 @@
|
|||
state: generic_panel_open
|
||||
- type: AccessReader
|
||||
access: [[ "NuclearOperative" ]]
|
||||
- type: CommunicationsConsole
|
||||
title: comms-console-announcement-title-unauthorized # DeltaV
|
||||
color: "#ff0000"
|
||||
canShuttle: false
|
||||
global: true #announce to everyone they're about to fuck shit up
|
||||
sound: /Audio/Announcements/intercept.ogg # DeltaV
|
||||
announceSentBy: false # The title already says who they are.
|
||||
# Begin DeltaV Changes
|
||||
# - type: CommunicationsConsole
|
||||
# title: comms-console-announcement-title-unauthorized # DeltaV
|
||||
# color: "#ff0000"
|
||||
# canShuttle: false
|
||||
# global: true #announce to everyone they're about to fuck shit up
|
||||
# sound: /Audio/Announcements/intercept.ogg # DeltaV
|
||||
# announceSentBy: false # The title already says who they are.
|
||||
- type: DVCommunicationsConsole
|
||||
announcementTitle: comms-console-announcement-title-unauthorized
|
||||
announcementColor: "#ff0000"
|
||||
announcementSound:
|
||||
path: /Audio/Announcements/intercept.ogg
|
||||
canAlertLevel: false
|
||||
canCallShuttles: false
|
||||
canConfigureScreens: false
|
||||
canKeycardAuthenticationDevice: false
|
||||
globalAnnouncements: true
|
||||
# End DeltaV Changes
|
||||
- type: Computer
|
||||
board: SyndicateCommsComputerCircuitboard
|
||||
- type: PointLight
|
||||
|
|
@ -775,13 +792,23 @@
|
|||
state: generic_panel_open
|
||||
- type: AccessReader
|
||||
access: [[ "Wizard" ]]
|
||||
- type: CommunicationsConsole
|
||||
title: comms-console-announcement-title-wizard
|
||||
color: "#ff00ff"
|
||||
canShuttle: false
|
||||
global: true #announce to everyone they're about to fuck shit up
|
||||
announceSentBy: false
|
||||
sound: /Audio/Announcements/announce.ogg # DeltaV - changed from war.oog to announce.ogg
|
||||
# Begin DeltaV Changes
|
||||
# - type: CommunicationsConsole
|
||||
# title: comms-console-announcement-title-wizard
|
||||
# color: "#ff00ff"
|
||||
# canShuttle: false
|
||||
# global: true #announce to everyone they're about to fuck shit up
|
||||
# announceSentBy: false
|
||||
# sound: /Audio/Announcements/announce.ogg # DeltaV - changed from war.oog to announce.ogg
|
||||
- type: DVCommunicationsConsole
|
||||
announcementTitle: comms-console-announcement-title-wizard
|
||||
announcementColor: "#ff00ff"
|
||||
canAlertLevel: false
|
||||
canCallShuttles: false
|
||||
canConfigureScreens: false
|
||||
canKeycardAuthenticationDevice: false
|
||||
globalAnnouncements: true
|
||||
# End DeltaV Changes
|
||||
- type: Computer
|
||||
board: WizardCommsComputerCircuitboard
|
||||
- type: PointLight
|
||||
|
|
@ -809,11 +836,21 @@
|
|||
state: generic_panel_open
|
||||
- type: AccessReader
|
||||
access: [[ "CentralCommand" ]]
|
||||
- type: CommunicationsConsole
|
||||
title: comms-console-announcement-title-centcom
|
||||
color: "#1d8bad"
|
||||
canShuttle: false
|
||||
global: true
|
||||
# Begin DeltaV Changes
|
||||
# - type: CommunicationsConsole
|
||||
# title: comms-console-announcement-title-centcom
|
||||
# color: "#1d8bad"
|
||||
# canShuttle: false
|
||||
# global: true
|
||||
- type: DVCommunicationsConsole
|
||||
announcementTitle: comms-console-announcement-title-centcom
|
||||
announcementColor: "#1d8bad"
|
||||
canAlertLevel: false
|
||||
canCallShuttles: false
|
||||
canConfigureScreens: false
|
||||
canKeycardAuthenticationDevice: false
|
||||
globalAnnouncements: true
|
||||
# End DeltaV Changes
|
||||
- type: Computer
|
||||
board: CentcommCommsComputerCircuitboard
|
||||
- type: PointLight
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
- type: entity
|
||||
categories: [ HideSpawnMenu ] # DeltaV - use the other one
|
||||
parent: BaseWallmountMachine
|
||||
id: Screen
|
||||
name: screen
|
||||
|
|
@ -35,6 +36,7 @@
|
|||
receiveFrequencyId: ShuttleTimer
|
||||
|
||||
- type: entity
|
||||
categories: [ HideSpawnMenu ] # DeltaV - use the other one
|
||||
id: ArrivalsShuttleTimer
|
||||
parent: Screen
|
||||
name: arrivals screen
|
||||
|
|
|
|||
|
|
@ -42,3 +42,12 @@
|
|||
- type: StationPlanetSpawner
|
||||
planet: Lavaland
|
||||
gridPath: /Maps/_DV/Nonstations/lavaland_mining_base.yml
|
||||
|
||||
- type: entity
|
||||
abstract: true
|
||||
id: BaseStationKeycardAuthenticationDevice
|
||||
components:
|
||||
- type: DVStationKeycardAuthenticationDevice
|
||||
actionThresholds:
|
||||
Mayday: 2
|
||||
Scuttling: 3
|
||||
|
|
|
|||
|
|
@ -0,0 +1,105 @@
|
|||
- type: entity
|
||||
parent: BaseWallmountMachine
|
||||
id: StatusDisplay
|
||||
name: status display
|
||||
description: Displays the current status of the station.
|
||||
components:
|
||||
- type: Rotatable
|
||||
- type: DVTextVisuals
|
||||
rows:
|
||||
- text: ""
|
||||
layer: enum.DVTextScreenVisualLayers.Line1
|
||||
offset: 0.03125,0.15625 # 1/32, 5/32
|
||||
- text: ""
|
||||
layer: enum.DVTextScreenVisualLayers.Line2
|
||||
offset: 0.03125,-0.0625 # 1/32, 0/32
|
||||
- type: DVScreen
|
||||
- type: Sprite
|
||||
drawdepth: WallMountedItems
|
||||
sprite: _DV/Structures/Wallmounts/screen.rsi
|
||||
noRot: true
|
||||
layers:
|
||||
- state: frame
|
||||
- shader: StencilClear
|
||||
state: mask
|
||||
- shader: StencilMask
|
||||
state: mask
|
||||
- map: ["enum.DVTextScreenVisualLayers.Line1"]
|
||||
shader: StencilDraw
|
||||
color: "#22ccff"
|
||||
visible: false
|
||||
- map: ["enum.DVTextScreenVisualLayers.Line2"]
|
||||
shader: StencilDraw
|
||||
color: "#22ccff"
|
||||
visible: false
|
||||
- map: ["alert_status"]
|
||||
visible: false
|
||||
state: status_display_green
|
||||
- map: ["alert_border"]
|
||||
visible: false
|
||||
state: alert_border_green
|
||||
- type: Appearance
|
||||
- type: ApcPowerReceiver
|
||||
- type: ExtensionCableReceiver
|
||||
- type: GenericVisualizer
|
||||
visuals:
|
||||
enum.DVScreenVisuals.ShowAlertBorder:
|
||||
alert_border:
|
||||
True: { visible: true }
|
||||
False: { visible: false }
|
||||
enum.DVScreenVisuals.AlertLevel:
|
||||
alert_border:
|
||||
green: { state: alert_border_green }
|
||||
blue: { state: alert_border_blue }
|
||||
red: { state: alert_border_red }
|
||||
white: { state: alert_border_white }
|
||||
yellow: { state: alert_border_yellow }
|
||||
violet: { state: alert_border_violet }
|
||||
delta: { state: alert_border_delta }
|
||||
epsilon: { state: alert_border_epsilon }
|
||||
gamma: { state: alert_border_gamma }
|
||||
octarine: { state: alert_border_octarine }
|
||||
zeta: { state: alert_border_zeta }
|
||||
alert_status:
|
||||
green: { state: status_display_green }
|
||||
blue: { state: status_display_blue }
|
||||
red: { state: status_display_red }
|
||||
white: { state: status_display_white }
|
||||
yellow: { state: status_display_yellow }
|
||||
violet: { state: status_display_violet }
|
||||
delta: { state: status_display_delta }
|
||||
epsilon: { state: status_display_epsilon }
|
||||
gamma: { state: status_display_gamma }
|
||||
octarine: { state: status_display_octarine }
|
||||
zeta: { state: status_display_zeta }
|
||||
enum.DVScreenVisuals.Content:
|
||||
enum.DVTextScreenVisualLayers.Line1:
|
||||
Text: { visible: true }
|
||||
CurrentTime: { visible: true }
|
||||
EstimatedTimeOfArrival: { visible: true }
|
||||
AlertLevel: { visible: false }
|
||||
enum.DVTextScreenVisualLayers.Line2:
|
||||
Text: { visible: true }
|
||||
CurrentTime: { visible: true }
|
||||
EstimatedTimeOfArrival: { visible: true }
|
||||
AlertLevel: { visible: false }
|
||||
alert_status:
|
||||
Text: { visible: false }
|
||||
CurrentTime: { visible: false }
|
||||
EstimatedTimeOfArrival: { visible: false }
|
||||
AlertLevel: { visible: true }
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Wireless
|
||||
receiveFrequencyId: ShuttleTimer
|
||||
|
||||
- type: entity
|
||||
parent: StatusDisplay
|
||||
id: StatusDisplayShuttle
|
||||
name: arrivals status display
|
||||
description: Displays the current status of the arrivals shuttle.
|
||||
components:
|
||||
- type: DeviceNetwork
|
||||
deviceNetId: Private
|
||||
receiveFrequencyId: ArrivalsShuttleTimer
|
||||
- type: DVScreen
|
||||
content: EstimatedTimeOfArrival
|
||||
|
|
@ -30,3 +30,8 @@
|
|||
id: MonumentPulse
|
||||
kind: source
|
||||
path: "/Textures/_DV/Shaders/monument_pulse.swsl"
|
||||
|
||||
- type: shader
|
||||
id: Masked
|
||||
kind: source
|
||||
path: "/Textures/_DV/Shaders/mask.swsl"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
uniform sampler2D uMask;
|
||||
uniform highp vec4 uMaskUV;
|
||||
|
||||
varying highp vec2 vMaskUV;
|
||||
|
||||
void vertex()
|
||||
{
|
||||
vMaskUV = (tCoord2 - uMaskUV.xy) / (uMaskUV.zw - uMaskUV.xy);
|
||||
// vMaskUV = mix(uMaskUV.xy, uMaskUV.zw, tCoord2);
|
||||
}
|
||||
|
||||
void fragment()
|
||||
{
|
||||
COLOR.rgba = zTexture(UV) * texture2D(uMask, vMaskUV);
|
||||
}
|
||||
|
After Width: | Height: | Size: 252 B |
|
After Width: | Height: | Size: 382 B |
|
After Width: | Height: | Size: 320 B |
|
After Width: | Height: | Size: 317 B |
|
After Width: | Height: | Size: 250 B |
|
After Width: | Height: | Size: 203 B |
|
After Width: | Height: | Size: 237 B |
|
After Width: | Height: | Size: 204 B |
|
After Width: | Height: | Size: 191 B |
|
After Width: | Height: | Size: 192 B |
|
After Width: | Height: | Size: 197 B |
|
After Width: | Height: | Size: 261 B |
|
After Width: | Height: | Size: 440 B |
|
After Width: | Height: | Size: 149 B |
|
|
@ -0,0 +1,269 @@
|
|||
{
|
||||
"version": 1,
|
||||
"license": "CC-BY-SA-3.0",
|
||||
"copyright": "Taken from Baystation12 at https://github.com/Baystation12/Baystation12/blob/926c09fe7fe69d647e530d03dce356737af82a3a/icons/misc/security_state.dmi and https://github.com/Baystation12/Baystation12/blob/926c09fe7fe69d647e530d03dce356737af82a3a/icons/obj/machines/status_display.dmi. white, octarine, zeta, yellow, gamma, epsilon made by sowelipililimute based on prior sprites",
|
||||
"size": {
|
||||
"x": 32,
|
||||
"y": 32
|
||||
},
|
||||
"states": [
|
||||
{
|
||||
"name": "status_display_green",
|
||||
"delays": [
|
||||
[
|
||||
1.6,
|
||||
1.6
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_blue",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_red",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_delta",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_green",
|
||||
"delays": [
|
||||
[
|
||||
1.6,
|
||||
1.6
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_blue",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_delta",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_red",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_violet",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "frame"
|
||||
},
|
||||
{
|
||||
"name": "frame_broken"
|
||||
},
|
||||
{
|
||||
"name": "mask"
|
||||
},
|
||||
{
|
||||
"name": "radiation",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_violet",
|
||||
"delays": [
|
||||
[
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1,
|
||||
0.1
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_white",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_white",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_octarine",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_octarine",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_zeta",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_zeta",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_yellow",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_yellow",
|
||||
"delays": [
|
||||
[
|
||||
0.5,
|
||||
0.5
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_gamma",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_gamma",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "status_display_epsilon",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "alert_border_epsilon",
|
||||
"delays": [
|
||||
[
|
||||
0.2,
|
||||
0.2,
|
||||
0.2,
|
||||
0.2
|
||||
]
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
After Width: | Height: | Size: 792 B |
|
After Width: | Height: | Size: 494 B |
|
After Width: | Height: | Size: 957 B |
|
After Width: | Height: | Size: 910 B |
|
After Width: | Height: | Size: 798 B |
|
After Width: | Height: | Size: 453 B |
|
After Width: | Height: | Size: 966 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 449 B |
|
After Width: | Height: | Size: 459 B |
|
After Width: | Height: | Size: 610 B |