diff --git a/Content.Client/Traitor/Uplink/UplinkBoundUserInterface.cs b/Content.Client/Traitor/Uplink/UplinkBoundUserInterface.cs
index 171fe488fe..f14b5ab842 100644
--- a/Content.Client/Traitor/Uplink/UplinkBoundUserInterface.cs
+++ b/Content.Client/Traitor/Uplink/UplinkBoundUserInterface.cs
@@ -1,26 +1,14 @@
-using Content.Client.Examine;
-using Content.Client.Message;
using Content.Shared.Traitor.Uplink;
using JetBrains.Annotations;
using Robust.Client.GameObjects;
-using Robust.Client.UserInterface;
-using Robust.Client.UserInterface.Controls;
using Robust.Shared.GameObjects;
-using Robust.Shared.IoC;
-using Robust.Shared.Localization;
-using Robust.Shared.Maths;
-using Robust.Shared.Prototypes;
namespace Content.Client.Traitor.Uplink
{
[UsedImplicitly]
public class UplinkBoundUserInterface : BoundUserInterface
{
- [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
- [Dependency] private readonly IUserInterfaceManager _userInterfaceManager = default!;
-
private UplinkMenu? _menu;
- private UplinkMenuPopup? _failPopup;
public UplinkBoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
@@ -28,23 +16,12 @@ namespace Content.Client.Traitor.Uplink
protected override void Open()
{
- _menu = new UplinkMenu(_prototypeManager);
+ _menu = new UplinkMenu();
_menu.OpenCentered();
_menu.OnClose += Close;
_menu.OnListingButtonPressed += (_, listing) =>
{
- if (_menu.CurrentLoggedInAccount?.DataBalance < listing.Price)
- {
- _failPopup = new UplinkMenuPopup(Loc.GetString("uplink-bound-user-interface-insufficient-funds-popup"));
- _userInterfaceManager.ModalRoot.AddChild(_failPopup);
- _failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24));
- _menu.OnClose += () =>
- {
- _failPopup.Dispose();
- };
- }
-
SendMessage(new UplinkBuyListingMessage(listing.ItemId));
};
@@ -54,59 +31,36 @@ namespace Content.Client.Traitor.Uplink
SendMessage(new UplinkRequestUpdateInterfaceMessage());
};
- }
+ _menu.OnWithdrawAttempt += (tc) =>
+ {
+ SendMessage(new UplinkTryWithdrawTC(tc));
+ };
+ }
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
if (_menu == null)
- {
return;
- }
switch (state)
{
case UplinkUpdateState msg:
- {
- _menu.CurrentLoggedInAccount = msg.Account;
- var balance = msg.Account.DataBalance;
- string weightedColor = balance switch
- {
- <= 0 => "gray",
- <= 5 => "green",
- <= 20 => "yellow",
- <= 50 => "purple",
- _ => "gray"
- };
- _menu.BalanceInfo.SetMarkup(Loc.GetString("uplink-bound-user-interface-tc-balance-popup",
- ("weightedColor", weightedColor),
- ("balance", balance)));
-
- _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);
- }
-
+ _menu.UpdateAccount(msg.Account);
+ _menu.UpdateListing(msg.Listings);
break;
- }
}
}
- private sealed class UplinkMenuPopup : Popup
+ protected override void Dispose(bool disposing)
{
- public UplinkMenuPopup(string text)
- {
- var label = new RichTextLabel();
- label.SetMessage(text);
- AddChild(new PanelContainer
- {
- StyleClasses = { ExamineSystem.StyleClassEntityTooltip },
- Children = { label }
- });
- }
+ base.Dispose(disposing);
+ if (!disposing)
+ return;
+
+ _menu?.Close();
+ _menu?.Dispose();
}
}
}
diff --git a/Content.Client/Traitor/Uplink/UplinkListingControl.xaml b/Content.Client/Traitor/Uplink/UplinkListingControl.xaml
index 544edc191d..d6d1283ced 100644
--- a/Content.Client/Traitor/Uplink/UplinkListingControl.xaml
+++ b/Content.Client/Traitor/Uplink/UplinkListingControl.xaml
@@ -10,6 +10,13 @@
MinWidth="64"/>
-
+
+
+
+
diff --git a/Content.Client/Traitor/Uplink/UplinkListingControl.xaml.cs b/Content.Client/Traitor/Uplink/UplinkListingControl.xaml.cs
index 8080f42fd8..c3f6c2f925 100644
--- a/Content.Client/Traitor/Uplink/UplinkListingControl.xaml.cs
+++ b/Content.Client/Traitor/Uplink/UplinkListingControl.xaml.cs
@@ -1,4 +1,5 @@
using Robust.Client.AutoGenerated;
+using Robust.Client.Graphics;
using Robust.Client.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.XAML;
@@ -9,7 +10,9 @@ namespace Content.Client.Traitor.Uplink
[GenerateTypedNameReferences]
public partial class UplinkListingControl : Control
{
- public UplinkListingControl(string itemName, string itemDescription, int itemPrice, bool canBuy)
+
+ public UplinkListingControl(string itemName, string itemDescription,
+ int itemPrice, bool canBuy, Texture? texture = null)
{
RobustXamlLoader.Load(this);
@@ -18,6 +21,8 @@ namespace Content.Client.Traitor.Uplink
UplinkItemBuyButton.Text = $"{itemPrice} TC";
UplinkItemBuyButton.Disabled = !canBuy;
+
+ UplinkItemTexture.Texture = texture;
}
}
}
diff --git a/Content.Client/Traitor/Uplink/UplinkMenu.xaml b/Content.Client/Traitor/Uplink/UplinkMenu.xaml
index dae85f2e81..0f67b73fbb 100644
--- a/Content.Client/Traitor/Uplink/UplinkMenu.xaml
+++ b/Content.Client/Traitor/Uplink/UplinkMenu.xaml
@@ -12,6 +12,10 @@
Access="Public"
HorizontalExpand="True"
HorizontalAlignment="Left" />
+
diff --git a/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs b/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs
index a599a018cd..df026608ee 100644
--- a/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs
+++ b/Content.Client/Traitor/Uplink/UplinkMenu.xaml.cs
@@ -1,12 +1,16 @@
using System;
+using Content.Client.Message;
using Content.Shared.PDA;
using Content.Shared.Traitor.Uplink;
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.IoC;
using Robust.Shared.Localization;
-using Robust.Shared.Maths;
using Robust.Shared.Prototypes;
namespace Content.Client.Traitor.Uplink
@@ -14,18 +18,25 @@ namespace Content.Client.Traitor.Uplink
[GenerateTypedNameReferences]
public partial class UplinkMenu : SS14Window
{
- private readonly IPrototypeManager _prototypeManager;
+ [Dependency] private readonly IPrototypeManager _prototypeManager = default!;
+ [Dependency] private readonly IResourceCache _resourceCache = default!;
+
+ private UplinkWithdrawWindow? _withdrawWindow;
public event Action? OnListingButtonPressed;
public event Action? OnCategoryButtonPressed;
+ public event Action? OnWithdrawAttempt;
- public UplinkMenu(IPrototypeManager prototypeManager)
+ private UplinkCategory _currentFilter;
+ private UplinkAccountData? _loggedInUplinkAccount;
+
+ public UplinkMenu()
{
RobustXamlLoader.Load(this);
-
- _prototypeManager = prototypeManager;
+ IoCManager.InjectDependencies(this);
PopulateUplinkCategoryButtons();
+ WithdrawButton.OnButtonDown += OnWithdrawButtonDown;
}
public UplinkCategory CurrentFilterCategory
@@ -42,16 +53,60 @@ namespace Content.Client.Traitor.Uplink
}
}
- public UplinkAccountData? CurrentLoggedInAccount
+ public void UpdateAccount(UplinkAccountData account)
{
- get => _loggedInUplinkAccount;
- set => _loggedInUplinkAccount = value;
+ _loggedInUplinkAccount = account;
+
+ // update balance label
+ var balance = account.DataBalance;
+ var weightedColor = balance switch
+ {
+ <= 0 => "gray",
+ <= 5 => "green",
+ <= 20 => "yellow",
+ <= 50 => "purple",
+ _ => "gray"
+ };
+ var balanceStr = Loc.GetString("uplink-bound-user-interface-tc-balance-popup",
+ ("weightedColor", weightedColor),
+ ("balance", balance));
+ BalanceInfo.SetMarkup(balanceStr);
+
+ // you can't withdraw if you don't have TC
+ WithdrawButton.Disabled = balance <= 0;
}
- private UplinkCategory _currentFilter;
- private UplinkAccountData? _loggedInUplinkAccount;
+ public void UpdateListing(UplinkListingData[] listings)
+ {
+ // should probably chunk these out instead. to-do if this clogs the internet tubes.
+ // maybe read clients prototypes instead?
+ ClearListings();
+ foreach (var item in listings)
+ {
+ AddListingGui(item);
+ }
+ }
- public void AddListingGui(UplinkListingData listing)
+ private void OnWithdrawButtonDown(BaseButton.ButtonEventArgs args)
+ {
+ if (_loggedInUplinkAccount == null)
+ return;
+
+ // check if window is already open
+ if (_withdrawWindow != null && _withdrawWindow.IsOpen)
+ {
+ _withdrawWindow.MoveToFront();
+ return;
+ }
+
+ // open a new one
+ _withdrawWindow = new UplinkWithdrawWindow(_loggedInUplinkAccount.DataBalance);
+ _withdrawWindow.OpenCentered();
+
+ _withdrawWindow.OnWithdrawAttempt += OnWithdrawAttempt;
+ }
+
+ private void AddListingGui(UplinkListingData listing)
{
if (!_prototypeManager.TryIndex(listing.ItemId, out EntityPrototype? prototype) || listing.Category != CurrentFilterCategory)
{
@@ -63,14 +118,19 @@ namespace Content.Client.Traitor.Uplink
var listingPrice = listing.Price;
var canBuy = _loggedInUplinkAccount?.DataBalance >= listing.Price;
- var newListing = new UplinkListingControl(listingName, listingDesc, listingPrice, canBuy);
+ var texture = listing.Icon?.Frame0();
+ if (texture == null)
+ texture = SpriteComponent.GetPrototypeIcon(prototype, _resourceCache).Default;
+
+
+ var newListing = new UplinkListingControl(listingName, listingDesc, listingPrice, canBuy, texture);
newListing.UplinkItemBuyButton.OnButtonDown += args
=> OnListingButtonPressed?.Invoke(args, listing);
UplinkListingsContainer.AddChild(newListing);
}
- public void ClearListings()
+ private void ClearListings()
{
UplinkListingsContainer.Children.Clear();
}
@@ -93,6 +153,12 @@ namespace Content.Client.Traitor.Uplink
}
}
+ public override void Close()
+ {
+ base.Close();
+ _withdrawWindow?.Close();
+ }
+
private sealed class PDAUplinkCategoryButton : Button
{
public UplinkCategory ButtonCategory;
diff --git a/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml b/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml
new file mode 100644
index 0000000000..218c7a8cb9
--- /dev/null
+++ b/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
diff --git a/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml.cs b/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml.cs
new file mode 100644
index 0000000000..2af3223354
--- /dev/null
+++ b/Content.Client/Traitor/Uplink/UplinkWithdrawWindow.xaml.cs
@@ -0,0 +1,34 @@
+using Robust.Client.AutoGenerated;
+using Robust.Client.UserInterface.CustomControls;
+using Robust.Client.UserInterface.XAML;
+using Robust.Shared.Localization;
+
+namespace Content.Client.Traitor.Uplink
+{
+ ///
+ /// Window to select amount TC to withdraw from Uplink account
+ /// Used as sub-window in Uplink UI
+ ///
+ [GenerateTypedNameReferences]
+ public partial class UplinkWithdrawWindow : SS14Window
+ {
+ public event System.Action? OnWithdrawAttempt;
+
+ public UplinkWithdrawWindow(int tcCount)
+ {
+ RobustXamlLoader.Load(this);
+
+ // setup withdraw slider
+ WithdrawSlider.MinValue = 1;
+ WithdrawSlider.MaxValue = tcCount;
+
+ // and buttons
+ ApplyButton.OnButtonDown += _ =>
+ {
+ OnWithdrawAttempt?.Invoke(WithdrawSlider.Value);
+ Close();
+ };
+ CancelButton.OnButtonDown += _ => Close();
+ }
+ }
+}
diff --git a/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs b/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs
index 4e451985f0..4477ff57be 100644
--- a/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs
+++ b/Content.Server/Traitor/Uplink/Account/UplinkAccountsSystem.cs
@@ -1,6 +1,9 @@
+using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Content.Server.Mind.Components;
+using Content.Server.Stack;
+using Content.Shared.Stacks;
using Content.Shared.Traitor.Uplink;
using Robust.Shared.GameObjects;
using Robust.Shared.IoC;
@@ -13,8 +16,12 @@ namespace Content.Server.Traitor.Uplink.Account
///
public class UplinkAccountsSystem : EntitySystem
{
+ public const string TelecrystalProtoId = "Telecrystal";
+
[Dependency]
private readonly UplinkListingSytem _listingSystem = default!;
+ [Dependency]
+ private readonly SharedStackSystem _stackSystem = default!;
private readonly HashSet _accounts = new();
@@ -86,5 +93,25 @@ namespace Content.Server.Traitor.Uplink.Account
purchasedItem = EntityManager.SpawnEntity(listing.ItemId, spawnCoords);
return true;
}
+
+ public bool TryWithdrawTC(UplinkAccount acc, int tc, EntityCoordinates spawnCoords, [NotNullWhen(true)] out EntityUid? stackUid)
+ {
+ stackUid = null;
+
+ // try to charge TC from players account
+ var actTC = Math.Min(tc, acc.Balance);
+ if (actTC <= 0)
+ return false;
+ if (!RemoveFromBalance(acc, actTC))
+ return false;
+
+ // create a stack of TCs near player
+ var stackEntity = EntityManager.SpawnEntity(TelecrystalProtoId, spawnCoords);
+ stackUid = stackEntity.Uid;
+
+ // set right amount in stack
+ _stackSystem.SetCount(stackUid.Value, actTC);
+ return true;
+ }
}
}
diff --git a/Content.Server/Traitor/Uplink/UplinkListingSytem.cs b/Content.Server/Traitor/Uplink/UplinkListingSytem.cs
index 2c81693eea..dea8f57458 100644
--- a/Content.Server/Traitor/Uplink/UplinkListingSytem.cs
+++ b/Content.Server/Traitor/Uplink/UplinkListingSytem.cs
@@ -24,7 +24,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.Price, item.Category, item.Description, item.Icon);
RegisterUplinkListing(newListing);
}
diff --git a/Content.Server/Traitor/Uplink/UplinkSystem.cs b/Content.Server/Traitor/Uplink/UplinkSystem.cs
index 9f6e9517f6..674fa67dff 100644
--- a/Content.Server/Traitor/Uplink/UplinkSystem.cs
+++ b/Content.Server/Traitor/Uplink/UplinkSystem.cs
@@ -6,6 +6,7 @@ using Content.Server.PDA;
using Content.Server.Traitor.Uplink.Account;
using Content.Server.Traitor.Uplink.Components;
using Content.Server.UserInterface;
+using Content.Shared.Hands.Components;
using Content.Shared.Interaction;
using Content.Shared.Traitor.Uplink;
using Robust.Server.GameObjects;
@@ -34,8 +35,11 @@ namespace Content.Server.Traitor.Uplink
SubscribeLocalEvent(OnInit);
SubscribeLocalEvent(OnRemove);
SubscribeLocalEvent(OnUseHand);
+
+ // UI events
SubscribeLocalEvent(OnBuy);
SubscribeLocalEvent(OnRequestUpdateUI);
+ SubscribeLocalEvent(OnWithdrawTC);
SubscribeLocalEvent(OnBalanceChangedBroadcast);
}
@@ -131,6 +135,31 @@ namespace Content.Server.Traitor.Uplink
RaiseNetworkEvent(new UplinkBuySuccessMessage(), message.Session.ConnectedClient);
}
+ private void OnWithdrawTC(EntityUid uid, UplinkComponent uplink, UplinkTryWithdrawTC args)
+ {
+ var acc = uplink.UplinkAccount;
+ if (acc == null)
+ return;
+
+ var player = args.Session.AttachedEntity;
+ if (player == null) return;
+ var cords = player.Transform.Coordinates;
+
+ // try to withdraw TCs from account
+ if (!_accounts.TryWithdrawTC(acc, args.TC, cords, out var tcUid))
+ return;
+
+ // try to put it into players hands
+ if (player.TryGetComponent(out SharedHandsComponent? hands))
+ hands.TryPutInAnyHand(EntityManager.GetEntity(tcUid.Value));
+
+ // play buying sound
+ SoundSystem.Play(Filter.SinglePlayer(args.Session), uplink.BuySuccessSound.GetSound(),
+ uplink.Owner, AudioParams.Default.WithVolume(-2f));
+
+ UpdateUserInterface(uplink);
+ }
+
public void ToggleUplinkUI(UplinkComponent component, IPlayerSession session)
{
var ui = component.Owner.GetUIOrNull(UplinkUiKey.Key);
diff --git a/Content.Shared/PDA/UplinkStoreListingPrototype.cs b/Content.Shared/PDA/UplinkStoreListingPrototype.cs
index 27d718a60c..ddb59957db 100644
--- a/Content.Shared/PDA/UplinkStoreListingPrototype.cs
+++ b/Content.Shared/PDA/UplinkStoreListingPrototype.cs
@@ -1,5 +1,6 @@
using Robust.Shared.Prototypes;
using Robust.Shared.Serialization.Manager.Attributes;
+using Robust.Shared.Utility;
using Robust.Shared.ViewVariables;
namespace Content.Shared.PDA
@@ -25,5 +26,8 @@ namespace Content.Shared.PDA
[DataField("listingName")]
public string ListingName { get; } = string.Empty;
+
+ [DataField("icon")]
+ public SpriteSpecifier? Icon { get; } = null;
}
}
diff --git a/Content.Shared/Traitor/Uplink/UplinkListingData.cs b/Content.Shared/Traitor/Uplink/UplinkListingData.cs
index 5fa160125e..e1037a52da 100644
--- a/Content.Shared/Traitor/Uplink/UplinkListingData.cs
+++ b/Content.Shared/Traitor/Uplink/UplinkListingData.cs
@@ -1,6 +1,7 @@
using Content.Shared.PDA;
using Robust.Shared.GameObjects;
using Robust.Shared.Serialization;
+using Robust.Shared.Utility;
using System;
namespace Content.Shared.Traitor.Uplink
@@ -13,16 +14,18 @@ namespace Content.Shared.Traitor.Uplink
public readonly UplinkCategory Category;
public readonly string Description;
public readonly string ListingName;
+ public readonly SpriteSpecifier? Icon;
public UplinkListingData(string listingName, string itemId,
int price, UplinkCategory category,
- string description)
+ string description, SpriteSpecifier? icon)
{
ListingName = listingName;
Price = price;
Category = category;
Description = description;
ItemId = itemId;
+ Icon = icon;
}
public bool Equals(UplinkListingData? other)
diff --git a/Content.Shared/Traitor/Uplink/UplinkMessagesUI.cs b/Content.Shared/Traitor/Uplink/UplinkMessagesUI.cs
index 3a036ca6b5..aa516e6a54 100644
--- a/Content.Shared/Traitor/Uplink/UplinkMessagesUI.cs
+++ b/Content.Shared/Traitor/Uplink/UplinkMessagesUI.cs
@@ -23,4 +23,15 @@ namespace Content.Shared.Traitor.Uplink
}
}
+
+ [Serializable, NetSerializable]
+ public sealed class UplinkTryWithdrawTC : BoundUserInterfaceMessage
+ {
+ public int TC;
+
+ public UplinkTryWithdrawTC(int tc)
+ {
+ TC = tc;
+ }
+ }
}
diff --git a/Resources/Locale/en-US/traitor/uplink/uplink-component.ftl b/Resources/Locale/en-US/traitor/uplink/uplink-component.ftl
index b02847b903..7e51046bc5 100644
--- a/Resources/Locale/en-US/traitor/uplink/uplink-component.ftl
+++ b/Resources/Locale/en-US/traitor/uplink/uplink-component.ftl
@@ -4,4 +4,10 @@ uplink-bound-user-interface-tc-balance-popup = TC Balance: [color={$weightedColo
uplink-user-interface-title = Uplink
-uplink-user-interface-search-label = Search
\ No newline at end of file
+uplink-user-interface-search-label = Search
+
+# Withdraw UI
+
+uplink-user-interface-withdraw-title = Withdraw TC
+uplink-user-interface-withdraw-withdraw-button = Withdraw
+uplink-user-interface-withdraw-cancel-button = Cancel
diff --git a/Resources/Prototypes/Catalog/uplink_catalog.yml b/Resources/Prototypes/Catalog/uplink_catalog.yml
index 5a16248905..970d8dfdcd 100644
--- a/Resources/Prototypes/Catalog/uplink_catalog.yml
+++ b/Resources/Prototypes/Catalog/uplink_catalog.yml
@@ -4,12 +4,16 @@
id: UplinkPistolClarissa
category: Weapons
itemId: PistolClarissa
+ listingName: Clarissa
+ description: A small, easily concealable, but somewhat underpowered gun. Use pistol magazines (.35 auto).
price: 6
- type: uplinkListing
id: UplinkRevolverInspector
category: Weapons
itemId: RevolverInspector
+ listingName: Inspector
+ description: A .40 magnum caliber revolver. Still quite deadly, despite its ancient design.
price: 8
# Inbuilt suppressor so it's sneaky + more expensive.
@@ -17,6 +21,8 @@
id: UplinkPistolMandella
category: Weapons
itemId: PistolMandella
+ listingName: Mandella
+ description: A rugged, robust operator handgun with inbuilt silencer. Use pistol magazines (.25 caseless).
price: 8
#- type: uplinkListing
@@ -99,6 +105,7 @@
category: Ammo
itemId: SLMagnum
price: 2
+ icon: /Textures/Objects/Weapons/Guns/Ammunition/SpeedLoaders/Magnum/magnum_sl.rsi/icon.png
# Bundles
@@ -107,24 +114,28 @@
category: Bundles
itemId: ClothingBackpackDuffelSyndicateFilledSMG
price: 14
+ icon: /Textures/Objects/Weapons/Guns/SMGs/c20r.rsi/icon.png
- type: uplinkListing
id: UplinkBojevicBundle
category: Bundles
itemId: ClothingBackpackDuffelSyndicateFilledShotgun
price: 13
+ icon: /Textures/Objects/Weapons/Guns/Shotguns/bojevic.rsi/icon.png
- type: uplinkListing
id: UplinkL6SawBundle
category: Bundles
itemId: ClothingBackpackDuffelSyndicateFilledLMG
price: 18
+ icon: /Textures/Objects/Weapons/Guns/LMGs/l6.rsi/icon.png
- type: uplinkListing
id: UplinkGrenadeLauncherBundle
category: Bundles
itemId: ClothingBackpackDuffelSyndicateFilledGrenadeLauncher
price: 25
+ icon: /Textures/Objects/Weapons/Guns/Launchers/china_lake.rsi/icon.png
# Tools
@@ -217,34 +228,6 @@
itemId: lanternextrabright
price: 2
-- type: uplinkListing
- id: UplinkTelecrystal
- category: Misc
- itemId: Telecrystal1
- price: 1
- listingName: telecrystal [1]
-
-- type: uplinkListing
- id: UplinkTelecrystal5
- category: Misc
- itemId: Telecrystal5
- price: 5
- listingName: telecrystal [5]
-
-- type: uplinkListing
- id: UplinkTelecrystal10
- category: Misc
- itemId: Telecrystal10
- price: 10
- listingName: telecrystal [10]
-
-- type: uplinkListing
- id: UplinkTelecrystal20
- category: Misc
- itemId: Telecrystal
- price: 20
- listingName: telecrystal [20]
-
# Pointless
- type: uplinkListing
diff --git a/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml b/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml
index 485e213e88..c9cfbc3c6c 100644
--- a/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml
+++ b/Resources/Prototypes/Entities/Objects/Specific/syndicate.yml
@@ -13,7 +13,7 @@
sprite: Objects/Specific/Syndicate/telecrystal.rsi
- type: Stack
count: 20
- max: 20
+ max: 999999 # todo: add support for unlimited stacks
stackType: Telecrystal
- type: Telecrystal