diff --git a/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml b/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml
new file mode 100644
index 0000000000..528cbef31a
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml.cs b/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml.cs
new file mode 100644
index 0000000000..86058959b4
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/MiniArticleCardControl.xaml.cs
@@ -0,0 +1,26 @@
+using Content.Client.Message;
+using Content.Shared.Research.Prototypes;
+using Robust.Client.AutoGenerated;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+
+namespace Content.Client.MassMedia.Ui;
+
+[GenerateTypedNameReferences]
+public sealed partial class MiniArticleCardControl : Control
+{
+ public Action? OnDeletePressed;
+ public int ArtcileNum;
+
+ public MiniArticleCardControl(string name)
+ {
+ RobustXamlLoader.Load(this);
+
+ Name.SetMarkup(name);
+
+ Delete.OnPressed += _ => OnDeletePressed?.Invoke();
+ }
+}
diff --git a/Content.Client/MassMedia/Ui/NewsReadBoundUserInterface.cs b/Content.Client/MassMedia/Ui/NewsReadBoundUserInterface.cs
new file mode 100644
index 0000000000..98ffd44359
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsReadBoundUserInterface.cs
@@ -0,0 +1,58 @@
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+using Content.Shared.MassMedia.Components;
+using Robust.Shared.Timing;
+
+namespace Content.Client.MassMedia.Ui
+{
+ [UsedImplicitly]
+ public sealed class NewsReadBoundUserInterface : BoundUserInterface
+ {
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+
+ [ViewVariables]
+ private NewsReadMenu? _menu;
+
+ [ViewVariables]
+ private string _windowName = Loc.GetString("news-read-ui-default-title");
+
+ public NewsReadBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+ {
+ }
+
+ protected override void Open()
+ {
+ _menu = new NewsReadMenu(_windowName);
+
+ _menu.OpenCentered();
+ _menu.OnClose += Close;
+
+ _menu.NextButtonPressed += () => SendMessage(new NewsReadNextMessage());
+ _menu.PastButtonPressed += () => SendMessage(new NewsReadPrevMessage());
+
+ SendMessage(new NewsReadArticleRequestMessage());
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (!disposing)
+ return;
+
+ _menu?.Close();
+ _menu?.Dispose();
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+ if (_menu == null)
+ return;
+
+ if (state is NewsReadBoundUserInterfaceState cast)
+ _menu.UpdateUI(cast.Article, cast.TargetNum, cast.TotalNum);
+ if (state is NewsReadEmptyBoundUserInterfaceState)
+ _menu.UpdateEmptyUI();
+ }
+ }
+}
diff --git a/Content.Client/MassMedia/Ui/NewsReadMenu.xaml b/Content.Client/MassMedia/Ui/NewsReadMenu.xaml
new file mode 100644
index 0000000000..b4c3698946
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsReadMenu.xaml
@@ -0,0 +1,52 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/MassMedia/Ui/NewsReadMenu.xaml.cs b/Content.Client/MassMedia/Ui/NewsReadMenu.xaml.cs
new file mode 100644
index 0000000000..f92a21794b
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsReadMenu.xaml.cs
@@ -0,0 +1,54 @@
+using Content.Client.Message;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Prototypes;
+using Content.Shared.MassMedia.Systems;
+
+namespace Content.Client.MassMedia.Ui;
+
+[GenerateTypedNameReferences]
+public sealed partial class NewsReadMenu : DefaultWindow
+{
+ [Dependency] private readonly IEntityManager _entityManager = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
+ public event Action? NextButtonPressed;
+ public event Action? PastButtonPressed;
+
+ public NewsReadMenu(string name)
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ if (Window != null)
+ Window.Title = name;
+
+ Next.OnPressed += _ => NextButtonPressed?.Invoke();
+ Past.OnPressed += _ => PastButtonPressed?.Invoke();
+ }
+
+ public void UpdateUI(NewsArticle article, int targetNum, int totalNum)
+ {
+ PageNum.Visible = true;
+ PageText.Visible = true;
+ ShareTime.Visible = true;
+
+ PageName.Text = article.Name;
+ PageText.SetMarkup(article.Content);
+
+ PageNum.Text = $"{targetNum}/{totalNum}";
+
+ string shareTime = article.ShareTime.ToString("hh\\:mm\\:ss");
+ ShareTime.SetMarkup(Loc.GetString("news-read-ui-time-prefix-text") + " " + shareTime);
+ }
+
+ public void UpdateEmptyUI()
+ {
+ PageName.Text = Loc.GetString("news-read-ui-not-found-text");
+
+ PageNum.Visible = false;
+ PageText.Visible = false;
+ ShareTime.Visible = false;
+ }
+}
diff --git a/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs b/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs
new file mode 100644
index 0000000000..2e130a428a
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsWriteBoundUserInterface.cs
@@ -0,0 +1,88 @@
+using Robust.Shared.Timing;
+using JetBrains.Annotations;
+using Robust.Client.GameObjects;
+using Content.Shared.MassMedia.Systems;
+using Content.Shared.MassMedia.Components;
+using Content.Client.GameTicking.Managers;
+using Robust.Shared.Utility;
+
+namespace Content.Client.MassMedia.Ui
+{
+ [UsedImplicitly]
+ public sealed class NewsWriteBoundUserInterface : BoundUserInterface
+ {
+ [ViewVariables]
+ private NewsWriteMenu? _menu;
+
+ [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
+ [Dependency] private readonly IGameTiming _gameTiming = default!;
+ private ClientGameTicker? _gameTicker;
+
+ [ViewVariables]
+ private string _windowName = Loc.GetString("news-read-ui-default-title");
+
+ public NewsWriteBoundUserInterface(EntityUid owner, Enum uiKey) : base(owner, uiKey)
+ {
+
+ }
+
+ protected override void Open()
+ {
+ _menu = new NewsWriteMenu(_windowName);
+
+ _menu.OpenCentered();
+ _menu.OnClose += Close;
+
+ _menu.ShareButtonPressed += OnShareButtonPressed;
+ _menu.DeleteButtonPressed += num => OnDeleteButtonPressed(num);
+
+ _gameTicker = _entitySystem.GetEntitySystem();
+
+ SendMessage(new NewsWriteArticlesRequestMessage());
+ }
+
+ protected override void Dispose(bool disposing)
+ {
+ base.Dispose(disposing);
+ if (!disposing)
+ return;
+
+ _menu?.Close();
+ _menu?.Dispose();
+ }
+
+ protected override void UpdateState(BoundUserInterfaceState state)
+ {
+ base.UpdateState(state);
+ if (_menu == null || state is not NewsWriteBoundUserInterfaceState cast)
+ return;
+
+ _menu.UpdateUI(cast.Articles);
+ }
+
+ private void OnShareButtonPressed()
+ {
+ if (_menu == null || _menu.NameInput.Text.Length == 0)
+ return;
+
+ var stringContent = Rope.Collapse(_menu.ContentInput.TextRope);
+
+ if (stringContent == null || stringContent.Length == 0) return;
+ if (_gameTicker == null) return;
+
+ NewsArticle article = new NewsArticle();
+ article.Name = _menu.NameInput.Text;
+ article.Content = stringContent;
+ article.ShareTime = _gameTiming.CurTime.Subtract(_gameTicker.RoundStartTimeSpan);
+
+ SendMessage(new NewsWriteShareMessage(article));
+ }
+
+ private void OnDeleteButtonPressed(int articleNum)
+ {
+ if (_menu == null) return;
+
+ SendMessage(new NewsWriteDeleteMessage(articleNum));
+ }
+ }
+}
diff --git a/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml b/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml
new file mode 100644
index 0000000000..0b03078812
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml.cs b/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml.cs
new file mode 100644
index 0000000000..788f31b9c9
--- /dev/null
+++ b/Content.Client/MassMedia/Ui/NewsWriteMenu.xaml.cs
@@ -0,0 +1,42 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Prototypes;
+using Content.Shared.MassMedia.Systems;
+
+namespace Content.Client.MassMedia.Ui;
+
+[GenerateTypedNameReferences]
+public sealed partial class NewsWriteMenu : DefaultWindow
+{
+ [Dependency] private readonly IEntityManager _entityManager = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+
+ public event Action? ShareButtonPressed;
+ public event Action? DeleteButtonPressed;
+
+ public NewsWriteMenu(string name)
+ {
+ RobustXamlLoader.Load(this);
+ IoCManager.InjectDependencies(this);
+
+ if (Window != null)
+ Window.Title = name;
+
+ Share.OnPressed += _ => ShareButtonPressed?.Invoke();
+ }
+
+ public void UpdateUI(NewsArticle[] articles)
+ {
+ ArticleCardsContainer.Children.Clear();
+
+ for (int i = 0; i < articles.Length; i++)
+ {
+ var mini = new MiniArticleCardControl(articles[i].Name);
+ mini.ArtcileNum = i;
+ mini.OnDeletePressed += () => DeleteButtonPressed?.Invoke(mini.ArtcileNum);
+
+ ArticleCardsContainer.AddChild(mini);
+ }
+ }
+}
diff --git a/Content.Client/PDA/PdaBoundUserInterface.cs b/Content.Client/PDA/PdaBoundUserInterface.cs
index bd23d5ea55..2238948cce 100644
--- a/Content.Client/PDA/PdaBoundUserInterface.cs
+++ b/Content.Client/PDA/PdaBoundUserInterface.cs
@@ -73,6 +73,12 @@ namespace Content.Client.PDA
SendMessage(new PdaLockUplinkMessage());
};
+ _menu.NewsReadButton.OnPressed += _ =>
+ {
+ SendMessage(new PdaOpenNewsMessage());
+ };
+
+
_menu.OnProgramItemPressed += ActivateCartridge;
_menu.OnInstallButtonPressed += InstallCartridge;
_menu.OnUninstallButtonPressed += UninstallCartridge;
diff --git a/Content.Client/PDA/PdaMenu.xaml b/Content.Client/PDA/PdaMenu.xaml
index a06032d6d2..f6b07d1ca6 100644
--- a/Content.Client/PDA/PdaMenu.xaml
+++ b/Content.Client/PDA/PdaMenu.xaml
@@ -1,4 +1,4 @@
-
+
Articles = new List();
+
+ public override void Initialize()
+ {
+ base.Initialize();
+
+ SubscribeLocalEvent(OnWriteUiMessage);
+ SubscribeLocalEvent(OnWriteUiMessage);
+ SubscribeLocalEvent(OnWriteUiMessage);
+ SubscribeLocalEvent(OnReadUiMessage);
+ SubscribeLocalEvent(OnReadUiMessage);
+ SubscribeLocalEvent(OnReadUiMessage);
+
+ SubscribeLocalEvent(OnRoundRestart);
+ }
+
+ private void OnRoundRestart(RoundRestartCleanupEvent ev)
+ {
+ if (Articles != null) Articles.Clear();
+ }
+
+ public void ToggleUi(EntityUid user, EntityUid deviceEnt, NewsReadComponent? component)
+ {
+ if (!Resolve(deviceEnt, ref component))
+ return;
+
+ if (!TryComp(user, out var actor))
+ return;
+
+ _ui.TryToggleUi(deviceEnt, NewsReadUiKey.Key, actor.PlayerSession);
+ }
+
+ public void ToggleUi(EntityUid user, EntityUid deviceEnt, NewsWriteComponent? component)
+ {
+ if (!Resolve(deviceEnt, ref component))
+ return;
+
+ if (!TryComp(user, out var actor))
+ return;
+
+ _ui.TryToggleUi(deviceEnt, NewsWriteUiKey.Key, actor.PlayerSession);
+ }
+
+ public void UpdateWriteUi(EntityUid uid, NewsWriteComponent component)
+ {
+ if (!_ui.TryGetUi(uid, NewsWriteUiKey.Key, out _))
+ return;
+
+ var state = new NewsWriteBoundUserInterfaceState(Articles.ToArray());
+ _ui.TrySetUiState(uid, NewsWriteUiKey.Key, state);
+ }
+
+ public void UpdateReadUi(EntityUid uid, NewsReadComponent component)
+ {
+ if (!_ui.TryGetUi(uid, NewsReadUiKey.Key, out _))
+ return;
+
+ if (component.ArticleNum < 0) NewsReadLeafArticle(component, -1);
+
+ if (Articles.Any())
+ _ui.TrySetUiState(uid, NewsReadUiKey.Key, new NewsReadBoundUserInterfaceState(Articles[component.ArticleNum], component.ArticleNum + 1, Articles.Count));
+ else
+ _ui.TrySetUiState(uid, NewsReadUiKey.Key, new NewsReadEmptyBoundUserInterfaceState());
+ }
+
+ public void OnWriteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteShareMessage msg)
+ {
+ Articles.Add(msg.Article);
+
+ UpdateReadDevices();
+ UpdateWriteDevices();
+ TryNotify();
+ }
+
+ public void OnWriteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteDeleteMessage msg)
+ {
+ if (msg.ArticleNum < Articles.Count)
+ {
+ Articles.RemoveAt(msg.ArticleNum);
+ }
+
+ UpdateReadDevices();
+ UpdateWriteDevices();
+ }
+
+ public void OnWriteUiMessage(EntityUid uid, NewsWriteComponent component, NewsWriteArticlesRequestMessage msg)
+ {
+ UpdateWriteUi(uid, component);
+ }
+
+ public void OnReadUiMessage(EntityUid uid, NewsReadComponent component, NewsReadNextMessage msg)
+ {
+ NewsReadLeafArticle(component, 1);
+
+ UpdateReadUi(uid, component);
+ }
+
+ public void OnReadUiMessage(EntityUid uid, NewsReadComponent component, NewsReadPrevMessage msg)
+ {
+ NewsReadLeafArticle(component, -1);
+
+ UpdateReadUi(uid, component);
+ }
+
+ public void OnReadUiMessage(EntityUid uid, NewsReadComponent component, NewsReadArticleRequestMessage msg)
+ {
+ UpdateReadUi(uid, component);
+ }
+
+ private void NewsReadLeafArticle(NewsReadComponent component, int leafDir)
+ {
+ component.ArticleNum += leafDir;
+
+ if (component.ArticleNum >= Articles.Count) component.ArticleNum = 0;
+ if (component.ArticleNum < 0) component.ArticleNum = Articles.Count - 1;
+ }
+
+ private void TryNotify()
+ {
+ var query = EntityQueryEnumerator();
+
+ while (query.MoveNext(out var comp, out var ringer))
+ {
+ _ringer.RingerPlayRingtone(comp.Owner, ringer);
+ }
+ }
+
+ private void UpdateReadDevices()
+ {
+ var query = EntityQueryEnumerator();
+
+ while (query.MoveNext(out var comp))
+ {
+ UpdateReadUi(comp.Owner, comp);
+ }
+ }
+
+ private void UpdateWriteDevices()
+ {
+ var query = EntityQueryEnumerator();
+
+ while (query.MoveNext(out var comp))
+ {
+ UpdateWriteUi(comp.Owner, comp);
+ }
+ }
+}
+
diff --git a/Content.Server/PDA/PdaSystem.cs b/Content.Server/PDA/PdaSystem.cs
index 31df32f7ad..e02e79ddd9 100644
--- a/Content.Server/PDA/PdaSystem.cs
+++ b/Content.Server/PDA/PdaSystem.cs
@@ -15,6 +15,8 @@ using Robust.Server.GameObjects;
using Robust.Server.Player;
using Robust.Shared.Containers;
using Content.Shared.Light.Component;
+using Content.Server.MassMedia.Components;
+using Content.Server.MassMedia.Systems;
namespace Content.Server.PDA
{
@@ -25,6 +27,7 @@ namespace Content.Server.PDA
[Dependency] private readonly RingerSystem _ringer = default!;
[Dependency] private readonly StationSystem _station = default!;
[Dependency] private readonly StoreSystem _store = default!;
+ [Dependency] private readonly NewsSystem _news = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly UnpoweredFlashlightSystem _unpoweredFlashlight = default!;
[Dependency] private readonly MindSystem _mindSystem = default!;
@@ -42,6 +45,7 @@ namespace Content.Server.PDA
SubscribeLocalEvent(OnUiMessage);
SubscribeLocalEvent(OnUiMessage);
SubscribeLocalEvent(OnUiMessage);
+ SubscribeLocalEvent(OnUiMessage);
SubscribeLocalEvent(OnStationRenamed);
SubscribeLocalEvent(OnAlertLevelChanged);
@@ -112,6 +116,7 @@ namespace Content.Server.PDA
var address = GetDeviceNetAddress(uid);
var hasInstrument = HasComp(uid);
var showUplink = HasComp(uid) && IsUnlocked(uid);
+ var showNews = HasComp(uid);
UpdateStationName(uid, pda);
UpdateAlertLevel(uid, pda);
@@ -133,6 +138,7 @@ namespace Content.Server.PDA
pda.StationName,
showUplink,
hasInstrument,
+ showNews,
address);
_cartridgeLoader?.UpdateUiState(uid, state);
@@ -195,6 +201,18 @@ namespace Content.Server.PDA
}
}
+ private void OnUiMessage(EntityUid uid, PdaComponent pda, PdaOpenNewsMessage msg)
+ {
+ if (!PdaUiKey.Key.Equals(msg.UiKey))
+ return;
+
+ if (TryComp(uid, out var news))
+ {
+ _news.ToggleUi(msg.Session.AttachedEntity!.Value, uid, news);
+ UpdatePdaUi(uid, pda);
+ }
+ }
+
private bool IsUnlocked(EntityUid uid)
{
return !TryComp(uid, out var uplink) || uplink.Unlocked;
diff --git a/Content.Server/PDA/Ringer/RingerComponent.cs b/Content.Server/PDA/Ringer/RingerComponent.cs
index 5ef26a8426..2d70f78a5b 100644
--- a/Content.Server/PDA/Ringer/RingerComponent.cs
+++ b/Content.Server/PDA/Ringer/RingerComponent.cs
@@ -22,7 +22,7 @@ namespace Content.Server.PDA.Ringer
///
[ViewVariables(VVAccess.ReadWrite)]
[DataField("range")]
- public float Range = 3f;
+ public float Range = 0.5f;
[ViewVariables(VVAccess.ReadWrite)]
[DataField("volume")]
diff --git a/Content.Server/PDA/Ringer/RingerSystem.cs b/Content.Server/PDA/Ringer/RingerSystem.cs
index 03aa1069e6..46bcc999b8 100644
--- a/Content.Server/PDA/Ringer/RingerSystem.cs
+++ b/Content.Server/PDA/Ringer/RingerSystem.cs
@@ -2,6 +2,7 @@ using Content.Server.Store.Components;
using Content.Server.Store.Systems;
using Content.Shared.PDA;
using Content.Shared.PDA.Ringer;
+using Content.Shared.Popups;
using Content.Shared.Store;
using Robust.Server.GameObjects;
using Robust.Server.Player;
@@ -19,6 +20,7 @@ namespace Content.Server.PDA.Ringer
[Dependency] private readonly IRobustRandom _random = default!;
[Dependency] private readonly UserInterfaceSystem _ui = default!;
[Dependency] private readonly AudioSystem _audio = default!;
+ [Dependency] private readonly SharedPopupSystem _popupSystem = default!;
public override void Initialize()
{
@@ -48,6 +50,18 @@ namespace Content.Server.PDA.Ringer
private void RingerPlayRingtone(EntityUid uid, RingerComponent ringer, RingerPlayRingtoneMessage args)
{
EnsureComp(uid);
+
+ _popupSystem.PopupEntity(Loc.GetString("comp-ringer-vibration-popup"), uid, Filter.Pvs(uid, 0.05f), false, PopupType.Small);
+
+ UpdateRingerUserInterface(uid, ringer);
+ }
+
+ public void RingerPlayRingtone(EntityUid uid, RingerComponent ringer)
+ {
+ EnsureComp(uid);
+
+ _popupSystem.PopupEntity(Loc.GetString("comp-ringer-vibration-popup"), uid, Filter.Pvs(uid, 0.05f), false, PopupType.Small);
+
UpdateRingerUserInterface(uid, ringer);
}
diff --git a/Content.Shared/MassMedia/Components/SharedNewsReadComponent.cs b/Content.Shared/MassMedia/Components/SharedNewsReadComponent.cs
new file mode 100644
index 0000000000..499aede51f
--- /dev/null
+++ b/Content.Shared/MassMedia/Components/SharedNewsReadComponent.cs
@@ -0,0 +1,57 @@
+using Robust.Shared.Serialization;
+using Content.Shared.MassMedia.Systems;
+
+namespace Content.Shared.MassMedia.Components;
+
+[Serializable, NetSerializable]
+public enum NewsReadUiKey : byte
+{
+ Key
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsReadBoundUserInterfaceState : BoundUserInterfaceState
+{
+ public NewsArticle Article;
+ public int TargetNum;
+ public int TotalNum;
+
+ public NewsReadBoundUserInterfaceState(NewsArticle article, int targetNum, int totalNum)
+ {
+ Article = article;
+ TargetNum = targetNum;
+ TotalNum = totalNum;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsReadEmptyBoundUserInterfaceState : BoundUserInterfaceState
+{
+ public NewsReadEmptyBoundUserInterfaceState()
+ {
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsReadNextMessage : BoundUserInterfaceMessage
+{
+ public NewsReadNextMessage()
+ {
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsReadPrevMessage : BoundUserInterfaceMessage
+{
+ public NewsReadPrevMessage()
+ {
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsReadArticleRequestMessage : BoundUserInterfaceMessage
+{
+ public NewsReadArticleRequestMessage()
+ {
+ }
+}
diff --git a/Content.Shared/MassMedia/Components/SharedNewsWriteComponent.cs b/Content.Shared/MassMedia/Components/SharedNewsWriteComponent.cs
new file mode 100644
index 0000000000..c7386698e0
--- /dev/null
+++ b/Content.Shared/MassMedia/Components/SharedNewsWriteComponent.cs
@@ -0,0 +1,51 @@
+using Robust.Shared.Serialization;
+using Content.Shared.MassMedia.Systems;
+
+namespace Content.Shared.MassMedia.Components;
+
+[Serializable, NetSerializable]
+public enum NewsWriteUiKey : byte
+{
+ Key
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsWriteBoundUserInterfaceState : BoundUserInterfaceState
+{
+ public NewsArticle[] Articles;
+
+ public NewsWriteBoundUserInterfaceState(NewsArticle[] articles)
+ {
+ Articles = articles;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsWriteShareMessage : BoundUserInterfaceMessage
+{
+ public NewsArticle Article;
+
+ public NewsWriteShareMessage(NewsArticle article)
+ {
+ Article = article;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsWriteDeleteMessage : BoundUserInterfaceMessage
+{
+ public int ArticleNum;
+
+ public NewsWriteDeleteMessage(int num)
+ {
+ ArticleNum = num;
+ }
+}
+
+[Serializable, NetSerializable]
+public sealed class NewsWriteArticlesRequestMessage : BoundUserInterfaceMessage
+{
+ public NewsWriteArticlesRequestMessage()
+ {
+ }
+}
diff --git a/Content.Shared/MassMedia/Systems/SharedNewsSystem.cs b/Content.Shared/MassMedia/Systems/SharedNewsSystem.cs
new file mode 100644
index 0000000000..140452eb65
--- /dev/null
+++ b/Content.Shared/MassMedia/Systems/SharedNewsSystem.cs
@@ -0,0 +1,9 @@
+namespace Content.Shared.MassMedia.Systems;
+
+[Serializable]
+public struct NewsArticle
+{
+ public string Name;
+ public string Content;
+ public TimeSpan ShareTime;
+}
diff --git a/Content.Shared/PDA/PdaMessagesUi.cs b/Content.Shared/PDA/PdaMessagesUi.cs
index 00d29e1e1a..7bcc0afbe9 100644
--- a/Content.Shared/PDA/PdaMessagesUi.cs
+++ b/Content.Shared/PDA/PdaMessagesUi.cs
@@ -32,6 +32,12 @@ public sealed class PdaShowMusicMessage : BoundUserInterfaceMessage
public PdaShowMusicMessage() { }
}
+[Serializable, NetSerializable]
+public sealed class PdaOpenNewsMessage : BoundUserInterfaceMessage
+{
+ public PdaOpenNewsMessage() { }
+}
+
[Serializable, NetSerializable]
public sealed class PdaRequestUpdateInterfaceMessage : BoundUserInterfaceMessage
{
diff --git a/Content.Shared/PDA/PdaUpdateState.cs b/Content.Shared/PDA/PdaUpdateState.cs
index 053527a868..581db5cad5 100644
--- a/Content.Shared/PDA/PdaUpdateState.cs
+++ b/Content.Shared/PDA/PdaUpdateState.cs
@@ -13,17 +13,19 @@ namespace Content.Shared.PDA
public string? StationName;
public bool HasUplink;
public bool CanPlayMusic;
+ public bool HasNewsTab;
public string? Address;
public PdaUpdateState(bool flashlightEnabled, bool hasPen, PdaIdInfoText pdaOwnerInfo,
string? stationName, bool hasUplink = false,
- bool canPlayMusic = false, string? address = null)
+ bool canPlayMusic = false, bool hasNewsTab = false, string? address = null)
{
FlashlightEnabled = flashlightEnabled;
HasPen = hasPen;
PdaOwnerInfo = pdaOwnerInfo;
HasUplink = hasUplink;
CanPlayMusic = canPlayMusic;
+ HasNewsTab = hasNewsTab;
StationName = stationName;
Address = address;
}
diff --git a/Resources/Locale/en-US/mass-media/news-ui.ftl b/Resources/Locale/en-US/mass-media/news-ui.ftl
new file mode 100644
index 0000000000..9dbc62b402
--- /dev/null
+++ b/Resources/Locale/en-US/mass-media/news-ui.ftl
@@ -0,0 +1,14 @@
+pda-news-button-label = News
+pda-news-button-description = View station news
+news-read-ui-next-text = Next
+news-read-ui-past-text = Past
+news-read-ui-default-title = Station News
+news-read-ui-not-found-text = No articles found
+news-read-ui-time-prefix-text = Publication time:
+news-write-ui-default-title = Mass-media Management
+news-write-ui-articles-label = Articles:
+news-write-ui-delete-text = Delete
+news-write-ui-share-text = Publish
+news-write-ui-article-name-label = Heading:
+news-write-ui-article-content-label = Content:
+
diff --git a/Resources/Locale/en-US/pda/Ringer/ringer-component.ftl b/Resources/Locale/en-US/pda/Ringer/ringer-component.ftl
index aa02d982a4..138cdd5514 100644
--- a/Resources/Locale/en-US/pda/Ringer/ringer-component.ftl
+++ b/Resources/Locale/en-US/pda/Ringer/ringer-component.ftl
@@ -3,6 +3,8 @@
# For the PDA Ringer screen
+comp-ringer-vibration-popup = PDA vibrates
+
comp-ringer-ui-menu-title = Ringtone
comp-ringer-ui-test-ringtone-button = Test
diff --git a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
index caa2831509..b72f53689c 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/Circuitboards/computer.yml
@@ -365,3 +365,16 @@
components:
- type: ComputerBoard
prototype: ComputerIFFSyndicate
+
+- type: entity
+ parent: BaseComputerCircuitboard
+ id: ComputerMassMediaCircuitboard
+ name: mass media console board
+ description: Write your message to the world!
+ components:
+ - type: Sprite
+ state: cpu_service
+ - type: StaticPrice
+ price: 150
+ - type: ComputerBoard
+ prototype: ComputerMassMedia
\ No newline at end of file
diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
index b6a396755c..915a7b6fd0 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
@@ -97,8 +97,11 @@
type: InstrumentBoundUserInterface
- key: enum.HealthAnalyzerUiKey.Key
type: HealthAnalyzerBoundUserInterface
+ - key: enum.NewsReadUiKey.Key
+ type: NewsReadBoundUserInterface
- type: CrewManifestViewer
unsecure: true
+ - type: NewsRead
- type: Tag
tags:
- DoorBumpOpener
diff --git a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
index 2b2c1fb200..13544c3bf0 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/Computers/computers.yml
@@ -940,3 +940,33 @@
radius: 1.5
energy: 1.6
color: "#b89f25"
+
+- type: entity
+ parent: BaseComputer
+ id: ComputerMassMedia
+ name: mass-media console
+ description: Write your message to the world!
+ components:
+ - type: Sprite
+ layers:
+ - map: ["computerLayerBody"]
+ state: computer
+ - map: ["computerLayerKeyboard"]
+ state: generic_keyboard
+ - map: ["computerLayerScreen"]
+ state: service
+ - map: ["computerLayerKeys"]
+ state: service_keys
+ - type: Computer
+ board: ComputerMassMediaCircuitboard
+ - type: DeviceNetworkRequiresPower
+ - type: NewsWrite
+ - type: ActivatableUI
+ key: enum.NewsWriteUiKey.Key
+ - type: ActivatableUIRequiresVision
+ - type: Transform
+ anchored: true
+ - type: UserInterface
+ interfaces:
+ - key: enum.NewsWriteUiKey.Key
+ type: NewsWriteBoundUserInterface
diff --git a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
index da5781057c..7dae0e0d4a 100644
--- a/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
+++ b/Resources/Prototypes/Entities/Structures/Machines/lathe.yml
@@ -316,6 +316,7 @@
- BoozeDispenserMachineCircuitboard
- SodaDispenserMachineCircuitboard
- TelecomServerCircuitboard
+ - MassMediaCircuitboard
- type: MaterialStorage
whitelist:
tags:
diff --git a/Resources/Prototypes/Recipes/Lathes/electronics.yml b/Resources/Prototypes/Recipes/Lathes/electronics.yml
index a7d858e464..e4d798803c 100644
--- a/Resources/Prototypes/Recipes/Lathes/electronics.yml
+++ b/Resources/Prototypes/Recipes/Lathes/electronics.yml
@@ -645,3 +645,11 @@
materials:
Steel: 100
Glass: 900
+
+- type: latheRecipe
+ id: MassMediaCircuitboard
+ result: ComputerMassMediaCircuitboard
+ completetime: 4
+ materials:
+ Steel: 100
+ Glass: 900
diff --git a/Resources/Prototypes/Research/civilianservices.yml b/Resources/Prototypes/Research/civilianservices.yml
index 46b0598731..8c661ed8e8 100644
--- a/Resources/Prototypes/Research/civilianservices.yml
+++ b/Resources/Prototypes/Research/civilianservices.yml
@@ -106,6 +106,7 @@
- ComputerTelevisionCircuitboard
- SynthesizerInstrument
- DawInstrumentMachineCircuitboard
+ - MassMediaCircuitboard
# Tier 2
diff --git a/Resources/Textures/Structures/Machines/computers.rsi/meta.json b/Resources/Textures/Structures/Machines/computers.rsi/meta.json
index b663858ccd..c43d5d7e52 100644
--- a/Resources/Textures/Structures/Machines/computers.rsi/meta.json
+++ b/Resources/Textures/Structures/Machines/computers.rsi/meta.json
@@ -6,1654 +6,1684 @@
"x": 32,
"y": 32
},
- "states": [
- {
- "name": "ai-fixer",
- "directions": 4
- },
- {
- "name": "ai-fixer-404",
- "directions": 4
- },
- {
- "name": "ai-fixer-empty",
- "directions": 4,
- "delays": [
- [
- 0.7,
- 0.7
- ],
- [
- 0.7,
- 0.7
- ],
- [
- 0.7,
- 0.7
- ],
- [
- 0.7,
- 0.7
- ]
- ]
- },
- {
- "name": "ai-fixer-full",
- "directions": 4
- },
- {
- "name": "ai-fixer-on",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "aiupload",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "aiupload_key",
- "directions": 4
- },
- {
- "name": "alert-0",
- "directions": 4
- },
- {
- "name": "alert-1",
- "directions": 4
- },
- {
- "name": "alert-2",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "area_atmos",
- "directions": 4,
- "delays": [
- [
- 1,
- 1
- ],
- [
- 1,
- 1
- ],
- [
- 1,
- 1
- ],
- [
- 1,
- 1
- ]
- ]
- },
- {
- "name": "artifact",
- "directions": 4,
- "delays": [
- [
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1
- ],
- [
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1
- ],
- [
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1
- ],
- [
- 1,
- 1,
- 1,
- 1,
- 1,
- 1,
- 1
- ]
- ]
- },
- {
- "name": "atmos_key",
- "directions": 4
- },
- {
- "name": "atmos_key_off",
- "directions": 4
- },
- {
- "name": "bounty",
- "directions": 4,
- "delays": [
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ]
- ]
- },
- {
- "name": "broken",
- "directions": 4
- },
- {
- "name": "cameras",
- "directions": 4,
- "delays": [
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ]
- ]
- },
- {
- "name": "comm",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "comm_logs",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2
- ],
- [
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2
- ],
- [
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2
- ],
- [
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2,
- 0.1,
- 0.2
- ]
- ]
- },
- {
- "name": "comm_monitor",
- "directions": 4,
- "delays": [
- [
- 0.4,
- 0.4,
- 0.4
- ],
- [
- 0.4,
- 0.4,
- 0.4
- ],
- [
- 0.4,
- 0.4,
- 0.4
- ],
- [
- 0.4,
- 0.4,
- 0.4
- ]
- ]
- },
- {
- "name": "comm_syndie",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "command",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "computer",
- "directions": 4
- },
- {
- "name": "screen_broken",
- "directions": 4
- },
- {
- "name": "crew",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "dna",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2,
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.8,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.8,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.8,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.8,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2,
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "dron_control_monitor",
- "directions": 4,
- "delays": [
- [
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05
- ],
- [
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05
- ],
- [
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05
- ],
- [
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05,
- 0.05
- ]
- ]
- },
- {
- "name": "engie_cams",
- "directions": 4,
- "delays": [
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ],
- [
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1,
- 1.8,
- 0.1
- ]
- ]
- },
- {
- "name": "engine",
- "directions": 4,
- "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,
- 0.2,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 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": "entertainment",
- "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,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 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": "eris_control",
- "directions": 4,
- "delays": [
- [
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5
- ],
- [
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5
- ],
- [
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5
- ],
- [
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5,
- 0.5
- ]
- ]
- },
- {
- "name": "error",
- "directions": 4
- },
- {
- "name": "explosive",
- "directions": 4,
- "delays": [
- [
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1,
- 1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "forensic",
- "directions": 4,
- "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,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 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": "generic",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "generic_keys",
- "directions": 4
- },
- {
- "name": "generic_keyboard",
- "directions": 4
- },
- {
- "name": "holocontrol",
- "directions": 4,
- "delays": [
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ]
- ]
- },
- {
- "name": "id",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "id_key",
- "directions": 4
- },
- {
- "name": "id_key_off",
- "directions": 4
- },
- {
- "name": "mass_driver"
- },
- {
- "name": "mecha",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "med_key",
- "directions": 4
- },
- {
- "name": "med_key_off",
- "directions": 4
- },
- {
- "name": "medcomp",
- "directions": 4,
- "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,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2,
- 0.2,
- 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": "mining",
- "directions": 4,
- "delays": [
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ],
- [
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1,
- 1,
- 0.1
- ]
- ]
- },
- {
- "name": "mining_key",
- "directions": 4
- },
- {
- "name": "mining_key_off",
- "directions": 4
- },
- {
- "name": "power_key",
- "directions": 4
- },
- {
- "name": "power_key_off",
- "directions": 4
- },
- {
- "name": "power_monitor",
- "directions": 4,
- "delays": [
- [
- 0.6,
- 0.6,
- 0.6,
- 0.6
- ],
- [
- 0.6,
- 0.6,
- 0.6,
- 0.6
- ],
- [
- 0.6,
- 0.6,
- 0.6,
- 0.6
- ],
- [
- 0.6,
- 0.6,
- 0.6,
- 0.6
- ]
- ]
- },
- {
- "name": "power_monitor_warn",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "rd_key",
- "directions": 4
- },
- {
- "name": "rd_key_off",
- "directions": 4
- },
- {
- "name": "rdcomp",
- "directions": 4
- },
- {
- "name": "recharge_comp",
- "directions": 4
- },
- {
- "name": "recharge_comp_on",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2
- ],
- [
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2
- ],
- [
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2
- ],
- [
- 0.2,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.1,
- 0.2
- ]
- ]
- },
- {
- "name": "request",
- "directions": 4,
- "delays": [
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ],
- [
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3,
- 0.3
- ]
- ]
- },
- {
- "name": "robot",
- "directions": 4
- },
- {
- "name": "security",
- "directions": 4,
- "delays": [
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ],
- [
- 0.2,
- 0.2
- ]
- ]
- },
- {
- "name": "security_key",
- "directions": 4
- },
- {
- "name": "security_key_off",
- "directions": 4
- },
- {
- "name": "shuttle",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "solar_screen",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "supply",
- "directions": 4
- },
- {
- "name": "syndie_key",
- "directions": 4
- },
- {
- "name": "syndie_key_off",
- "directions": 4
- },
- {
- "name": "syndishuttle",
- "directions": 4
- },
- {
- "name": "tank",
- "directions": 4
- },
- {
- "name": "tcboss",
- "directions": 4
- },
- {
- "name": "tech_key",
- "directions": 4
- },
- {
- "name": "tech_key_off",
- "directions": 4
- },
- {
- "name": "teleport",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "teleport_key",
- "directions": 4
- },
- {
- "name": "teleport_key_off",
- "directions": 4
- },
- {
- "name": "telesci",
- "directions": 4,
- "delays": [
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ],
- [
- 0.1,
- 0.1,
- 0.1,
- 0.1
- ]
- ]
- },
- {
- "name": "telesci_key",
- "directions": 4
- },
- {
- "name": "telesci_key_off",
- "directions": 4
- },
- {
- "name": "turbinecomp",
- "directions": 4
- },
- {
- "name": "computer-datatheory"
- },
- {
- "name": "avionics-systems"
- },
- {
- "name": "television"
- },
- {
- "name": "television_broken"
- },
- {
- "name": "telescreen",
- "directions": 4
- },
- {
- "name": "telescreen_frame",
- "directions": 4
- },
- {
- "name": "telescreen_broken",
- "directions": 4
- },
- {
- "name": "detective_television"
- }
- ]
+ "states": [
+ {
+ "name": "ai-fixer",
+ "directions": 4
+ },
+ {
+ "name": "ai-fixer-404",
+ "directions": 4
+ },
+ {
+ "name": "ai-fixer-empty",
+ "directions": 4,
+ "delays": [
+ [
+ 0.7,
+ 0.7
+ ],
+ [
+ 0.7,
+ 0.7
+ ],
+ [
+ 0.7,
+ 0.7
+ ],
+ [
+ 0.7,
+ 0.7
+ ]
+ ]
+ },
+ {
+ "name": "ai-fixer-full",
+ "directions": 4
+ },
+ {
+ "name": "ai-fixer-on",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "aiupload",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "aiupload_key",
+ "directions": 4
+ },
+ {
+ "name": "alert-0",
+ "directions": 4
+ },
+ {
+ "name": "alert-1",
+ "directions": 4
+ },
+ {
+ "name": "alert-2",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "area_atmos",
+ "directions": 4,
+ "delays": [
+ [
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1
+ ]
+ ]
+ },
+ {
+ "name": "artifact",
+ "directions": 4,
+ "delays": [
+ [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ],
+ [
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1,
+ 1
+ ]
+ ]
+ },
+ {
+ "name": "atmos_key",
+ "directions": 4
+ },
+ {
+ "name": "atmos_key_off",
+ "directions": 4
+ },
+ {
+ "name": "bounty",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ },
+ {
+ "name": "broken",
+ "directions": 4
+ },
+ {
+ "name": "cameras",
+ "directions": 4,
+ "delays": [
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "comm",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "comm_logs",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2,
+ 0.1,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "comm_monitor",
+ "directions": 4,
+ "delays": [
+ [
+ 0.4,
+ 0.4,
+ 0.4
+ ],
+ [
+ 0.4,
+ 0.4,
+ 0.4
+ ],
+ [
+ 0.4,
+ 0.4,
+ 0.4
+ ],
+ [
+ 0.4,
+ 0.4,
+ 0.4
+ ]
+ ]
+ },
+ {
+ "name": "comm_syndie",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "command",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "computer",
+ "directions": 4
+ },
+ {
+ "name": "screen_broken",
+ "directions": 4
+ },
+ {
+ "name": "crew",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "dna",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.8,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.8,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.8,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.8,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2,
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "dron_control_monitor",
+ "directions": 4,
+ "delays": [
+ [
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05
+ ],
+ [
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05
+ ],
+ [
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05
+ ],
+ [
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05,
+ 0.05
+ ]
+ ]
+ },
+ {
+ "name": "engie_cams",
+ "directions": 4,
+ "delays": [
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ],
+ [
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1,
+ 1.8,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "engine",
+ "directions": 4,
+ "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,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 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": "entertainment",
+ "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,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 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": "eris_control",
+ "directions": 4,
+ "delays": [
+ [
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5,
+ 0.5
+ ]
+ ]
+ },
+ {
+ "name": "error",
+ "directions": 4
+ },
+ {
+ "name": "explosive",
+ "directions": 4,
+ "delays": [
+ [
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1,
+ 1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "forensic",
+ "directions": 4,
+ "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,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 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": "generic",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "generic_keys",
+ "directions": 4
+ },
+ {
+ "name": "generic_keyboard",
+ "directions": 4
+ },
+ {
+ "name": "holocontrol",
+ "directions": 4,
+ "delays": [
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "id",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "id_key",
+ "directions": 4
+ },
+ {
+ "name": "id_key_off",
+ "directions": 4
+ },
+ {
+ "name": "mass_driver"
+ },
+ {
+ "name": "mecha",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "med_key",
+ "directions": 4
+ },
+ {
+ "name": "med_key_off",
+ "directions": 4
+ },
+ {
+ "name": "medcomp",
+ "directions": 4,
+ "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,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2,
+ 0.2,
+ 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": "mining",
+ "directions": 4,
+ "delays": [
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ],
+ [
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1,
+ 1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "mining_key",
+ "directions": 4
+ },
+ {
+ "name": "mining_key_off",
+ "directions": 4
+ },
+ {
+ "name": "power_key",
+ "directions": 4
+ },
+ {
+ "name": "power_key_off",
+ "directions": 4
+ },
+ {
+ "name": "power_monitor",
+ "directions": 4,
+ "delays": [
+ [
+ 0.6,
+ 0.6,
+ 0.6,
+ 0.6
+ ],
+ [
+ 0.6,
+ 0.6,
+ 0.6,
+ 0.6
+ ],
+ [
+ 0.6,
+ 0.6,
+ 0.6,
+ 0.6
+ ],
+ [
+ 0.6,
+ 0.6,
+ 0.6,
+ 0.6
+ ]
+ ]
+ },
+ {
+ "name": "power_monitor_warn",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "rd_key",
+ "directions": 4
+ },
+ {
+ "name": "rd_key_off",
+ "directions": 4
+ },
+ {
+ "name": "rdcomp",
+ "directions": 4
+ },
+ {
+ "name": "recharge_comp",
+ "directions": 4
+ },
+ {
+ "name": "recharge_comp_on",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "request",
+ "directions": 4,
+ "delays": [
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ],
+ [
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3,
+ 0.3
+ ]
+ ]
+ },
+ {
+ "name": "robot",
+ "directions": 4
+ },
+ {
+ "name": "security",
+ "directions": 4,
+ "delays": [
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ],
+ [
+ 0.2,
+ 0.2
+ ]
+ ]
+ },
+ {
+ "name": "security_key",
+ "directions": 4
+ },
+ {
+ "name": "security_key_off",
+ "directions": 4
+ },
+ {
+ "name": "shuttle",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "solar_screen",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "supply",
+ "directions": 4
+ },
+ {
+ "name": "syndie_key",
+ "directions": 4
+ },
+ {
+ "name": "syndie_key_off",
+ "directions": 4
+ },
+ {
+ "name": "syndishuttle",
+ "directions": 4
+ },
+ {
+ "name": "tank",
+ "directions": 4
+ },
+ {
+ "name": "tcboss",
+ "directions": 4
+ },
+ {
+ "name": "tech_key",
+ "directions": 4
+ },
+ {
+ "name": "tech_key_off",
+ "directions": 4
+ },
+ {
+ "name": "teleport",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "teleport_key",
+ "directions": 4
+ },
+ {
+ "name": "teleport_key_off",
+ "directions": 4
+ },
+ {
+ "name": "telesci",
+ "directions": 4,
+ "delays": [
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ],
+ [
+ 0.1,
+ 0.1,
+ 0.1,
+ 0.1
+ ]
+ ]
+ },
+ {
+ "name": "telesci_key",
+ "directions": 4
+ },
+ {
+ "name": "telesci_key_off",
+ "directions": 4
+ },
+ {
+ "name": "turbinecomp",
+ "directions": 4
+ },
+ {
+ "name": "computer-datatheory"
+ },
+ {
+ "name": "avionics-systems"
+ },
+ {
+ "name": "television"
+ },
+ {
+ "name": "television_broken"
+ },
+ {
+ "name": "telescreen",
+ "directions": 4
+ },
+ {
+ "name": "telescreen_frame",
+ "directions": 4
+ },
+ {
+ "name": "telescreen_broken",
+ "directions": 4
+ },
+ {
+ "name": "detective_television"
+ },
+ {
+ "directions": 4,
+ "name": "service",
+ "delays": [
+ [
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5
+ ],
+ [
+ 0.5,
+ 0.5,
+ 0.5
+ ]
+ ]
+ },
+ {
+ "name": "service_keys",
+ "directions": 4
+ }
+ ]
}
diff --git a/Resources/Textures/Structures/Machines/computers.rsi/service.png b/Resources/Textures/Structures/Machines/computers.rsi/service.png
new file mode 100644
index 0000000000..9d9884e4be
Binary files /dev/null and b/Resources/Textures/Structures/Machines/computers.rsi/service.png differ
diff --git a/Resources/Textures/Structures/Machines/computers.rsi/service_keys.png b/Resources/Textures/Structures/Machines/computers.rsi/service_keys.png
new file mode 100644
index 0000000000..691c996080
Binary files /dev/null and b/Resources/Textures/Structures/Machines/computers.rsi/service_keys.png differ