diff --git a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs new file mode 100644 index 0000000000..6b30c82036 --- /dev/null +++ b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs @@ -0,0 +1,432 @@ +using System; +using Content.Client.Utility; +using Content.Shared.GameObjects.Components.PDA; +using Robust.Client.GameObjects.Components.UserInterface; +using Robust.Client.Graphics.Drawing; +using Robust.Client.UserInterface.Controls; +using Robust.Client.UserInterface.CustomControls; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using Robust.Shared.Utility; + +namespace Content.Client.GameObjects.Components.PDA +{ + public class PDABoundUserInterface : BoundUserInterface + { +#pragma warning disable 649 + [Dependency] private readonly IPrototypeManager _prototypeManager; +#pragma warning restore 649 + private PDAMenu _menu; + private ClientUserInterfaceComponent Owner; + + public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey) + { + Owner = owner; + } + + protected override void Open() + { + base.Open(); + SendMessage(new PDARequestUpdateInterfaceMessage()); + _menu = new PDAMenu(this, _prototypeManager); + _menu.OpenToLeft(); + _menu.OnClose += Close; + _menu.FlashLightToggleButton.OnToggled += args => + { + SendMessage(new PDAToggleFlashlightMessage()); + }; + + _menu.EjectIDButton.OnPressed += args => + { + SendMessage(new PDAEjectIDMessage()); + }; + + _menu.MasterTabContainer.OnTabChanged += i => + { + var tab = _menu.MasterTabContainer.GetChild(i); + if (tab == _menu.UplinkTabContainer) + { + SendMessage(new PDARequestUpdateInterfaceMessage()); + } + }; + + _menu.OnListingButtonPressed += (args, listing) => + { + SendMessage(new PDAUplinkBuyListingMessage(listing)); + }; + + _menu.OnCategoryButtonPressed += (args, category) => + { + _menu.CurrentFilterCategory = category; + SendMessage(new PDARequestUpdateInterfaceMessage()); + + }; + } + + + protected override void UpdateState(BoundUserInterfaceState state) + { + base.UpdateState(state); + DebugTools.Assert((state is PDAUBoundUserInterfaceState)); + + var cstate = (PDAUBoundUserInterfaceState) state; + switch (state) + { + case PDAUpdateState msg: + { + _menu.FlashLightToggleButton.Pressed = msg.FlashlightEnabled; + _menu.PDAOwnerLabel.SetMarkup(Loc.GetString("Owner: [color=white]{0}[/color]", + msg.PDAOwnerInfo.ActualOwnerName)); + + if (msg.PDAOwnerInfo.JobTitle == null || msg.PDAOwnerInfo.IdOwner == null) + { + _menu.IDInfoLabel.SetMarkup(Loc.GetString("ID:")); + } + else + { + _menu.IDInfoLabel.SetMarkup(Loc.GetString( + "ID: [color=white]{0}[/color], [color=yellow]{1}[/color]", + msg.PDAOwnerInfo.IdOwner, + msg.PDAOwnerInfo.JobTitle)); + } + + _menu.EjectIDButton.Visible = msg.PDAOwnerInfo.IdOwner != null; + if (msg.Account != null) + { + _menu.CurrentLoggedInAccount = msg.Account; + } + + if (msg.Listings != null) + { + _menu.ClearListings(); + foreach (var item in msg.Listings) //Should probably chunk these out instead. to-do if this clogs the internet tubes. + { + _menu.AddListingGui(item); + } + } + break; + } + + } + } + + protected override void Dispose(bool disposing) + { + base.Dispose(disposing); + _menu?.Dispose(); + } + + private class PDAMenu : SS14Window + { + protected override Vector2? CustomSize => (512, 256); + + private PDABoundUserInterface _owner { get; } + + public Button FlashLightToggleButton { get; } + public Button EjectIDButton { get; } + + public TabContainer MasterTabContainer; + + public RichTextLabel PDAOwnerLabel { get; } + public PanelContainer IDInfoContainer { get; } + public RichTextLabel IDInfoLabel { get; } + + public VBoxContainer UplinkTabContainer { get; } + + protected HSplitContainer CategoryAndListingsContainer; + + private IPrototypeManager _prototypeManager; + + public VBoxContainer UplinkListingsContainer; + + public VBoxContainer CategoryListContainer; + public event Action OnListingButtonPressed; + public event Action OnCategoryButtonPressed; + + public UplinkCategory CurrentFilterCategory + { + get => _currentFilter; + set + { + if (value.GetType() != typeof(UplinkCategory)) + { + return; + } + + _currentFilter = value; + } + } + + public UplinkAccountData CurrentLoggedInAccount + { + get => _loggedInUplinkAccount; + set => _loggedInUplinkAccount = value; + } + + + private UplinkCategory _currentFilter; + private UplinkAccountData _loggedInUplinkAccount; + + + public PDAMenu(PDABoundUserInterface owner, IPrototypeManager prototypeManager) + { + _owner = owner; + _prototypeManager = prototypeManager; + Title = Loc.GetString("PDA"); + + #region MAIN_MENU_TAB + //Main menu + PDAOwnerLabel = new RichTextLabel + { + }; + + IDInfoLabel = new RichTextLabel() + { + SizeFlagsHorizontal = SizeFlags.FillExpand, + }; + + EjectIDButton = new Button + { + Text = Loc.GetString("Eject ID"), + SizeFlagsHorizontal = SizeFlags.ShrinkCenter, + SizeFlagsVertical = SizeFlags.ShrinkCenter + }; + + var innerHBoxContainer = new HBoxContainer + { + Children = + { + IDInfoLabel, + EjectIDButton + } + }; + + IDInfoContainer = new PanelContainer + { + SizeFlagsHorizontal = SizeFlags.Fill, + Children = + { + innerHBoxContainer, + } + }; + + FlashLightToggleButton = new Button + { + Text = Loc.GetString("Toggle Flashlight"), + ToggleMode = true, + }; + + var mainMenuTabContainer = new VBoxContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsHorizontal = SizeFlags.FillExpand, + CustomMinimumSize = (50, 50), + + Children = + { + PDAOwnerLabel, + IDInfoContainer, + FlashLightToggleButton + } + }; + + #endregion + + #region UPLINK_TAB + //Uplink Tab + CategoryListContainer = new VBoxContainer + { + }; + var uplinkStoreHeader = new Label + { + Align = Label.AlignMode.Center, + Text = Loc.GetString("Uplink Listings"), + }; + + //Red background container. + var masterPanelContainer = new PanelContainer + { + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.DarkRed.WithAlpha(0.6f)}, + SizeFlagsVertical = SizeFlags.FillExpand + }; + + //This contains both the panel of the category buttons and the listings box. + CategoryAndListingsContainer = new HSplitContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + }; + + + var uplinkShopScrollContainer = new ScrollContainer + { + SizeFlagsHorizontal = SizeFlags.FillExpand, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 2, + CustomMinimumSize = (100, 256) + }; + + //Add the category list to the left side. The store items to center. + var categoryListContainerBackground = new PanelContainer + { + PanelOverride = new StyleBoxFlat {BackgroundColor = Color.Black.WithAlpha(0.4f)}, + SizeFlagsVertical = SizeFlags.FillExpand, + Children = + { + CategoryListContainer + } + }; + + CategoryAndListingsContainer.AddChild(categoryListContainerBackground); + CategoryAndListingsContainer.AddChild(uplinkShopScrollContainer); + masterPanelContainer.AddChild(CategoryAndListingsContainer); + + //Actual list of buttons for buying a listing from the uplink. + UplinkListingsContainer = new VBoxContainer + { + SizeFlagsHorizontal = SizeFlags.FillExpand, + SizeFlagsVertical = SizeFlags.FillExpand, + SizeFlagsStretchRatio = 2, + CustomMinimumSize = (100, 256), + }; + uplinkShopScrollContainer.AddChild(UplinkListingsContainer); + + var innerVboxContainer = new VBoxContainer + { + SizeFlagsVertical = SizeFlags.FillExpand, + + Children = + { + uplinkStoreHeader, + masterPanelContainer + } + }; + + UplinkTabContainer = new VBoxContainer + { + Children = + { + innerVboxContainer + } + }; + PopulateUplinkCategoryButtons(); + #endregion + + //The master menu that contains all of the tabs. + MasterTabContainer = new TabContainer + { + Children = + { + mainMenuTabContainer, + } + }; + + //Add all the tabs to the Master container. + MasterTabContainer.SetTabTitle(0, Loc.GetString("Main Menu")); + MasterTabContainer.AddChild(UplinkTabContainer); + MasterTabContainer.SetTabTitle(1, Loc.GetString("Uplink")); + Contents.AddChild(MasterTabContainer); + } + + private void PopulateUplinkCategoryButtons() + { + + foreach (UplinkCategory cat in Enum.GetValues(typeof (UplinkCategory))) + { + + var catButton = new PDAUplinkCategoryButton + { + Text = Loc.GetString(cat.ToString()), + ButtonCategory = cat + + }; + + catButton.OnPressed += args => OnCategoryButtonPressed?.Invoke(args, catButton.ButtonCategory); + + CategoryListContainer.AddChild(catButton); + } + + } + + public void AddListingGui(UplinkListingData listing) + { + if (!_prototypeManager.TryIndex(listing.ItemId, out EntityPrototype prototype) || listing.Category != CurrentFilterCategory) + { + return; + } + + var itemLabel = new Label + { + Text = listing.ListingName == string.Empty ? prototype.Name : listing.ListingName, + ToolTip = listing.Description == string.Empty ? prototype.Description : listing.Description, + SizeFlagsHorizontal = SizeFlags.FillExpand, + }; + + var priceLabel = new Label + { + Text = $"{listing.Price} TC", + Align = Label.AlignMode.Right, + }; + + + //Can the account afford this item? If so use the item's color, else gray it out. + var itemColor = _loggedInUplinkAccount.DataBalance >= listing.Price + ? listing.DisplayColor + : Color.Gray.WithAlpha(0.25f); + + //Contains the name of the item and its price. Used for spacing price and name. + var listingButtonHbox = new HBoxContainer + { + Modulate = itemColor, + Children = + { + itemLabel, + priceLabel + } + }; + + var listingButtonPanelContainer = new PanelContainer + { + Children = + { + listingButtonHbox + } + }; + + var pdaUplinkListingButton = new PDAUplinkItemButton + { + ButtonListing = listing, + SizeFlagsVertical = SizeFlags.Fill, + Children = + { + listingButtonPanelContainer + } + }; + pdaUplinkListingButton.OnPressed += args + => OnListingButtonPressed?.Invoke(args,pdaUplinkListingButton.ButtonListing); + UplinkListingsContainer.AddChild(pdaUplinkListingButton); + } + + + public void ClearListings() + { + UplinkListingsContainer.Children.Clear(); + } + + + private sealed class PDAUplinkItemButton : ContainerButton + { + public UplinkListingData ButtonListing; + } + + private sealed class PDAUplinkCategoryButton : Button + { + public UplinkCategory ButtonCategory; + + } + } + } +} diff --git a/Content.Client/GameObjects/Components/PDA/PDAComponent.cs b/Content.Client/GameObjects/Components/PDA/PDAComponent.cs new file mode 100644 index 0000000000..8118d7ee33 --- /dev/null +++ b/Content.Client/GameObjects/Components/PDA/PDAComponent.cs @@ -0,0 +1,11 @@ +using Content.Shared.GameObjects.Components.PDA; +using Robust.Shared.GameObjects; + +namespace Content.Client.GameObjects.Components.PDA +{ + [RegisterComponent] + public class PDAComponent : SharedPDAComponent + { + + } +} diff --git a/Content.Client/GameObjects/Components/PDA/PDAVisualizer.cs b/Content.Client/GameObjects/Components/PDA/PDAVisualizer.cs new file mode 100644 index 0000000000..019bd03ae1 --- /dev/null +++ b/Content.Client/GameObjects/Components/PDA/PDAVisualizer.cs @@ -0,0 +1,38 @@ +using Content.Shared.GameObjects.Components.PDA; +using Robust.Client.GameObjects; +using Robust.Client.Interfaces.GameObjects.Components; + +namespace Content.Client.GameObjects.Components.PDA +{ + public class PDAVisualizer : AppearanceVisualizer + { + + private enum PDAVisualLayers + { + Base, + Unlit + } + + + public override void OnChangeData(AppearanceComponent component) + { + base.OnChangeData(component); + if (component.Owner.Deleted) + { + return; + } + var sprite = component.Owner.GetComponent(); + sprite.LayerSetVisible(PDAVisualLayers.Unlit, false); + if(!component.TryGetData(PDAVisuals.ScreenLit, out var isScreenLit)) + { + return; + } + sprite.LayerSetState(PDAVisualLayers.Unlit, "unlit_pda_screen"); + sprite.LayerSetVisible(PDAVisualLayers.Unlit, isScreenLit); + + + } + + + } +} diff --git a/Content.Server/EntryPoint.cs b/Content.Server/EntryPoint.cs index 6add00daed..885405dc93 100644 --- a/Content.Server/EntryPoint.cs +++ b/Content.Server/EntryPoint.cs @@ -2,6 +2,7 @@ using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; +using Content.Server.Interfaces.PDA; using Content.Server.Preferences; using Content.Server.Sandbox; using Content.Shared.Kitchen; @@ -84,6 +85,7 @@ namespace Content.Server IoCManager.Resolve().Initialize(); IoCManager.Resolve().FinishInit(); IoCManager.Resolve().Initialize(); + IoCManager.Resolve().Initialize(); } public override void Update(ModUpdateLevel level, FrameEventArgs frameEventArgs) diff --git a/Content.Server/GameObjects/Components/Access/AccessComponent.cs b/Content.Server/GameObjects/Components/Access/AccessComponent.cs index fa122346b7..829f47ed0e 100644 --- a/Content.Server/GameObjects/Components/Access/AccessComponent.cs +++ b/Content.Server/GameObjects/Components/Access/AccessComponent.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Content.Server.Interfaces; using Robust.Shared.GameObjects; using Robust.Shared.Serialization; using Robust.Shared.ViewVariables; @@ -6,16 +7,26 @@ using Robust.Shared.ViewVariables; namespace Content.Server.GameObjects.Components.Access { [RegisterComponent] - public class AccessComponent : Component + [ComponentReference(typeof(IAccess))] + public class AccessComponent : Component, IAccess { public override string Name => "Access"; [ViewVariables] - public List Tags; + private List _tags; public override void ExposeData(ObjectSerializer serializer) { base.ExposeData(serializer); + serializer.DataField(ref _tags, "tags", new List()); + } - serializer.DataField(ref Tags, "tags", new List()); + public List GetTags() + { + return _tags; + } + + public void SetTags(List newTags) + { + _tags = newTags; } } } diff --git a/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs index 6eba78317f..8f1e89da30 100644 --- a/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs +++ b/Content.Server/GameObjects/Components/Access/AccessReaderComponent.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using Content.Server.Interfaces; using Content.Server.Interfaces.GameObjects; using Content.Shared.GameObjects.Components.Inventory; using JetBrains.Annotations; @@ -26,22 +28,22 @@ namespace Content.Server.GameObjects.Components.Access /// The entity to be searched for access. public bool IsAllowed(IEntity entity) { - var accessProvider = FindAccessProvider(entity); - return accessProvider != null && IsAllowed(accessProvider); + var tags = FindAccessTags(entity); + return tags != null && IsAllowed(tags); } - private bool IsAllowed(AccessComponent accessProvider) + private bool IsAllowed(List accessTags) { foreach (var sufficient in _sufficientTags) { - if (accessProvider.Tags.Contains(sufficient)) + if (accessTags.Contains(sufficient)) { return true; } } foreach (var necessary in _necessaryTags) { - if (!accessProvider.Tags.Contains(necessary)) + if (!accessTags.Contains(necessary)) { return false; } @@ -50,20 +52,20 @@ namespace Content.Server.GameObjects.Components.Access } [CanBeNull] - private static AccessComponent FindAccessProvider(IEntity entity) + private static List FindAccessTags(IEntity entity) { - if (entity.TryGetComponent(out AccessComponent accessComponent)) + if (entity.TryGetComponent(out IAccess accessComponent)) { - return accessComponent; + return accessComponent.GetTags(); } if (entity.TryGetComponent(out IHandsComponent handsComponent)) { var activeHandEntity = handsComponent.GetActiveHand?.Owner; if (activeHandEntity != null && - activeHandEntity.TryGetComponent(out AccessComponent handAccessComponent)) + activeHandEntity.TryGetComponent(out IAccess handAccessComponent)) { - return handAccessComponent; + return handAccessComponent.GetTags(); } } else @@ -74,10 +76,10 @@ namespace Content.Server.GameObjects.Components.Access { if (inventoryComponent.HasSlot(EquipmentSlotDefines.Slots.IDCARD) && inventoryComponent.TryGetSlotItem(EquipmentSlotDefines.Slots.IDCARD, out ItemComponent item) && - item.Owner.TryGetComponent(out AccessComponent idAccessComponent) + item.Owner.TryGetComponent(out IAccess idAccessComponent) ) { - return idAccessComponent; + return idAccessComponent.GetTags(); } } return null; diff --git a/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs b/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs index 12c7ac72ee..868c46a0db 100644 --- a/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs +++ b/Content.Server/GameObjects/Components/Access/IdCardConsoleComponent.cs @@ -101,7 +101,7 @@ namespace Content.Server.GameObjects.Components.Access return; } var targetIdAccess = targetIdEntity.GetComponent(); - targetIdAccess.Tags = newAccessList; + targetIdAccess.SetTags(newAccessList); } /// @@ -180,7 +180,7 @@ namespace Content.Server.GameObjects.Components.Access true, targetIdComponent.FullName, targetIdComponent.JobTitle, - targetAccessComponent.Tags, + targetAccessComponent.GetTags(), _privilegedIdContainer.ContainedEntity?.Name ?? "", _targetIdContainer.ContainedEntity?.Name ?? ""); } diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs new file mode 100644 index 0000000000..9fb8ead381 --- /dev/null +++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs @@ -0,0 +1,254 @@ +using System.Collections.Generic; +using System.Linq; +using Content.Server.GameObjects.Components.Access; +using Content.Server.GameObjects.EntitySystems; +using Content.Server.Interfaces; +using Content.Server.Interfaces.PDA; +using Content.Shared.GameObjects; +using Content.Shared.GameObjects.Components.PDA; +using JetBrains.Annotations; +using Robust.Server.GameObjects; +using Robust.Server.GameObjects.Components.Container; +using Robust.Server.GameObjects.Components.UserInterface; +using Robust.Server.Interfaces.GameObjects; +using Robust.Shared.GameObjects; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.Interfaces.Network; +using Robust.Shared.IoC; +using Robust.Shared.Localization; +using Robust.Shared.Players; +using Robust.Shared.Serialization; + +namespace Content.Server.GameObjects.Components.PDA +{ + [RegisterComponent] + [ComponentReference(typeof(IActivate))] + [ComponentReference(typeof(IAccess))] + public class PDAComponent : SharedPDAComponent, IInteractUsing, IActivate, IUse, IAccess + { +#pragma warning disable 649 + [Dependency] protected readonly IPDAUplinkManager _uplinkManager; + [Dependency] protected readonly IEntityManager _entityManager; +#pragma warning restore 649 + + private Container _idSlot; + private PointLightComponent _pdaLight; + private bool _lightOn = false; + private BoundUserInterface _interface; + private string _startingIdCard; + public bool IdSlotEmpty => _idSlot.ContainedEntities.Count < 1; + public IEntity OwnerMob { get; private set; } + + public IdCardComponent ContainedID { get; private set; } + + private AppearanceComponent _appearance; + + private UplinkAccount _syndicateUplinkAccount; + + public override void ExposeData(ObjectSerializer serializer) + { + base.ExposeData(serializer); + serializer.DataField(ref _startingIdCard, "idCard", "AssistantIDCard"); + } + + public override void Initialize() + { + base.Initialize(); + _idSlot = ContainerManagerComponent.Ensure("pda_entity_container", Owner, out var existed); + _pdaLight = Owner.GetComponent(); + _appearance = Owner.GetComponent(); + _interface = Owner.GetComponent() + .GetBoundUserInterface(PDAUiKey.Key); + _interface.OnReceiveMessage += UserInterfaceOnReceiveMessage; + var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.GridPosition); + var idCardComponent = idCard.GetComponent(); + InsertIdCard(idCardComponent); + UpdatePDAAppearance(); + } + + private void UserInterfaceOnReceiveMessage(ServerBoundUserInterfaceMessage message) + { + switch (message.Message) + { + case PDARequestUpdateInterfaceMessage msg: + { + UpdatePDAUserInterface(); + break; + } + case PDAToggleFlashlightMessage msg: + { + ToggleLight(); + break; + } + + case PDAEjectIDMessage msg: + { + HandleIDEjection(message.Session.AttachedEntity); + break; + } + + case PDAUplinkBuyListingMessage buyMsg: + { + + if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ListingToBuy)) + { + //TODO: Send a message that tells the buyer they are too poor or something. + } + + break; + } + } + } + + private void UpdatePDAUserInterface() + { + var ownerInfo = new PDAIdInfoText + { + ActualOwnerName = OwnerMob?.Name, + IdOwner = ContainedID?.FullName, + JobTitle = ContainedID?.JobTitle + }; + + //Do we have an account? If so provide the info. + if (_syndicateUplinkAccount != null) + { + var accData = new UplinkAccountData(_syndicateUplinkAccount.AccountHolder, _syndicateUplinkAccount.Balance); + var listings = _uplinkManager.FetchListings.ToArray(); + _interface.SetState(new PDAUpdateState(_lightOn,ownerInfo,accData,listings)); + } + else + { + _interface.SetState(new PDAUpdateState(_lightOn,ownerInfo)); + } + + UpdatePDAAppearance(); + } + + private void UpdatePDAAppearance() + { + _appearance?.SetData(PDAVisuals.ScreenLit, _lightOn); + } + + public bool InteractUsing(InteractUsingEventArgs eventArgs) + { + var item = eventArgs.Using; + if (!IdSlotEmpty) + { + return false; + } + + if (!item.TryGetComponent(out var idCardComponent) || _idSlot.Contains(item)) + { + return false; + } + InsertIdCard(idCardComponent); + UpdatePDAUserInterface(); + return true; + + } + + void IActivate.Activate(ActivateEventArgs eventArgs) + { + if (!eventArgs.User.TryGetComponent(out IActorComponent actor)) + { + return; + } + _interface.Open(actor.playerSession); + UpdatePDAAppearance(); + } + + public bool UseEntity(UseEntityEventArgs eventArgs) + { + if (!eventArgs.User.TryGetComponent(out IActorComponent actor)) + { + return false; + } + _interface.Open(actor.playerSession); + UpdatePDAAppearance(); + return true; + } + + public void SetPDAOwner(IEntity mob) + { + if (mob == OwnerMob) + { + return; + } + + OwnerMob = mob; + UpdatePDAUserInterface(); + } + + private void InsertIdCard(IdCardComponent card) + { + _idSlot.Insert(card.Owner); + ContainedID = card; + } + + /// + /// Initialize the PDA's syndicate uplink account. + /// + /// + public void InitUplinkAccount(UplinkAccount acc) + { + _syndicateUplinkAccount = acc; + _uplinkManager.AddNewAccount(_syndicateUplinkAccount); + + _syndicateUplinkAccount.BalanceChanged += account => + { + UpdatePDAUserInterface(); + }; + + UpdatePDAUserInterface(); + } + + private void ToggleLight() + { + _lightOn = !_lightOn; + _pdaLight.Enabled = _lightOn; + UpdatePDAUserInterface(); + } + + private void HandleIDEjection(IEntity pdaUser) + { + if (IdSlotEmpty) + { + return; + } + + var cardEntity = ContainedID.Owner; + _idSlot.Remove(cardEntity); + + var hands = pdaUser.GetComponent(); + var cardItemComponent = cardEntity.GetComponent(); + hands.PutInHandOrDrop(cardItemComponent); + ContainedID = null; + UpdatePDAUserInterface(); + } + + [Verb] + public sealed class EjectIDVerb : Verb + { + protected override void GetData(IEntity user, PDAComponent component, VerbData data) + { + data.Text = Loc.GetString("Eject ID"); + data.Visibility = component.IdSlotEmpty ? VerbVisibility.Invisible : VerbVisibility.Visible; + } + + protected override void Activate(IEntity user, PDAComponent component) + { + component.HandleIDEjection(user); + } + } + + List IAccess.GetTags() + { + return ContainedID?.Owner.GetComponent()?.GetTags(); + } + + void IAccess.SetTags(List newTags) + { + ContainedID?.Owner.GetComponent().SetTags(newTags); + } + } +} diff --git a/Content.Server/GameTicking/GameTicker.cs b/Content.Server/GameTicking/GameTicker.cs index 9f3b8cc536..796e2e5c0a 100644 --- a/Content.Server/GameTicking/GameTicker.cs +++ b/Content.Server/GameTicking/GameTicker.cs @@ -7,6 +7,7 @@ using Content.Server.GameObjects.Components.Access; using Content.Server.GameObjects.Components.Markers; using Content.Server.GameObjects.Components.Mobs; using Content.Server.GameObjects.Components.Observer; +using Content.Server.GameObjects.Components.PDA; using Content.Server.GameObjects.EntitySystems; using Content.Server.GameTicking.GamePresets; using Content.Server.Interfaces; @@ -17,6 +18,7 @@ using Content.Server.Mobs.Roles; using Content.Server.Players; using Content.Shared; using Content.Shared.Chat; +using Content.Shared.GameObjects.Components.PDA; using Content.Shared.Jobs; using Content.Shared.Preferences; using Robust.Server.Interfaces; @@ -627,20 +629,38 @@ namespace Content.Server.GameTicking { var inventory = mob.GetComponent(); - if (!inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent cardItem)) + if (!inventory.TryGetSlotItem(Slots.IDCARD, out ItemComponent pdaItem)) { return; } - var card = cardItem.Owner; + var pda = pdaItem.Owner; - var cardComponent = card.GetComponent(); - cardComponent.FullName = characterName; - cardComponent.JobTitle = jobPrototype.Name; + var pdaComponent = pda.GetComponent(); + if (pdaComponent.IdSlotEmpty) + { + return; + } + + var card = pdaComponent.ContainedID; + card.FullName = characterName; + card.JobTitle = jobPrototype.Name; + + var access = card.Owner.GetComponent(); + var accessTags = access.GetTags(); + accessTags.AddRange(jobPrototype.Access); + access.SetTags(accessTags); + pdaComponent.SetPDAOwner(mob); + var mindComponent = mob.GetComponent(); + if (mindComponent.HasMind)//Redundancy checks. + { + if (mindComponent.Mind.AllRoles.Any(role => role.Antag)) //Give antags a new uplinkaccount. + { + var uplinkAccount = new UplinkAccount(mob.Uid, 20); //TODO: make me into a variable based on server pop or something. + pdaComponent.InitUplinkAccount(uplinkAccount); + } + } - var access = card.GetComponent(); - access.Tags.Clear(); - access.Tags.AddRange(jobPrototype.Access); } private void AddManifestEntry(string characterName, string jobId) diff --git a/Content.Server/Interfaces/IAccess.cs b/Content.Server/Interfaces/IAccess.cs new file mode 100644 index 0000000000..1729f99d3f --- /dev/null +++ b/Content.Server/Interfaces/IAccess.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; + +namespace Content.Server.Interfaces +{ + public interface IAccess + { + public List GetTags(); + + public void SetTags(List newTags); + } +} diff --git a/Content.Server/Interfaces/PDA/IPDAUplinkManager.cs b/Content.Server/Interfaces/PDA/IPDAUplinkManager.cs new file mode 100644 index 0000000000..34bc3d3c71 --- /dev/null +++ b/Content.Server/Interfaces/PDA/IPDAUplinkManager.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using Content.Shared.GameObjects.Components.PDA; +using Content.Shared.Prototypes.PDA; + +namespace Content.Server.Interfaces.PDA +{ + public interface IPDAUplinkManager + { + public IReadOnlyList FetchListings => null; + void Initialize(); + public bool AddNewAccount(UplinkAccount acc); + + public bool ChangeBalance(UplinkAccount acc, int amt); + + public bool TryPurchaseItem(UplinkAccount acc, UplinkListingData listing); + + } +} diff --git a/Content.Server/PDA/PDAUplinkManager.cs b/Content.Server/PDA/PDAUplinkManager.cs new file mode 100644 index 0000000000..52c503ebea --- /dev/null +++ b/Content.Server/PDA/PDAUplinkManager.cs @@ -0,0 +1,107 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using Content.Server.GameObjects; +using Content.Server.GameObjects.Components.Mobs; +using Content.Server.Interfaces.PDA; +using Content.Shared.GameObjects.Components.PDA; +using Content.Shared.Prototypes.PDA; +using Robust.Shared.Interfaces.GameObjects; +using Robust.Shared.IoC; +using Robust.Shared.Prototypes; + +namespace Content.Server.PDA +{ + public class PDAUplinkManager : IPDAUplinkManager + { +#pragma warning disable 649 + [Dependency] private readonly IPrototypeManager _prototypeManager; + [Dependency] private readonly IEntityManager _entityManager; +#pragma warning restore 649 + + private List _accounts; + private List _listings; + + public IReadOnlyList FetchListings => _listings; + + public void Initialize() + { + _listings = new List(); + foreach (var item in _prototypeManager.EnumeratePrototypes()) + { + var newListing = new UplinkListingData(item.ListingName, item.ItemId, item.Price, item.Category, + item.Description, item.DisplayColor); + + RegisterUplinkListing(newListing); + } + + _accounts = new List(); + } + + private void RegisterUplinkListing(UplinkListingData listing) + { + if (!ContainsListing(listing)) + { + _listings.Add(listing); + } + + } + + private bool ContainsListing(UplinkListingData listing) + { + return _listings.Any(otherListing => listing.Equals(otherListing)); + } + + public bool AddNewAccount(UplinkAccount acc) + { + var entity = _entityManager.GetEntity(acc.AccountHolder); + if (entity.TryGetComponent(out MindComponent mindComponent)) + { + if (mindComponent.Mind.AllRoles.Any(role => !role.Antag)) + { + return false; + } + } + if (_accounts.Contains(acc)) + { + return false; + } + + _accounts.Add(acc); + return true; + } + + public bool ChangeBalance(UplinkAccount acc, int amt) + { + var account = _accounts.Find(uplinkAccount => uplinkAccount.AccountHolder == acc.AccountHolder); + if (account != null && account.Balance + amt < 0) + { + return false; + } + account.ModifyAccountBalance(account.Balance + amt); + return true; + } + + public bool TryPurchaseItem(UplinkAccount acc, UplinkListingData listing) + { + if (acc == null || listing == null) + { + return false; + } + if (!ContainsListing(listing) || acc.Balance < listing.Price) + { + return false; + } + + var player = _entityManager.GetEntity(acc.AccountHolder); + var hands = player.GetComponent(); + hands.PutInHandOrDrop(_entityManager.SpawnEntity(listing.ItemId, + player.Transform.GridPosition).GetComponent()); + return ChangeBalance(acc, -listing.Price); + + } + + + } +} diff --git a/Content.Server/ServerContentIoC.cs b/Content.Server/ServerContentIoC.cs index 7ca422e4c4..54b61d71c7 100644 --- a/Content.Server/ServerContentIoC.cs +++ b/Content.Server/ServerContentIoC.cs @@ -4,6 +4,8 @@ using Content.Server.GameTicking; using Content.Server.Interfaces; using Content.Server.Interfaces.Chat; using Content.Server.Interfaces.GameTicking; +using Content.Server.Interfaces.PDA; +using Content.Server.PDA; using Content.Server.Preferences; using Content.Server.Sandbox; using Content.Server.Utility; @@ -30,6 +32,7 @@ namespace Content.Server IoCManager.Register(); IoCManager.Register(); IoCManager.Register(); + IoCManager.Register(); } } } diff --git a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs new file mode 100644 index 0000000000..16515d3f9d --- /dev/null +++ b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs @@ -0,0 +1,184 @@ +using System; +using System.Collections.Generic; +using JetBrains.Annotations; +using Robust.Shared.GameObjects; +using Robust.Shared.GameObjects.Components.UserInterface; +using Robust.Shared.Maths; +using Robust.Shared.Serialization; + +namespace Content.Shared.GameObjects.Components.PDA +{ + public class SharedPDAComponent : Component + { + public override string Name => "PDA"; + public override uint? NetID => ContentNetIDs.PDA; + + } + + [Serializable, NetSerializable] + public sealed class PDAToggleFlashlightMessage : BoundUserInterfaceMessage + { + public PDAToggleFlashlightMessage() + { + + } + } + + [Serializable, NetSerializable] + public sealed class PDAEjectIDMessage : BoundUserInterfaceMessage + { + public PDAEjectIDMessage() + { + + } + } + + + [Serializable, NetSerializable] + public class PDAUBoundUserInterfaceState : BoundUserInterfaceState + { + + } + + [Serializable, NetSerializable] + public sealed class PDAUpdateState : PDAUBoundUserInterfaceState + { + public bool FlashlightEnabled; + public PDAIdInfoText PDAOwnerInfo; + public UplinkAccountData Account; + public UplinkListingData[] Listings; + + public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo) + { + FlashlightEnabled = isFlashlightOn; + PDAOwnerInfo = ownerInfo; + } + + public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData) + { + FlashlightEnabled = isFlashlightOn; + PDAOwnerInfo = ownerInfo; + Account = accountData; + } + + public PDAUpdateState(bool isFlashlightOn, PDAIdInfoText ownerInfo, UplinkAccountData accountData, UplinkListingData[] listings) + { + FlashlightEnabled = isFlashlightOn; + PDAOwnerInfo = ownerInfo; + Account = accountData; + Listings = listings; + } + } + + [Serializable, NetSerializable] + public sealed class PDAUplinkBuyListingMessage : BoundUserInterfaceMessage + { + public UplinkListingData ListingToBuy; + public PDAUplinkBuyListingMessage(UplinkListingData itemToBuy) + { + ListingToBuy = itemToBuy; + } + } + + [Serializable, NetSerializable] + public sealed class PDARequestUpdateInterfaceMessage : BoundUserInterfaceMessage + { + public PDARequestUpdateInterfaceMessage() + { + + } + } + + + [NetSerializable, Serializable] + public struct PDAIdInfoText + { + public string ActualOwnerName; + public string IdOwner; + public string JobTitle; + } + + [NetSerializable, Serializable] + public enum PDAVisuals + { + ScreenLit, + } + + [NetSerializable, Serializable] + public enum PDAUiKey + { + Key + } + + public class UplinkAccount + { + public event Action BalanceChanged; + public EntityUid AccountHolder; + public int Balance { get; private set; } + + public UplinkAccount(EntityUid uid, int startingBalance) + { + AccountHolder = uid; + Balance = startingBalance; + } + + public bool ModifyAccountBalance(int newBalance) + { + if (newBalance < 0) + { + return false; + } + Balance = newBalance; + BalanceChanged?.Invoke(this); + return true; + + } + } + + [NetSerializable, Serializable] + public class UplinkAccountData + { + public EntityUid DataAccountHolder; + public int DataBalance; + + public UplinkAccountData(EntityUid dataAccountHolder, int dataBalance) + { + DataAccountHolder = dataAccountHolder; + DataBalance = dataBalance; + } + } + + [NetSerializable, Serializable] + public class UplinkListingData : ComponentState, IEquatable + { + public string ItemId; + public int Price; + public UplinkCategory Category; + public string Description; + public string ListingName; + public Color DisplayColor; + + public UplinkListingData(string listingName,string itemId, + int price, UplinkCategory category, + string description, Color displayColor) : base(ContentNetIDs.PDA) + { + ListingName = listingName; + Price = price; + Category = category; + Description = description; + ItemId = itemId; + DisplayColor = displayColor; + } + + public bool Equals(UplinkListingData other) + { + if (other == null) + { + return false; + } + + return ItemId == other.ItemId; + } + } + +} diff --git a/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs new file mode 100644 index 0000000000..9dca94d517 --- /dev/null +++ b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs @@ -0,0 +1,8 @@ +namespace Content.Shared.GameObjects.Components.PDA +{ + public enum UplinkCategory + { + Weapon, + Utility, + } +} diff --git a/Content.Shared/GameObjects/ContentNetIDs.cs b/Content.Shared/GameObjects/ContentNetIDs.cs index d8a53eb727..9e5b7e71a5 100644 --- a/Content.Shared/GameObjects/ContentNetIDs.cs +++ b/Content.Shared/GameObjects/ContentNetIDs.cs @@ -46,5 +46,6 @@ public const uint GRAVITY_GENERATOR = 1041; public const uint SURGERY = 1042; public const uint MULTITOOLS = 1043; + public const uint PDA = 1044; } } diff --git a/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs b/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs new file mode 100644 index 0000000000..50f7097127 --- /dev/null +++ b/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs @@ -0,0 +1,42 @@ +using Content.Shared.GameObjects.Components.PDA; +using Robust.Shared.Maths; +using Robust.Shared.Prototypes; +using Robust.Shared.Serialization; +using YamlDotNet.RepresentationModel; + +namespace Content.Shared.Prototypes.PDA +{ + [Prototype("uplinkListing")] + public class UplinkStoreListingPrototype : IPrototype, IIndexedPrototype + { + + private string _id; + private string _itemId; + private int _price; + private UplinkCategory _category; + private string _desc; + private string _name; + private Color _displayColor; + + public string ID => _id; + + public string ItemId => _itemId; + public int Price => _price; + public UplinkCategory Category => _category; + public string Description => _desc; + public string ListingName => _name; + public Color DisplayColor => _displayColor; + public void LoadFrom(YamlMappingNode mapping) + { + var serializer = YamlObjectSerializer.NewReader(mapping); + serializer.DataField(ref _id, "id", string.Empty); + serializer.DataField(ref _itemId, "itemId", string.Empty); + serializer.DataField(ref _price, "price", 5); + serializer.DataField(ref _category, "category", UplinkCategory.Utility); + serializer.DataField(ref _desc, "description", string.Empty); + serializer.DataField(ref _name, "listingName", string.Empty); + serializer.DataField(ref _displayColor, "displayColor", Color.White); + + } + } +} diff --git a/Resources/Prototypes/Entities/Items/pda.yml b/Resources/Prototypes/Entities/Items/pda.yml new file mode 100644 index 0000000000..95a399130f --- /dev/null +++ b/Resources/Prototypes/Entities/Items/pda.yml @@ -0,0 +1,353 @@ +- type: entity + name: PDA + parent: BaseItem + id: BasePDA + abstract: true + description: Personal Data Assistant + components: + - type: Appearance + visuals: + - type: PDAVisualizer + - type: Clothing + QuickEquip: false + Slots: + - idcard + - type: PointLight + enabled: false + radius: 3 + - type: UserInterface + interfaces: + - key: enum.PDAUiKey.Key + type: PDABoundUserInterface + - type: Sound + + +- type: entity + name: Assistant PDA + parent: BasePDA + id: AssistantPDA + description: Why isn't it gray? + components: + - type: PDA + idCard: AssistantIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Chef PDA + parent: BasePDA + id: ChefPDA + description: Why isn't it gray? + components: + - type: PDA + idCard: ChefIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-chef + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-chef + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Clown PDA + parent: BasePDA + id: ClownPDA + description: Looks can be deceiving. + components: + - type: PDA + idCard: ClownIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-clown + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-clown + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Cargo PDA + parent: BasePDA + id: CargoPDA + description: PDA for the guys that order the pizzas. + components: + - type: PDA + idCard: CargoIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-cargo + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-cargo + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Bartender PDA + parent: BasePDA + id: BartenderPDA + description: Smells like beer. + components: + - type: PDA + idCard: BartenderIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-bar + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-bar + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + + +- type: entity + name: Janitor PDA + parent: BasePDA + id: JanitorPDA + description: Smells like bleach. + components: + - type: PDA + idCard: JanitorIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-j + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-j + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Captain PDA + parent: BasePDA + id: CaptainPDA + description: Surprisingly no different than your PDA. + components: + - type: PDA + idCard: CaptainIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-c + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-c + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: HoP PDA + parent: BasePDA + id: HoPPDA + components: + - type: PDA + idCard: HoPIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-hop + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-hop + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: CE PDA + parent: BasePDA + id: CEPDA + components: + - type: PDA + idCard: CEIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-ce + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-ce + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + + +- type: entity + name: Engineer PDA + parent: BasePDA + id: EngineerPDA + components: + - type: PDA + idCard: EngineeringIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-e + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-e + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: CMO PDA + parent: BasePDA + id: CMOPDA + components: + - type: PDA + idCard: CMOIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-cmo + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-cmo + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + + +- type: entity + name: Medical PDA + parent: BasePDA + id: MedicalPDA + components: + - type: PDA + idCard: MedicalIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-m + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-m + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: RnD PDA + parent: BasePDA + id: RnDPDA + components: + - type: PDA + idCard: RDIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-rd + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-rd + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Science PDA + parent: BasePDA + id: SciencePDA + components: + - type: PDA + idCard: ResearchIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-rd + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-rd + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: HoS PDA + parent: BasePDA + id: HoSPDA + components: + - type: PDA + idCard: HoSIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-hos + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-hos + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] + +- type: entity + name: Security PDA + parent: BasePDA + id: SecurityPDA + components: + - type: PDA + idCard: SecurityIDCard + - type: Icon + sprite: Objects/Devices/pda.rsi + state: pda-s + - type: Sprite + sprite: Objects/Devices/pda.rsi + netsync: false + layers: + - state: pda-s + map: ["enum.PDAVisualLayers.Base"] + - state: unlit_pda_screen + shader: unshaded + map: ["enum.PDAVisualLayers.Unlit"] diff --git a/Resources/Prototypes/Jobs/Cargo/CargoTechnician.yml b/Resources/Prototypes/Jobs/Cargo/CargoTechnician.yml index c26ab2d0f5..c74fb14d65 100644 --- a/Resources/Prototypes/Jobs/Cargo/CargoTechnician.yml +++ b/Resources/Prototypes/Jobs/Cargo/CargoTechnician.yml @@ -17,4 +17,4 @@ innerclothing: UniformCargoTech backpack: BackpackClothing shoes: ShoesBlack - idcard: CargoIDCard + idcard: CargoPDA diff --git a/Resources/Prototypes/Jobs/Civilian/Assistant.yml b/Resources/Prototypes/Jobs/Civilian/Assistant.yml index 9e64c1a098..c3b355fa28 100644 --- a/Resources/Prototypes/Jobs/Civilian/Assistant.yml +++ b/Resources/Prototypes/Jobs/Civilian/Assistant.yml @@ -16,5 +16,5 @@ innerclothing: UniformColorGrey backpack: BackpackClothing shoes: ShoesBlack - idcard: AssistantIDCard + idcard: AssistantPDA diff --git a/Resources/Prototypes/Jobs/Civilian/Bartender.yml b/Resources/Prototypes/Jobs/Civilian/Bartender.yml index f71f705a3c..05d3ca32e8 100644 --- a/Resources/Prototypes/Jobs/Civilian/Bartender.yml +++ b/Resources/Prototypes/Jobs/Civilian/Bartender.yml @@ -16,4 +16,4 @@ outerclothing: OuterclothingArmorVest backpack: BackpackClothing shoes: ShoesBlack - idcard: BartenderIDCard + idcard: BartenderPDA diff --git a/Resources/Prototypes/Jobs/Civilian/Chef.yml b/Resources/Prototypes/Jobs/Civilian/Chef.yml index 81bbab1123..649f66e0e1 100644 --- a/Resources/Prototypes/Jobs/Civilian/Chef.yml +++ b/Resources/Prototypes/Jobs/Civilian/Chef.yml @@ -16,4 +16,4 @@ innerclothing: UniformChef backpack: BackpackClothing shoes: ShoesBlack - idcard: ChefIDCard + idcard: ChefPDA diff --git a/Resources/Prototypes/Jobs/Civilian/Clown.yml b/Resources/Prototypes/Jobs/Civilian/Clown.yml index 506a728cda..79de53d5ad 100644 --- a/Resources/Prototypes/Jobs/Civilian/Clown.yml +++ b/Resources/Prototypes/Jobs/Civilian/Clown.yml @@ -18,4 +18,4 @@ shoes: ShoesClown mask: MaskClown pocket1: BikeHorn - idcard: ClownIDCard + idcard: ClownPDA diff --git a/Resources/Prototypes/Jobs/Civilian/Janitor.yml b/Resources/Prototypes/Jobs/Civilian/Janitor.yml index 2cc0156944..a6842cc5d6 100644 --- a/Resources/Prototypes/Jobs/Civilian/Janitor.yml +++ b/Resources/Prototypes/Jobs/Civilian/Janitor.yml @@ -17,4 +17,4 @@ backpack: BackpackClothing shoes: ShoesGaloshes head: HatPurplesoft - idcard: JanitorIDCard + idcard: JanitorPDA diff --git a/Resources/Prototypes/Jobs/Command/Captain.yml b/Resources/Prototypes/Jobs/Command/Captain.yml index e100b0d27c..6127f0879c 100644 --- a/Resources/Prototypes/Jobs/Command/Captain.yml +++ b/Resources/Prototypes/Jobs/Command/Captain.yml @@ -32,4 +32,4 @@ eyes: SunGlasses gloves: GlovesCaptain outerclothing: OuterclothingCaparmor - idcard: CaptainIDCard + idcard: CaptainPDA diff --git a/Resources/Prototypes/Jobs/Command/HeadOfPersonnel.yml b/Resources/Prototypes/Jobs/Command/HeadOfPersonnel.yml index 9eb839edf5..15b4379af7 100644 --- a/Resources/Prototypes/Jobs/Command/HeadOfPersonnel.yml +++ b/Resources/Prototypes/Jobs/Command/HeadOfPersonnel.yml @@ -24,4 +24,4 @@ backpack: BackpackClothing shoes: ShoesBrown head: HatHopcap - idcard: HoPIDCard + idcard: HoPPDA diff --git a/Resources/Prototypes/Jobs/Engineering/ChiefEngineer.yml b/Resources/Prototypes/Jobs/Engineering/ChiefEngineer.yml index 4545866751..b9df28c533 100644 --- a/Resources/Prototypes/Jobs/Engineering/ChiefEngineer.yml +++ b/Resources/Prototypes/Jobs/Engineering/ChiefEngineer.yml @@ -21,4 +21,4 @@ innerclothing: UniformChiefEngineer backpack: BackpackEngineering shoes: ShoesBrown - idcard: CEIDCard + idcard: CEPDA diff --git a/Resources/Prototypes/Jobs/Engineering/StationEngineer.yml b/Resources/Prototypes/Jobs/Engineering/StationEngineer.yml index 1d217dc8d1..f3bcae49a3 100644 --- a/Resources/Prototypes/Jobs/Engineering/StationEngineer.yml +++ b/Resources/Prototypes/Jobs/Engineering/StationEngineer.yml @@ -19,4 +19,4 @@ backpack: BackpackEngineering shoes: ShoesWorkboots outerclothing: OuterclothingHazard - idcard: EngineeringIDCard + idcard: EngineerPDA diff --git a/Resources/Prototypes/Jobs/Medical/ChiefMedicalOfficer.yml b/Resources/Prototypes/Jobs/Medical/ChiefMedicalOfficer.yml index f1bbdfc3c4..7d80df9ead 100644 --- a/Resources/Prototypes/Jobs/Medical/ChiefMedicalOfficer.yml +++ b/Resources/Prototypes/Jobs/Medical/ChiefMedicalOfficer.yml @@ -22,4 +22,4 @@ backpack: BackpackMedical shoes: ShoesBrown outerclothing: OuterclothingLabcoatcmo - idcard: CMOIDCard + idcard: CMOPDA diff --git a/Resources/Prototypes/Jobs/Medical/MedicalDoctor.yml b/Resources/Prototypes/Jobs/Medical/MedicalDoctor.yml index 411b2cc1e3..b2747a76e3 100644 --- a/Resources/Prototypes/Jobs/Medical/MedicalDoctor.yml +++ b/Resources/Prototypes/Jobs/Medical/MedicalDoctor.yml @@ -17,4 +17,4 @@ backpack: BackpackMedical shoes: ShoesWhite outerclothing: OuterclothingLabcoatmedspecopen - idcard: MedicalIDCard + idcard: MedicalPDA diff --git a/Resources/Prototypes/Jobs/Science/ResearchDirector.yml b/Resources/Prototypes/Jobs/Science/ResearchDirector.yml index 886733d28e..a54a646b46 100644 --- a/Resources/Prototypes/Jobs/Science/ResearchDirector.yml +++ b/Resources/Prototypes/Jobs/Science/ResearchDirector.yml @@ -20,4 +20,4 @@ backpack: BackpackClothing shoes: ShoesBrown outerclothing: OuterclothingLabcoatgenopen - idcard: RDIDCard + idcard: RnDPDA diff --git a/Resources/Prototypes/Jobs/Science/Scientist.yml b/Resources/Prototypes/Jobs/Science/Scientist.yml index 686aeb9acf..0c97f5e039 100644 --- a/Resources/Prototypes/Jobs/Science/Scientist.yml +++ b/Resources/Prototypes/Jobs/Science/Scientist.yml @@ -17,4 +17,4 @@ backpack: BackpackClothing shoes: ShoesWhite outerclothing: OuterclothingLabcoattoxopen - idcard: ResearchIDCard + idcard: SciencePDA diff --git a/Resources/Prototypes/Jobs/Security/HeadOfSecurity.yml b/Resources/Prototypes/Jobs/Security/HeadOfSecurity.yml index 8d88c1bd0b..96460d5899 100644 --- a/Resources/Prototypes/Jobs/Security/HeadOfSecurity.yml +++ b/Resources/Prototypes/Jobs/Security/HeadOfSecurity.yml @@ -23,4 +23,4 @@ outerclothing: OuterclothingHoSTrenchcoat eyes: SecGlasses head: HatBeretHoS - idcard: HoSIDCard + idcard: HoSPDA diff --git a/Resources/Prototypes/Jobs/Security/SecurityOfficer.yml b/Resources/Prototypes/Jobs/Security/SecurityOfficer.yml index a9c5fd43e4..20b1ca1d9b 100644 --- a/Resources/Prototypes/Jobs/Security/SecurityOfficer.yml +++ b/Resources/Prototypes/Jobs/Security/SecurityOfficer.yml @@ -20,4 +20,4 @@ shoes: ShoesJackboots eyes: SecGlasses outerclothing: OuterclothingArmorVestAlt - idcard: SecurityIDCard + idcard: SecurityPDA diff --git a/Resources/Prototypes/PDA/uplink_catalog.yml b/Resources/Prototypes/PDA/uplink_catalog.yml new file mode 100644 index 0000000000..11cced4cef --- /dev/null +++ b/Resources/Prototypes/PDA/uplink_catalog.yml @@ -0,0 +1,29 @@ + +- type: uplinkListing + id: UplinkPen + category: Utility + itemId: Pen + price: 2 + displayColor: Blue + +- type: uplinkListing + id: UplinkPistolClarissa + category: Weapon + itemId: PistolClarissa + price: 15 + displayColor: Yellow + +# - type: uplinkListing +# id: UplinkPistolDeagle +# category: Weapon +# itemId: PistolDeagle +# price: 30 +# displayColor: Red + +# - type: uplinkListing +# id: UplinkMagazineFedShotgun +# category: Weapon +# itemId: MagazineFedShotgun +# price: 50 +# description: For when you want ZERO evidence left behind. +# displayColor: Red diff --git a/Resources/Textures/Objects/Devices/pda.rsi/aicard-404.png b/Resources/Textures/Objects/Devices/pda.rsi/aicard-404.png new file mode 100644 index 0000000000..645d236997 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/aicard-404.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/aicard-full.png b/Resources/Textures/Objects/Devices/pda.rsi/aicard-full.png new file mode 100644 index 0000000000..4786cc0faa Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/aicard-full.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/aicard-on.png b/Resources/Textures/Objects/Devices/pda.rsi/aicard-on.png new file mode 100644 index 0000000000..d668f51bb1 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/aicard-on.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/aicard.png b/Resources/Textures/Objects/Devices/pda.rsi/aicard.png new file mode 100644 index 0000000000..22b37682ae Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/aicard.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-a.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-a.png new file mode 100644 index 0000000000..c3c65c95e8 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-a.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-b.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-b.png new file mode 100644 index 0000000000..88d44bea5b Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-b.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-c.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-c.png new file mode 100644 index 0000000000..ae4007833e Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-c.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-ce.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-ce.png new file mode 100644 index 0000000000..be85201701 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-ce.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-chem.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-chem.png new file mode 100644 index 0000000000..02e52db37c Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-chem.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-clown.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-clown.png new file mode 100644 index 0000000000..45e2da7aff Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-clown.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-cmo.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-cmo.png new file mode 100644 index 0000000000..e1521813e3 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-cmo.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-e.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-e.png new file mode 100644 index 0000000000..8ea96d8b26 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-e.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-eye.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-eye.png new file mode 100644 index 0000000000..209e6ae0a2 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-eye.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-h.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-h.png new file mode 100644 index 0000000000..8ec45a4908 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-h.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-hos.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-hos.png new file mode 100644 index 0000000000..9daffbecaa Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-hos.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-j.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-j.png new file mode 100644 index 0000000000..b66e333d13 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-j.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-lib.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-lib.png new file mode 100644 index 0000000000..6ba64526da Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-lib.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-m.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-m.png new file mode 100644 index 0000000000..1420c062fb Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-m.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-mi.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-mi.png new file mode 100644 index 0000000000..04b1dc1ec7 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-mi.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-q.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-q.png new file mode 100644 index 0000000000..2f55aecdd5 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-q.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-rd.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-rd.png new file mode 100644 index 0000000000..15966051e1 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-rd.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-s.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-s.png new file mode 100644 index 0000000000..ca192b4f95 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-s.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-tear.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-tear.png new file mode 100644 index 0000000000..783762ea10 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-tear.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart-tox.png b/Resources/Textures/Objects/Devices/pda.rsi/cart-tox.png new file mode 100644 index 0000000000..23f4f49f45 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart-tox.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/cart.png b/Resources/Textures/Objects/Devices/pda.rsi/cart.png new file mode 100644 index 0000000000..b9e61ec5bf Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/cart.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/crap.png b/Resources/Textures/Objects/Devices/pda.rsi/crap.png new file mode 100644 index 0000000000..d5d805f8a8 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/crap.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/meta.json b/Resources/Textures/Objects/Devices/pda.rsi/meta.json new file mode 100644 index 0000000000..d1c3e6d61a --- /dev/null +++ b/Resources/Textures/Objects/Devices/pda.rsi/meta.json @@ -0,0 +1 @@ +{"version":1,"size":{"x":32,"y":32},"states":[{"name":"aicard","directions":1,"delays":[[1]]},{"name":"aicard-404","directions":1,"delays":[[1]]},{"name":"aicard-full","directions":1,"delays":[[1]]},{"name":"aicard-on","directions":1,"delays":[[1]]},{"name":"cart","directions":1,"delays":[[1]]},{"name":"cart-a","directions":1,"delays":[[1]]},{"name":"cart-b","directions":1,"delays":[[1]]},{"name":"cart-c","directions":1,"delays":[[1]]},{"name":"cart-ce","directions":1,"delays":[[1]]},{"name":"cart-chem","directions":1,"delays":[[1]]},{"name":"cart-clown","directions":1,"delays":[[1]]},{"name":"cart-cmo","directions":1,"delays":[[1]]},{"name":"cart-e","directions":1,"delays":[[1]]},{"name":"cart-eye","directions":1,"delays":[[1]]},{"name":"cart-h","directions":1,"delays":[[1]]},{"name":"cart-hos","directions":1,"delays":[[1]]},{"name":"cart-j","directions":1,"delays":[[1]]},{"name":"cart-lib","directions":1,"delays":[[1]]},{"name":"cart-m","directions":1,"delays":[[1]]},{"name":"cart-mi","directions":1,"delays":[[1]]},{"name":"cart-q","directions":1,"delays":[[1]]},{"name":"cart-rd","directions":1,"delays":[[1]]},{"name":"cart-s","directions":1,"delays":[[1]]},{"name":"cart-tear","directions":1,"delays":[[1]]},{"name":"cart-tox","directions":1,"delays":[[1]]},{"name":"crap","directions":1,"delays":[[1]]},{"name":"morecrap","directions":1,"delays":[[1]]},{"name":"pai","directions":1,"delays":[[1]]},{"name":"pai-angry","directions":1,"delays":[[0.1,0.1,0.1,0.1]]},{"name":"pai-cat","directions":1,"delays":[[1,0.1,0.1,10]]},{"name":"pai-exclamation","directions":1,"delays":[[1,0.5,1,0.5]]},{"name":"pai-extremely-happy","directions":1,"delays":[[1,0.1,5]]},{"name":"pai-face","directions":1,"delays":[[5,0.1,0.1,10]]},{"name":"pai-happy","directions":1,"delays":[[1,0.1,0.1,10]]},{"name":"pai-laugh","directions":1,"delays":[[0.1,0.1,0.1]]},{"name":"pai-neutral","directions":1,"delays":[[5,0.1,0.1,0.1,4,0.1]]},{"name":"pai-nose","directions":1,"delays":[[1]]},{"name":"pai-off","directions":1,"delays":[[1]]},{"name":"pai-question","directions":1,"delays":[[1,0.5,1,0.5]]},{"name":"pai-sad","directions":1,"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":"pai-silly","directions":1,"delays":[[5,0.1,0.1,0.1,0.1,0.1,0.5,0.1]]},{"name":"pai-smirk","directions":1,"delays":[[2,0.5,0.5,0.5,0.5,0.5,0.5,5]]},{"name":"pai-what","directions":1,"delays":[[2,0.1,0.1,5]]},{"name":"pda","directions":1,"delays":[[1]]},{"name":"unlit_pda_screen","directions":1,"delays":[[1]]},{"name":"pda-atmo","directions":1,"delays":[[1]]},{"name":"pda-bar","directions":1,"delays":[[1]]},{"name":"pda-c","directions":1,"delays":[[1]]},{"name":"pda-cargo","directions":1,"delays":[[1]]},{"name":"pda-ce","directions":1,"delays":[[1]]},{"name":"pda-chef","directions":1,"delays":[[1]]},{"name":"pda-chem","directions":1,"delays":[[1]]},{"name":"pda-clown","directions":1,"delays":[[1]]},{"name":"pda-cmo","directions":1,"delays":[[1]]},{"name":"pda-det","directions":1,"delays":[[1]]},{"name":"pda-e","directions":1,"delays":[[1]]},{"name":"pda-h","directions":1,"delays":[[1]]},{"name":"pda-holy","directions":1,"delays":[[1]]},{"name":"pda-hop","directions":1,"delays":[[1]]},{"name":"pda-hos","directions":1,"delays":[[1]]},{"name":"pda-hydro","directions":1,"delays":[[1]]},{"name":"pda-j","directions":1,"delays":[[1]]},{"name":"pda-lawyer","directions":1,"delays":[[1]]},{"name":"pda-lawyer-old","directions":1,"delays":[[1]]},{"name":"pda-libb","directions":1,"delays":[[1]]},{"name":"pda-libc","directions":1,"delays":[[0.1,0.1,0.1,0.1]]},{"name":"pda-m","directions":1,"delays":[[1]]},{"name":"pda-mime","directions":1,"delays":[[1]]},{"name":"pda-miner","directions":1,"delays":[[1]]},{"name":"pda-q","directions":1,"delays":[[1]]},{"name":"pda-r","directions":1,"delays":[[0.8,0.8]]},{"name":"pda-rd","directions":1,"delays":[[1]]},{"name":"pda-robot","directions":1,"delays":[[1]]},{"name":"pda-s","directions":1,"delays":[[1]]},{"name":"pda-syn","directions":1,"delays":[[1]]},{"name":"pda-tox","directions":1,"delays":[[1]]},{"name":"pda-transp","directions":1,"delays":[[1]]},{"name":"pda-v","directions":1,"delays":[[1]]},{"name":"pda-warden","directions":1,"delays":[[1]]},{"name":"pda_pen","directions":1,"delays":[[1]]},{"name":"pdabox","directions":1,"delays":[[1]]}]} diff --git a/Resources/Textures/Objects/Devices/pda.rsi/morecrap.png b/Resources/Textures/Objects/Devices/pda.rsi/morecrap.png new file mode 100644 index 0000000000..24097c2edf Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/morecrap.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-angry.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-angry.png new file mode 100644 index 0000000000..6d3f5d0115 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-angry.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-cat.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-cat.png new file mode 100644 index 0000000000..a25e96f19d Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-cat.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-exclamation.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-exclamation.png new file mode 100644 index 0000000000..52a088b311 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-exclamation.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-extremely-happy.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-extremely-happy.png new file mode 100644 index 0000000000..321b46c412 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-extremely-happy.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-face.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-face.png new file mode 100644 index 0000000000..523077242f Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-face.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-happy.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-happy.png new file mode 100644 index 0000000000..eff72f0d91 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-happy.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-laugh.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-laugh.png new file mode 100644 index 0000000000..7f70903253 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-laugh.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-neutral.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-neutral.png new file mode 100644 index 0000000000..3049248fd6 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-neutral.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-nose.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-nose.png new file mode 100644 index 0000000000..7325e5afa1 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-nose.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-off.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-off.png new file mode 100644 index 0000000000..7f3a7ec1a6 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-off.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-question.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-question.png new file mode 100644 index 0000000000..32d1bf2aeb Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-question.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-sad.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-sad.png new file mode 100644 index 0000000000..1f040034b1 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-sad.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-silly.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-silly.png new file mode 100644 index 0000000000..cf0279e88c Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-silly.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-smirk.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-smirk.png new file mode 100644 index 0000000000..a6efa390da Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-smirk.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai-what.png b/Resources/Textures/Objects/Devices/pda.rsi/pai-what.png new file mode 100644 index 0000000000..d306828f7c Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai-what.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pai.png b/Resources/Textures/Objects/Devices/pda.rsi/pai.png new file mode 100644 index 0000000000..78845a991a Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pai.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-atmo.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-atmo.png new file mode 100644 index 0000000000..b3977d4b42 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-atmo.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-bar.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-bar.png new file mode 100644 index 0000000000..8b6942ceef Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-bar.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-c.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-c.png new file mode 100644 index 0000000000..67dd678967 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-c.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-cargo.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-cargo.png new file mode 100644 index 0000000000..f43bcb2481 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-cargo.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-ce.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-ce.png new file mode 100644 index 0000000000..9ed242f17d Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-ce.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-chef.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-chef.png new file mode 100644 index 0000000000..00e98af427 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-chef.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-chem.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-chem.png new file mode 100644 index 0000000000..1bafc8f3d0 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-chem.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-clown.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-clown.png new file mode 100644 index 0000000000..7f31664a00 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-clown.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-cmo.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-cmo.png new file mode 100644 index 0000000000..d22662c5b3 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-cmo.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-det.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-det.png new file mode 100644 index 0000000000..e93ec473b4 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-det.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-e.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-e.png new file mode 100644 index 0000000000..d2caa6827e Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-e.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-h.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-h.png new file mode 100644 index 0000000000..39b498c96d Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-h.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-holy.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-holy.png new file mode 100644 index 0000000000..bb433abdfe Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-holy.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-hop.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-hop.png new file mode 100644 index 0000000000..040704ca53 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-hop.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-hos.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-hos.png new file mode 100644 index 0000000000..1346ac1d2c Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-hos.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-hydro.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-hydro.png new file mode 100644 index 0000000000..1cca5cea17 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-hydro.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-j.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-j.png new file mode 100644 index 0000000000..5091e9fa04 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-j.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer-old.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer-old.png new file mode 100644 index 0000000000..4fe3013540 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer-old.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer.png new file mode 100644 index 0000000000..6f9496648d Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-lawyer.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-libb.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-libb.png new file mode 100644 index 0000000000..579c665884 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-libb.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-libc.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-libc.png new file mode 100644 index 0000000000..054b0a39f4 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-libc.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-m.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-m.png new file mode 100644 index 0000000000..3adb51ab57 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-m.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-mime.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-mime.png new file mode 100644 index 0000000000..3a97e0650c Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-mime.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-miner.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-miner.png new file mode 100644 index 0000000000..42734a457d Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-miner.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-q.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-q.png new file mode 100644 index 0000000000..d90ee0c144 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-q.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-r.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-r.png new file mode 100644 index 0000000000..8382078b26 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-r.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-rd.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-rd.png new file mode 100644 index 0000000000..99669734b1 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-rd.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-robot.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-robot.png new file mode 100644 index 0000000000..1923f8ee03 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-robot.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-s.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-s.png new file mode 100644 index 0000000000..005e75870e Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-s.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-syn.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-syn.png new file mode 100644 index 0000000000..cf21c285e7 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-syn.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-tox.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-tox.png new file mode 100644 index 0000000000..1425d9e5ae Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-tox.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-transp.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-transp.png new file mode 100644 index 0000000000..e140da7f04 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-transp.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-v.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-v.png new file mode 100644 index 0000000000..b5c169dde3 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-v.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda-warden.png b/Resources/Textures/Objects/Devices/pda.rsi/pda-warden.png new file mode 100644 index 0000000000..a6ec69de0f Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda-warden.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda.png b/Resources/Textures/Objects/Devices/pda.rsi/pda.png new file mode 100644 index 0000000000..0f0abfbe1e Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pda_pen.png b/Resources/Textures/Objects/Devices/pda.rsi/pda_pen.png new file mode 100644 index 0000000000..324a706220 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pda_pen.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/pdabox.png b/Resources/Textures/Objects/Devices/pda.rsi/pdabox.png new file mode 100644 index 0000000000..4f5012c896 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/pdabox.png differ diff --git a/Resources/Textures/Objects/Devices/pda.rsi/unlit_pda_screen.png b/Resources/Textures/Objects/Devices/pda.rsi/unlit_pda_screen.png new file mode 100644 index 0000000000..93e998e3c7 Binary files /dev/null and b/Resources/Textures/Objects/Devices/pda.rsi/unlit_pda_screen.png differ