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" } ] }