diff --git a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs
new file mode 100644
index 0000000000..c00e78c8d6
--- /dev/null
+++ b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUi.cs
@@ -0,0 +1,29 @@
+using Content.Client.UserInterface.Fragments;
+using Content.Shared.CartridgeLoader.Cartridges;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface;
+
+namespace Content.Client.CartridgeLoader.Cartridges;
+
+public sealed class CrewManifestUi : UIFragment
+{
+ private CrewManifestUiFragment? _fragment;
+
+ public override Control GetUIFragmentRoot()
+ {
+ return _fragment!;
+ }
+
+ public override void Setup(BoundUserInterface userInterface, EntityUid? fragmentOwner)
+ {
+ _fragment = new CrewManifestUiFragment();
+ }
+
+ public override void UpdateState(BoundUserInterfaceState state)
+ {
+ if (state is not CrewManifestUiState crewManifestState)
+ return;
+
+ _fragment?.UpdateState(crewManifestState.StationName, crewManifestState.Entries);
+ }
+}
diff --git a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml
new file mode 100644
index 0000000000..14b06c90ad
--- /dev/null
+++ b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs
new file mode 100644
index 0000000000..273707cb6e
--- /dev/null
+++ b/Content.Client/CartridgeLoader/Cartridges/CrewManifestUiFragment.xaml.cs
@@ -0,0 +1,34 @@
+using Content.Shared.CrewManifest;
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.Controls;
+using Robust.Client.UserInterface.XAML;
+
+namespace Content.Client.CartridgeLoader.Cartridges;
+
+[GenerateTypedNameReferences]
+public sealed partial class CrewManifestUiFragment : BoxContainer
+{
+ public CrewManifestUiFragment()
+ {
+ RobustXamlLoader.Load(this);
+
+ StationName.AddStyleClass("LabelBig");
+ Orientation = LayoutOrientation.Vertical;
+ HorizontalExpand = true;
+ VerticalExpand = true;
+ }
+
+ public void UpdateState(string stationName, CrewManifestEntries? entries)
+ {
+ CrewManifestListing.DisposeAllChildren();
+ CrewManifestListing.RemoveAllChildren();
+
+ StationNameContainer.Visible = entries != null;
+ StationName.Text = stationName;
+
+ if (entries == null)
+ return;
+
+ CrewManifestListing.AddCrewManifestEntries(entries);
+ }
+}
diff --git a/Content.Client/CrewManifest/CrewManifestUi.xaml b/Content.Client/CrewManifest/CrewManifestUi.xaml
index b025e79d97..db3a7ac390 100644
--- a/Content.Client/CrewManifest/CrewManifestUi.xaml
+++ b/Content.Client/CrewManifest/CrewManifestUi.xaml
@@ -1,5 +1,6 @@
@@ -11,9 +12,9 @@
-
+
-
+
diff --git a/Content.Client/CrewManifest/CrewManifestUi.xaml.cs b/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
index 5cfead0d8b..4183c90814 100644
--- a/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
+++ b/Content.Client/CrewManifest/CrewManifestUi.xaml.cs
@@ -1,37 +1,16 @@
-using System.Linq;
-using System.Numerics;
-using Content.Shared.CCVar;
using Content.Shared.CrewManifest;
-using Content.Shared.Roles;
-using Content.Shared.StatusIcon;
using Robust.Client.AutoGenerated;
-using Robust.Client.GameObjects;
-using Robust.Client.ResourceManagement;
-using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Client.UserInterface.XAML;
-using Robust.Client.Utility;
-using Robust.Shared.Configuration;
-using Robust.Shared.Prototypes;
-using Robust.Shared.Utility;
namespace Content.Client.CrewManifest;
[GenerateTypedNameReferences]
public sealed partial class CrewManifestUi : DefaultWindow
{
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IResourceCache _resourceCache = default!;
- [Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
- [Dependency] private readonly IConfigurationManager _configManager = default!;
-
- private readonly CrewManifestSystem _crewManifestSystem;
-
public CrewManifestUi()
{
RobustXamlLoader.Load(this);
- IoCManager.InjectDependencies(this);
- _crewManifestSystem = _entitySystemManager.GetEntitySystem();
StationName.AddStyleClass("LabelBig");
}
@@ -44,131 +23,9 @@ public sealed partial class CrewManifestUi : DefaultWindow
StationNameContainer.Visible = entries != null;
StationName.Text = name;
- if (entries == null) return;
+ if (entries == null)
+ return;
- var entryList = SortEntries(entries);
-
- foreach (var item in entryList)
- {
- CrewManifestListing.AddChild(new CrewManifestSection(item.section, item.entries, _resourceCache, _crewManifestSystem));
- }
- }
-
- private List<(string section, List entries)> SortEntries(CrewManifestEntries entries)
- {
- var entryDict = new Dictionary>();
-
- foreach (var entry in entries.Entries)
- {
- foreach (var department in _prototypeManager.EnumeratePrototypes())
- {
- // this is a little expensive, and could be better
- if (department.Roles.Contains(entry.JobPrototype))
- {
- entryDict.GetOrNew(department.ID).Add(entry);
- }
- }
- }
-
- var entryList = new List<(string section, List entries)>();
-
- foreach (var (section, listing) in entryDict)
- {
- entryList.Add((section, listing));
- }
-
- var sortOrder = _configManager.GetCVar(CCVars.CrewManifestOrdering).Split(",").ToList();
-
- entryList.Sort((a, b) =>
- {
- var ai = sortOrder.IndexOf(a.section);
- var bi = sortOrder.IndexOf(b.section);
-
- // this is up here so -1 == -1 occurs first
- if (ai == bi)
- return 0;
-
- if (ai == -1)
- return -1;
-
- if (bi == -1)
- return 1;
-
- return ai.CompareTo(bi);
- });
-
- return entryList;
- }
-
- private sealed class CrewManifestSection : BoxContainer
- {
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
- private readonly SpriteSystem _spriteSystem = default!;
-
- public CrewManifestSection(string sectionTitle, List entries, IResourceCache cache, CrewManifestSystem crewManifestSystem)
- {
- IoCManager.InjectDependencies(this);
- _spriteSystem = _entitySystem.GetEntitySystem();
-
- Orientation = LayoutOrientation.Vertical;
- HorizontalExpand = true;
-
- if (Loc.TryGetString($"department-{sectionTitle}", out var localizedDepart))
- sectionTitle = localizedDepart;
-
- AddChild(new Label()
- {
- StyleClasses = { "LabelBig" },
- Text = Loc.GetString(sectionTitle)
- });
-
- var gridContainer = new GridContainer()
- {
- HorizontalExpand = true,
- Columns = 2
- };
-
- AddChild(gridContainer);
-
- foreach (var entry in entries)
- {
- var name = new RichTextLabel()
- {
- HorizontalExpand = true,
- };
- name.SetMessage(entry.Name);
-
- var titleContainer = new BoxContainer()
- {
- Orientation = LayoutOrientation.Horizontal,
- HorizontalExpand = true
- };
-
- var title = new RichTextLabel();
- title.SetMessage(entry.JobTitle);
-
-
- if (_prototypeManager.TryIndex(entry.JobIcon, out var jobIcon))
- {
- var icon = new TextureRect()
- {
- TextureScale = new Vector2(2, 2),
- Stretch = TextureRect.StretchMode.KeepCentered,
- Texture = _spriteSystem.Frame0(jobIcon.Icon),
- };
-
- titleContainer.AddChild(icon);
- titleContainer.AddChild(title);
- }
- else
- {
- titleContainer.AddChild(title);
- }
-
- gridContainer.AddChild(name);
- gridContainer.AddChild(titleContainer);
- }
- }
+ CrewManifestListing.AddCrewManifestEntries(entries);
}
}
diff --git a/Content.Client/CrewManifest/UI/CrewManifestListing.cs b/Content.Client/CrewManifest/UI/CrewManifestListing.cs
new file mode 100644
index 0000000000..614add536e
--- /dev/null
+++ b/Content.Client/CrewManifest/UI/CrewManifestListing.cs
@@ -0,0 +1,74 @@
+using Content.Shared.CCVar;
+using Content.Shared.CrewManifest;
+using Content.Shared.Roles;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Configuration;
+using Robust.Shared.Prototypes;
+using Robust.Shared.Utility;
+using System.Linq;
+
+namespace Content.Client.CrewManifest.UI;
+
+public sealed class CrewManifestListing : BoxContainer
+{
+ [Dependency] private readonly IConfigurationManager _configManager = default!;
+ [Dependency] private readonly IEntitySystemManager _entitySystem = default!;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ private readonly SpriteSystem _spriteSystem;
+
+ public CrewManifestListing()
+ {
+ IoCManager.InjectDependencies(this);
+ _spriteSystem = _entitySystem.GetEntitySystem();
+ }
+
+ public void AddCrewManifestEntries(CrewManifestEntries entries)
+ {
+ var entryDict = new Dictionary>();
+
+ foreach (var entry in entries.Entries)
+ {
+ foreach (var department in _prototypeManager.EnumeratePrototypes())
+ {
+ // this is a little expensive, and could be better
+ if (department.Roles.Contains(entry.JobPrototype))
+ {
+ entryDict.GetOrNew(department.ID).Add(entry);
+ }
+ }
+ }
+
+ var entryList = new List<(string section, List entries)>();
+
+ foreach (var (section, listing) in entryDict)
+ {
+ entryList.Add((section, listing));
+ }
+
+ var sortOrder = _configManager.GetCVar(CCVars.CrewManifestOrdering).Split(",").ToList();
+
+ entryList.Sort((a, b) =>
+ {
+ var ai = sortOrder.IndexOf(a.section);
+ var bi = sortOrder.IndexOf(b.section);
+
+ // this is up here so -1 == -1 occurs first
+ if (ai == bi)
+ return 0;
+
+ if (ai == -1)
+ return -1;
+
+ if (bi == -1)
+ return 1;
+
+ return ai.CompareTo(bi);
+ });
+
+ foreach (var item in entryList)
+ {
+ AddChild(new CrewManifestSection(_prototypeManager, _spriteSystem, item.section, item.entries));
+ }
+ }
+}
diff --git a/Content.Client/CrewManifest/UI/CrewManifestSection.cs b/Content.Client/CrewManifest/UI/CrewManifestSection.cs
new file mode 100644
index 0000000000..9b51b5d424
--- /dev/null
+++ b/Content.Client/CrewManifest/UI/CrewManifestSection.cs
@@ -0,0 +1,74 @@
+using Content.Shared.CrewManifest;
+using Content.Shared.StatusIcon;
+using Robust.Client.GameObjects;
+using Robust.Client.UserInterface.Controls;
+using Robust.Shared.Prototypes;
+using System.Numerics;
+
+namespace Content.Client.CrewManifest.UI;
+
+public sealed class CrewManifestSection : BoxContainer
+{
+ public CrewManifestSection(IPrototypeManager prototypeManager, SpriteSystem spriteSystem, string sectionTitle,
+ List entries)
+ {
+ Orientation = LayoutOrientation.Vertical;
+ HorizontalExpand = true;
+
+ if (Loc.TryGetString($"department-{sectionTitle}", out var localizedDepart))
+ sectionTitle = localizedDepart;
+
+ AddChild(new Label()
+ {
+ StyleClasses = { "LabelBig" },
+ Text = Loc.GetString(sectionTitle)
+ });
+
+ var gridContainer = new GridContainer()
+ {
+ HorizontalExpand = true,
+ Columns = 2
+ };
+
+ AddChild(gridContainer);
+
+ foreach (var entry in entries)
+ {
+ var name = new RichTextLabel()
+ {
+ HorizontalExpand = true,
+ };
+ name.SetMessage(entry.Name);
+
+ var titleContainer = new BoxContainer()
+ {
+ Orientation = LayoutOrientation.Horizontal,
+ HorizontalExpand = true
+ };
+
+ var title = new RichTextLabel();
+ title.SetMessage(entry.JobTitle);
+
+
+ if (prototypeManager.TryIndex(entry.JobIcon, out var jobIcon))
+ {
+ var icon = new TextureRect()
+ {
+ TextureScale = new Vector2(2, 2),
+ Stretch = TextureRect.StretchMode.KeepCentered,
+ Texture = spriteSystem.Frame0(jobIcon.Icon),
+ };
+
+ titleContainer.AddChild(icon);
+ titleContainer.AddChild(title);
+ }
+ else
+ {
+ titleContainer.AddChild(title);
+ }
+
+ gridContainer.AddChild(name);
+ gridContainer.AddChild(titleContainer);
+ }
+ }
+}
diff --git a/Content.Client/PDA/PdaBoundUserInterface.cs b/Content.Client/PDA/PdaBoundUserInterface.cs
index bd23d5ea55..059d3c0aef 100644
--- a/Content.Client/PDA/PdaBoundUserInterface.cs
+++ b/Content.Client/PDA/PdaBoundUserInterface.cs
@@ -1,8 +1,6 @@
using Content.Client.CartridgeLoader;
using Content.Shared.CartridgeLoader;
-using Content.Shared.CCVar;
using Content.Shared.Containers.ItemSlots;
-using Content.Shared.CrewManifest;
using Content.Shared.PDA;
using JetBrains.Annotations;
using Robust.Client.UserInterface;
@@ -13,8 +11,6 @@ namespace Content.Client.PDA
[UsedImplicitly]
public sealed class PdaBoundUserInterface : CartridgeLoaderBoundUserInterface
{
- [Dependency] private readonly IConfigurationManager _configManager = default!;
-
[ViewVariables]
private PdaMenu? _menu;
@@ -34,15 +30,6 @@ namespace Content.Client.PDA
SendMessage(new PdaToggleFlashlightMessage());
};
- if (_configManager.GetCVar(CCVars.CrewManifestUnsecure))
- {
- _menu.CrewManifestButton.Visible = true;
- _menu.CrewManifestButton.OnPressed += _ =>
- {
- SendMessage(new CrewManifestOpenUiMessage());
- };
- }
-
_menu.EjectIdButton.OnPressed += _ =>
{
SendMessage(new ItemSlotButtonPressedEvent(PdaComponent.PdaIdSlotId));
diff --git a/Content.Client/PDA/PdaMenu.xaml b/Content.Client/PDA/PdaMenu.xaml
index dbdcb4d90b..9f9dad6640 100644
--- a/Content.Client/PDA/PdaMenu.xaml
+++ b/Content.Client/PDA/PdaMenu.xaml
@@ -60,11 +60,6 @@
Access="Public"
Text="{Loc 'comp-pda-ui-ringtone-button'}"
Description="{Loc 'comp-pda-ui-ringtone-button-description'}"/>
-
();
//Don't count a cartridge that has already been installed as available to avoid confusion
- if (loader.CartridgeSlot.HasItem && IsInstalled(Prototype(loader.CartridgeSlot.Item!.Value)?.ID, loader))
+ if (loader.CartridgeSlot.HasItem && TryFindInstalled(Prototype(loader.CartridgeSlot.Item!.Value)?.ID, loader, out _))
return loader.InstalledPrograms;
var available = new List();
@@ -127,7 +128,13 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
return false;
//Prevent installing cartridges that have already been installed
- if (IsInstalled(prototype, loader))
+ if (TryFindInstalled(prototype, loader, out _))
+ return false;
+
+ var ev = new ProgramInstallationAttempt(loaderUid, prototype);
+ RaiseLocalEvent(ref ev);
+
+ if (ev.Cancelled)
return false;
var installedProgram = Spawn(prototype, new EntityCoordinates(loaderUid, 0, 0));
@@ -141,6 +148,22 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
return true;
}
+ ///
+ /// Uninstalls a program using its prototype
+ ///
+ /// The cartridge loader uid
+ /// The prototype name of the program to be uninstalled
+ /// The cartridge loader component
+ /// Whether uninstalling the program was successful
+ public bool UninstallProgram(EntityUid loaderUid, string prototype, CartridgeLoaderComponent? loader = default!)
+ {
+ if (!Resolve(loaderUid, ref loader))
+ return false;
+
+ return TryFindInstalled(prototype, loader, out var programUid) &&
+ UninstallProgram(loaderUid, programUid.Value, loader);
+ }
+
///
/// Uninstalls a program using its uid
///
@@ -345,16 +368,20 @@ public sealed class CartridgeLoaderSystem : SharedCartridgeLoaderSystem
}
///
- /// Checks if a program is already installed by searching for its prototype name in the list of installed programs
+ /// Searches for a program by its prototype name in the list of installed programs
///
- private bool IsInstalled(string? prototype, CartridgeLoaderComponent loader)
+ private bool TryFindInstalled(string? prototype, CartridgeLoaderComponent loader, [NotNullWhen(true)] out EntityUid? programUid)
{
foreach (var program in loader.InstalledPrograms)
{
if (Prototype(program)?.ID == prototype)
+ {
+ programUid = program;
return true;
+ }
}
+ programUid = default;
return false;
}
@@ -414,3 +441,9 @@ public sealed class CartridgeAfterInteractEvent : EntityEventArgs
InteractEvent = interactEvent;
}
}
+
+///
+/// Raised on an attempt of program installation.
+///
+[ByRefEvent]
+public record struct ProgramInstallationAttempt(EntityUid LoaderUid, string Prototype, bool Cancelled = false);
diff --git a/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeComponent.cs b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeComponent.cs
new file mode 100644
index 0000000000..344f8674e3
--- /dev/null
+++ b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeComponent.cs
@@ -0,0 +1,6 @@
+namespace Content.Server.CartridgeLoader.Cartridges;
+
+[RegisterComponent]
+public sealed class CrewManifestCartridgeComponent : Component
+{
+}
diff --git a/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs
new file mode 100644
index 0000000000..74757c1f79
--- /dev/null
+++ b/Content.Server/CartridgeLoader/Cartridges/CrewManifestCartridgeSystem.cs
@@ -0,0 +1,95 @@
+using Content.Server.CrewManifest;
+using Content.Server.Station.Systems;
+using Content.Shared.CartridgeLoader;
+using Content.Shared.CartridgeLoader.Cartridges;
+using Content.Shared.CCVar;
+using Robust.Shared.Configuration;
+
+namespace Content.Server.CartridgeLoader.Cartridges;
+
+public sealed class CrewManifestCartridgeSystem : EntitySystem
+{
+ [Dependency] private readonly CartridgeLoaderSystem _cartridgeLoader = default!;
+ [Dependency] private readonly IConfigurationManager _configManager = default!;
+ [Dependency] private readonly CrewManifestSystem _crewManifest = default!;
+ [Dependency] private readonly StationSystem _stationSystem = default!;
+
+ private const string CartridgePrototypeName = "CrewManifestCartridge";
+
+ ///
+ /// Flag that shows that if crew manifest is allowed to be viewed from 'unsecure' entities,
+ /// which is the keys for the cartridge.
+ ///
+ private bool _unsecureViewersAllowed = true;
+
+ public override void Initialize()
+ {
+ base.Initialize();
+ SubscribeLocalEvent(OnUiMessage);
+ SubscribeLocalEvent(OnUiReady);
+ SubscribeLocalEvent(OnInstallationAttempt);
+ _configManager.OnValueChanged(CCVars.CrewManifestUnsecure, OnCrewManifestUnsecureChanged, true);
+ }
+
+ ///
+ /// The ui messages received here get wrapped by a CartridgeMessageEvent and are relayed from the
+ ///
+ ///
+ /// The cartridge specific ui message event needs to inherit from the CartridgeMessageEvent
+ ///
+ private void OnUiMessage(EntityUid uid, CrewManifestCartridgeComponent component, CartridgeMessageEvent args)
+ {
+ UpdateUiState(uid, args.LoaderUid, component);
+ }
+
+ ///
+ /// This gets called when the ui fragment needs to be updated for the first time after activating
+ ///
+ private void OnUiReady(EntityUid uid, CrewManifestCartridgeComponent component, CartridgeUiReadyEvent args)
+ {
+ UpdateUiState(uid, args.Loader, component);
+ }
+
+ private void UpdateUiState(EntityUid uid, EntityUid loaderUid, CrewManifestCartridgeComponent? component)
+ {
+ if (!Resolve(uid, ref component))
+ return;
+
+ var owningStation = _stationSystem.GetOwningStation(uid);
+
+ if (owningStation is null)
+ return;
+
+ var (stationName, entries) = _crewManifest.GetCrewManifest(owningStation.Value);
+
+ var state = new CrewManifestUiState(stationName, entries);
+ _cartridgeLoader.UpdateCartridgeUiState(loaderUid, state);
+ }
+
+ private void OnInstallationAttempt(ref ProgramInstallationAttempt args)
+ {
+ if (args.Prototype == CartridgePrototypeName && !_unsecureViewersAllowed)
+ args.Cancelled = true;
+ }
+
+ private void OnCrewManifestUnsecureChanged(bool unsecureViewersAllowed)
+ {
+ _unsecureViewersAllowed = unsecureViewersAllowed;
+
+ var allCartridgeLoaders = AllEntityQuery();
+
+ while (allCartridgeLoaders.MoveNext(out EntityUid loaderUid, out CartridgeLoaderComponent? comp))
+ {
+ if (_unsecureViewersAllowed)
+ _cartridgeLoader?.InstallProgram(loaderUid, CartridgePrototypeName, false, comp);
+ else
+ _cartridgeLoader?.UninstallProgram(loaderUid, CartridgePrototypeName, comp);
+ }
+ }
+
+ public override void Shutdown()
+ {
+ base.Shutdown();
+ _configManager.UnsubValueChanged(CCVars.CrewManifestUnsecure, OnCrewManifestUnsecureChanged);
+ }
+}
diff --git a/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs b/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs
new file mode 100644
index 0000000000..9eaca5a2d3
--- /dev/null
+++ b/Content.Shared/CartridgeLoader/Cartridges/CrewManifestUiState.cs
@@ -0,0 +1,17 @@
+using Content.Shared.CrewManifest;
+using Robust.Shared.Serialization;
+
+namespace Content.Shared.CartridgeLoader.Cartridges;
+
+[Serializable, NetSerializable]
+public sealed class CrewManifestUiState : BoundUserInterfaceState
+{
+ public string StationName;
+ public CrewManifestEntries? Entries;
+
+ public CrewManifestUiState(string stationName, CrewManifestEntries? entries)
+ {
+ StationName = stationName;
+ Entries = entries;
+ }
+}
diff --git a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
index 3be0fdcce0..f324da7be6 100644
--- a/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
+++ b/Resources/Locale/en-US/cartridge-loader/cartridges.ftl
@@ -2,6 +2,9 @@
notekeeper-program-name = Notekeeper
news-read-program-name = Station news
+crew-manifest-program-name = Crew manifest
+crew-manifest-cartridge-loading = Loading ...
+
net-probe-program-name = NetProbe
net-probe-scan = Scanned {$device}!
net-probe-label-name = Name
diff --git a/Resources/Prototypes/Entities/Objects/Devices/cartridges.yml b/Resources/Prototypes/Entities/Objects/Devices/cartridges.yml
index 78092d414e..739e0f394f 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/cartridges.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/cartridges.yml
@@ -7,9 +7,6 @@
- type: Sprite
sprite: Objects/Devices/cartridge.rsi
state: cart-y
- - type: Icon
- sprite: Objects/Devices/cartridge.rsi
- state: cart-y
- type: UIFragment
ui: !type:NotekeeperUi
- type: Cartridge
@@ -28,9 +25,6 @@
- type: Sprite
sprite: Objects/Devices/cartridge.rsi
state: cart-y
- - type: Icon
- sprite: Objects/Devices/cartridge.rsi
- state: cart-y
- type: UIFragment
ui: !type:NewsReadUi
- type: Cartridge
@@ -40,6 +34,24 @@
state: news_read
- type: NewsReadCartridge
+- type: entity
+ parent: BaseItem
+ id: CrewManifestCartridge
+ name: Crew Manifest Cartridge
+ description: A program for listing your fellow crewmembers
+ components:
+ - type: Sprite
+ sprite: Objects/Devices/cartridge.rsi
+ state: cart-y
+ - type: UIFragment
+ ui: !type:CrewManifestUi
+ - type: Cartridge
+ programName: crew-manifest-program-name
+ icon:
+ sprite: Interface/Misc/program_icons.rsi
+ state: crew_manifest
+ - type: CrewManifestCartridge
+
- type: entity
parent: BaseItem
id: NetProbeCartridge
@@ -49,9 +61,6 @@
- type: Sprite
sprite: Objects/Devices/cartridge.rsi
state: cart-y
- - type: Icon
- sprite: Objects/Devices/cartridge.rsi
- state: cart-y
- type: UIFragment
ui: !type:NetProbeUi
- type: Cartridge
diff --git a/Resources/Prototypes/Entities/Objects/Devices/pda.yml b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
index 161a68124c..53bf43f742 100644
--- a/Resources/Prototypes/Entities/Objects/Devices/pda.yml
+++ b/Resources/Prototypes/Entities/Objects/Devices/pda.yml
@@ -72,6 +72,7 @@
- type: CartridgeLoader
uiKey: enum.PdaUiKey.Key
preinstalled:
+ - CrewManifestCartridge
- NotekeeperCartridge
- NewsReadCartridge
cartridgeSlot:
diff --git a/Resources/Textures/Interface/Misc/program_icons.rsi/crew_manifest.png b/Resources/Textures/Interface/Misc/program_icons.rsi/crew_manifest.png
new file mode 100644
index 0000000000..1896ffcdfa
Binary files /dev/null and b/Resources/Textures/Interface/Misc/program_icons.rsi/crew_manifest.png differ
diff --git a/Resources/Textures/Interface/Misc/program_icons.rsi/meta.json b/Resources/Textures/Interface/Misc/program_icons.rsi/meta.json
index 5ed7f67860..4c2a45ad76 100644
--- a/Resources/Textures/Interface/Misc/program_icons.rsi/meta.json
+++ b/Resources/Textures/Interface/Misc/program_icons.rsi/meta.json
@@ -1,7 +1,7 @@
{
"version": 1,
"license": "CC-BY-SA-3.0",
- "copyright": "Made with love, by Misha_Unity",
+ "copyright": "news_read by Misha_Unity, crew_manifest by Phill101",
"size": {
"x": 32,
"y": 32
@@ -9,6 +9,9 @@
"states": [
{
"name": "news_read"
+ },
+ {
+ "name": "crew_manifest"
}
]
}