diff --git a/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs b/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs index 7e7ca63fd1..5be4d5a2e2 100644 --- a/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs +++ b/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs @@ -1,4 +1,3 @@ -using System; using Content.Client.Message; using Content.Shared.PDA; using Content.Shared.Traitor.Uplink; @@ -9,8 +8,6 @@ using Robust.Client.UserInterface.Controls; using Robust.Client.UserInterface.CustomControls; using Robust.Client.UserInterface.XAML; using Robust.Client.Utility; -using Robust.Shared.IoC; -using Robust.Shared.Localization; using Robust.Shared.Prototypes; namespace Content.Client.Traitor.Uplink diff --git a/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs b/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs index 1e3ac3a9fe..509d727fc8 100644 --- a/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs +++ b/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs @@ -1,8 +1,10 @@ using System.Diagnostics.CodeAnalysis; using System.Linq; +using Content.Server.Traitor.Uplink.Components; using Content.Shared.Stacks; using Content.Shared.Traitor.Uplink; using Robust.Shared.Map; +using Robust.Shared.Prototypes; namespace Content.Server.Traitor.Uplink.Account { @@ -68,10 +70,14 @@ namespace Content.Server.Traitor.Uplink.Account } - public bool TryPurchaseItem(UplinkAccount acc, string itemId, EntityCoordinates spawnCoords, [NotNullWhen(true)] out EntityUid? purchasedItem) + public bool TryPurchaseItem(UplinkComponent component, string itemId, EntityCoordinates spawnCoords, [NotNullWhen(true)] out EntityUid? purchasedItem) { + var acc = component.UplinkAccount; purchasedItem = null; + if (acc == null) return false; + if (acc.AccountHolder == null) return false; + if (!_listingSystem.TryGetListing(itemId, out var listing)) { return false; diff --git a/Content.Server/Traitor/Uplink/UplinkComponent.cs b/Content.Server/Traitor/Uplink/UplinkComponent.cs index 5415500bc8..68e6e68285 100644 --- a/Content.Server/Traitor/Uplink/UplinkComponent.cs +++ b/Content.Server/Traitor/Uplink/UplinkComponent.cs @@ -1,5 +1,7 @@ +using Content.Shared.Roles; using Content.Shared.Sound; using Content.Shared.Traitor.Uplink; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; namespace Content.Server.Traitor.Uplink.Components { @@ -22,6 +24,9 @@ namespace Content.Server.Traitor.Uplink.Components [ViewVariables] public UplinkAccount? UplinkAccount; + [ViewVariables, DataField("jobWhiteList", customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + public HashSet? JobWhitelist = null; + [Serializable] [DataDefinition] public sealed class PresetUplinkInfo diff --git a/Content.Server/Traitor/Uplink/UplinkListingSytem.cs b/Content.Server/Traitor/Uplink/UplinkListingSytem.cs index 968f57ecbf..67458ad5f8 100644 --- a/Content.Server/Traitor/Uplink/UplinkListingSytem.cs +++ b/Content.Server/Traitor/Uplink/UplinkListingSytem.cs @@ -21,7 +21,7 @@ namespace Content.Server.Traitor.Uplink foreach (var item in _prototypeManager.EnumeratePrototypes()) { var newListing = new UplinkListingData(item.ListingName, item.ItemId, - item.Price, item.Category, item.Description, item.Icon); + item.Price, item.Category, item.Description, item.Icon, item.JobWhitelist); RegisterUplinkListing(newListing); } diff --git a/Content.Server/Traitor/Uplink/UplinkSystem.cs b/Content.Server/Traitor/Uplink/UplinkSystem.cs index f5394fb9bf..3482002eb6 100644 --- a/Content.Server/Traitor/Uplink/UplinkSystem.cs +++ b/Content.Server/Traitor/Uplink/UplinkSystem.cs @@ -1,4 +1,6 @@ using System.Linq; +using Content.Server.Mind.Components; +using Content.Server.Roles; using Content.Server.Traitor.Uplink.Account; using Content.Server.Traitor.Uplink.Components; using Content.Server.UserInterface; @@ -106,10 +108,10 @@ namespace Content.Server.Traitor.Uplink private void OnBuy(EntityUid uid, UplinkComponent uplink, UplinkBuyListingMessage message) { - if (message.Session.AttachedEntity is not {Valid: true} player) return; + if (message.Session.AttachedEntity is not { Valid: true } player) return; if (uplink.UplinkAccount == null) return; - if (!_accounts.TryPurchaseItem(uplink.UplinkAccount, message.ItemId, + if (!_accounts.TryPurchaseItem(uplink, message.ItemId, EntityManager.GetComponent(player).Coordinates, out var entity)) { SoundSystem.Play(uplink.InsufficientFundsSound.GetSound(), @@ -132,7 +134,7 @@ namespace Content.Server.Traitor.Uplink if (acc == null) return; - if (args.Session.AttachedEntity is not {Valid: true} player) return; + if (args.Session.AttachedEntity is not { Valid: true } player) return; var cords = EntityManager.GetComponent(player).Coordinates; // try to withdraw TCs from account @@ -163,16 +165,60 @@ namespace Content.Server.Traitor.Uplink if (ui == null) return; - var listings = _listing.GetListings().Values.ToArray(); + var listings = _listing.GetListings().Values.ToList(); var acc = component.UplinkAccount; UplinkAccountData accData; if (acc != null) - accData = new UplinkAccountData(acc.AccountHolder, acc.Balance); - else - accData = new UplinkAccountData(null, 0); + { + // if we don't have a jobwhitelist stored, get a new one + if (component.JobWhitelist == null && + acc.AccountHolder != null && + TryComp(acc.AccountHolder, out var mind) && + mind.Mind != null) + { + HashSet? jobList = new(); + foreach (var role in mind.Mind.AllRoles.ToList()) + { + if (role.GetType() == typeof(Job)) + { + var job = (Job) role; + jobList.Add(job.Prototype.ID); + } + } + component.JobWhitelist = jobList; + } - ui.SetState(new UplinkUpdateState(accData, listings)); + // filter out items not on the whitelist + if (component.JobWhitelist != null) + { + for (var i = 0; i < listings.Count; i++) + { + var entry = listings[i]; + if (entry.JobWhitelist != null) + { + var found = false; + foreach (var job in component.JobWhitelist) + { + if (entry.JobWhitelist.Contains(job)) + { + found = true; + break; + } + } + if (!found) + listings.Remove(entry); + } + } + } + accData = new UplinkAccountData(acc.AccountHolder, acc.Balance); + } + else + { + accData = new UplinkAccountData(null, 0); + } + + ui.SetState(new UplinkUpdateState(accData, listings.ToArray())); } public bool AddUplink(EntityUid user, UplinkAccount account, EntityUid? uplinkEntity = null) @@ -204,9 +250,9 @@ namespace Content.Server.Traitor.Uplink { while (containerSlotEnumerator.MoveNext(out var pdaUid)) { - if(!pdaUid.ContainedEntity.HasValue) continue; + if (!pdaUid.ContainedEntity.HasValue) continue; - if(HasComp(pdaUid.ContainedEntity.Value)) + if (HasComp(pdaUid.ContainedEntity.Value)) return pdaUid.ContainedEntity.Value; } } diff --git a/Content.Shared/PDA/UplinkCategory.cs b/Content.Shared/PDA/UplinkCategory.cs index 2b21a230a0..94e5d82b44 100644 --- a/Content.Shared/PDA/UplinkCategory.cs +++ b/Content.Shared/PDA/UplinkCategory.cs @@ -10,6 +10,7 @@ namespace Content.Shared.PDA Bundles, Tools, Utility, + Job, Armor, Pointless, } diff --git a/Content.Shared/PDA/UplinkStoreListingPrototype.cs b/Content.Shared/PDA/UplinkStoreListingPrototype.cs index 78a34e541e..f997380e7f 100644 --- a/Content.Shared/PDA/UplinkStoreListingPrototype.cs +++ b/Content.Shared/PDA/UplinkStoreListingPrototype.cs @@ -1,5 +1,7 @@ +using Content.Shared.Roles; using Robust.Shared.Prototypes; using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype; +using Robust.Shared.Serialization.TypeSerializers.Implementations.Custom.Prototype.Set; using Robust.Shared.Utility; namespace Content.Shared.PDA @@ -29,6 +31,9 @@ namespace Content.Shared.PDA [DataField("icon")] public SpriteSpecifier? Icon { get; } = null; + [DataField("jobWhitelist", customTypeSerializer:typeof(PrototypeIdHashSetSerializer))] + public HashSet? JobWhitelist; + [DataField("surplus")] public bool CanSurplus = true; } diff --git a/Content.Shared/Traitor/Uplink/UplinkAccountData.cs b/Content.Shared/Traitor/Uplink/UplinkAccountData.cs index 2b3cb4e149..2d4a392a30 100644 --- a/Content.Shared/Traitor/Uplink/UplinkAccountData.cs +++ b/Content.Shared/Traitor/Uplink/UplinkAccountData.cs @@ -1,3 +1,4 @@ +using Content.Shared.Roles; using Robust.Shared.Serialization; namespace Content.Shared.Traitor.Uplink @@ -7,7 +8,6 @@ namespace Content.Shared.Traitor.Uplink { public EntityUid? DataAccountHolder; public int DataBalance; - public UplinkAccountData(EntityUid? dataAccountHolder, int dataBalance) { DataAccountHolder = dataAccountHolder; diff --git a/Content.Shared/Traitor/Uplink/UplinkListingData.cs b/Content.Shared/Traitor/Uplink/UplinkListingData.cs index 848054f0be..a6e5ac65ed 100644 --- a/Content.Shared/Traitor/Uplink/UplinkListingData.cs +++ b/Content.Shared/Traitor/Uplink/UplinkListingData.cs @@ -13,10 +13,11 @@ namespace Content.Shared.Traitor.Uplink public readonly string Description; public readonly string ListingName; public readonly SpriteSpecifier? Icon; + public readonly HashSet? JobWhitelist; public UplinkListingData(string listingName, string itemId, int price, UplinkCategory category, - string description, SpriteSpecifier? icon) + string description, SpriteSpecifier? icon, HashSet? jobWhitelist) { ListingName = listingName; Price = price; @@ -24,6 +25,7 @@ namespace Content.Shared.Traitor.Uplink Description = description; ItemId = itemId; Icon = icon; + JobWhitelist = jobWhitelist; } public bool Equals(UplinkListingData? other) diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml index 8b06f9be33..e5173f7546 100644 --- a/Resources/Prototypes/Catalog/uplink_catalog.yml +++ b/Resources/Prototypes/Catalog/uplink_catalog.yml @@ -304,6 +304,17 @@ itemId: DehydratedSpaceCarp price: 3 +# Job Specific + +- type: uplinkListing + id: uplinkNecronomicon + category: Job + itemId: BibleNecronomicon + description: An unholy book capable of summoning a demonic familiar. + price: 6 + jobWhitelist: + - Chaplain + # Armor # Should be cameleon shoes, change when implemented.