diff --git a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs
index 6b30c82036..062fd7feea 100644
--- a/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs
+++ b/Content.Client/GameObjects/Components/PDA/PDABoundUserInterface.cs
@@ -1,8 +1,10 @@
using System;
+using Content.Client.GameObjects.EntitySystems;
using Content.Client.Utility;
using Content.Shared.GameObjects.Components.PDA;
using Robust.Client.GameObjects.Components.UserInterface;
using Robust.Client.Graphics.Drawing;
+using Robust.Client.Interfaces.UserInterface;
using Robust.Client.UserInterface.Controls;
using Robust.Client.UserInterface.CustomControls;
using Robust.Shared.GameObjects;
@@ -19,13 +21,14 @@ namespace Content.Client.GameObjects.Components.PDA
{
#pragma warning disable 649
[Dependency] private readonly IPrototypeManager _prototypeManager;
+ [Dependency] private readonly IUserInterfaceManager _userInterfaceManager;
#pragma warning restore 649
private PDAMenu _menu;
- private ClientUserInterfaceComponent Owner;
+ private PDAMenuPopup failPopup;
public PDABoundUserInterface(ClientUserInterfaceComponent owner, object uiKey) : base(owner, uiKey)
{
- Owner = owner;
+
}
protected override void Open()
@@ -56,6 +59,17 @@ namespace Content.Client.GameObjects.Components.PDA
_menu.OnListingButtonPressed += (args, listing) =>
{
+ if (_menu.CurrentLoggedInAccount.DataBalance < listing.Price)
+ {
+ failPopup = new PDAMenuPopup(Loc.GetString("Insufficient funds!"));
+ _userInterfaceManager.ModalRoot.AddChild(failPopup);
+ failPopup.Open(UIBox2.FromDimensions(_menu.Position.X + 150, _menu.Position.Y + 60, 156, 24));
+ _menu.OnClose += () =>
+ {
+ failPopup.Dispose();
+ };
+ }
+
SendMessage(new PDAUplinkBuyListingMessage(listing));
};
@@ -67,13 +81,12 @@ namespace Content.Client.GameObjects.Components.PDA
};
}
-
protected override void UpdateState(BoundUserInterfaceState state)
{
base.UpdateState(state);
DebugTools.Assert((state is PDAUBoundUserInterfaceState));
- var cstate = (PDAUBoundUserInterfaceState) state;
+ var cstate = (PDAUBoundUserInterfaceState)state;
switch (state)
{
case PDAUpdateState msg:
@@ -108,18 +121,96 @@ namespace Content.Client.GameObjects.Components.PDA
_menu.AddListingGui(item);
}
}
+
+ var balance = _menu.CurrentLoggedInAccount.DataBalance;
+ var weightedColor = GetWeightedColorString(balance);
+ _menu.BalanceInfo.SetMarkup(Loc.GetString("TC Balance: [color={0}]{1}[/color]", weightedColor, balance));
+ _menu.MasterTabContainer.SetTabVisible(1, msg.Account != null);
break;
}
-
}
}
+
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
_menu?.Dispose();
}
+ ///
+ /// This is shitcode. It is, however, "PJB-approved shitcode".
+ ///
+ ///
+ ///
+ public static Color GetWeightedColor(int x)
+ {
+ var weightedColor = Color.Gray;
+ if (x <= 0)
+ {
+ return weightedColor;
+ }
+ if (x <= 5)
+ {
+ weightedColor = Color.Green;
+ }
+ else if (x > 5 && x < 10)
+ {
+ weightedColor = Color.Yellow;
+ }
+ else if (x > 10 && x <= 20)
+ {
+ weightedColor = Color.Orange;
+ }
+ else if (x > 20 && x <= 50)
+ {
+ weightedColor = Color.Purple;
+ }
+
+ return weightedColor;
+ }
+
+ public static string GetWeightedColorString(int x)
+ {
+ var weightedColor = "gray";
+ if (x <= 0)
+ {
+ return weightedColor;
+ }
+
+ if (x <= 5)
+ {
+ weightedColor = "green";
+ }
+ else if (x > 5 && x < 10)
+ {
+ weightedColor = "yellow";
+ }
+ else if (x > 10 && x <= 20)
+ {
+ weightedColor = "yellow";
+ }
+ else if (x > 20 && x <= 50)
+ {
+ weightedColor = "purple";
+ }
+ return weightedColor;
+ }
+
+ public sealed class PDAMenuPopup : Popup
+ {
+ public PDAMenuPopup(string text)
+ {
+ var label = new RichTextLabel();
+ label.SetMessage(text);
+ AddChild(new PanelContainer
+ {
+ StyleClasses = { ExamineSystem.StyleClassEntityTooltip },
+ Children = { label }
+ });
+ }
+ }
+
private class PDAMenu : SS14Window
{
protected override Vector2? CustomSize => (512, 256);
@@ -144,6 +235,7 @@ namespace Content.Client.GameObjects.Components.PDA
public VBoxContainer UplinkListingsContainer;
public VBoxContainer CategoryListContainer;
+ public RichTextLabel BalanceInfo;
public event Action OnListingButtonPressed;
public event Action OnCategoryButtonPressed;
@@ -241,16 +333,16 @@ namespace Content.Client.GameObjects.Components.PDA
CategoryListContainer = new VBoxContainer
{
};
- var uplinkStoreHeader = new Label
+
+ BalanceInfo = new RichTextLabel
{
- Align = Label.AlignMode.Center,
- Text = Loc.GetString("Uplink Listings"),
+ SizeFlagsHorizontal = SizeFlags.ShrinkCenter,
};
//Red background container.
var masterPanelContainer = new PanelContainer
{
- PanelOverride = new StyleBoxFlat {BackgroundColor = Color.DarkRed.WithAlpha(0.6f)},
+ PanelOverride = new StyleBoxFlat { BackgroundColor = Color.Black },
SizeFlagsVertical = SizeFlags.FillExpand
};
@@ -272,7 +364,7 @@ namespace Content.Client.GameObjects.Components.PDA
//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)},
+ PanelOverride = new StyleBoxFlat { BackgroundColor = Color.Gray.WithAlpha(0.02f) },
SizeFlagsVertical = SizeFlags.FillExpand,
Children =
{
@@ -300,7 +392,7 @@ namespace Content.Client.GameObjects.Components.PDA
Children =
{
- uplinkStoreHeader,
+ BalanceInfo,
masterPanelContainer
}
};
@@ -334,7 +426,7 @@ namespace Content.Client.GameObjects.Components.PDA
private void PopulateUplinkCategoryButtons()
{
- foreach (UplinkCategory cat in Enum.GetValues(typeof (UplinkCategory)))
+ foreach (UplinkCategory cat in Enum.GetValues(typeof(UplinkCategory)))
{
var catButton = new PDAUplinkCategoryButton
@@ -343,7 +435,9 @@ namespace Content.Client.GameObjects.Components.PDA
ButtonCategory = cat
};
-
+ //It'd be neat if it could play a cool tech ping sound when you switch categories,
+ //but right now there doesn't seem to be an easy way to do client-side audio without still having to round trip to the server and
+ //send to a specific client INetChannel.
catButton.OnPressed += args => OnCategoryButtonPressed?.Invoke(args, catButton.ButtonCategory);
CategoryListContainer.AddChild(catButton);
@@ -357,34 +451,41 @@ namespace Content.Client.GameObjects.Components.PDA
{
return;
}
-
+ var weightedColor = GetWeightedColor(listing.Price);
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,
+ Modulate = _loggedInUplinkAccount.DataBalance >= listing.Price
+ ? Color.White
+ : Color.Gray.WithAlpha(0.30f)
};
var priceLabel = new Label
{
Text = $"{listing.Price} TC",
- Align = Label.AlignMode.Right,
+ SizeFlagsHorizontal = SizeFlags.ShrinkEnd,
+ Modulate = _loggedInUplinkAccount.DataBalance >= listing.Price
+ ? weightedColor
+ : Color.Gray.WithAlpha(0.30f)
};
+ //Padding for the price lable.
+ var pricePadding = new HBoxContainer
+ {
+ CustomMinimumSize = (32, 1),
+ SizeFlagsHorizontal = SizeFlags.Fill,
+ };
- //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.
+ //Contains the name of the item and its price. Used for spacing item name and price.
var listingButtonHbox = new HBoxContainer
{
- Modulate = itemColor,
Children =
{
itemLabel,
- priceLabel
+ priceLabel,
+ pricePadding
}
};
@@ -406,17 +507,15 @@ namespace Content.Client.GameObjects.Components.PDA
}
};
pdaUplinkListingButton.OnPressed += args
- => OnListingButtonPressed?.Invoke(args,pdaUplinkListingButton.ButtonListing);
+ => OnListingButtonPressed?.Invoke(args, pdaUplinkListingButton.ButtonListing);
UplinkListingsContainer.AddChild(pdaUplinkListingButton);
}
-
public void ClearListings()
{
UplinkListingsContainer.Children.Clear();
}
-
private sealed class PDAUplinkItemButton : ContainerButton
{
public UplinkListingData ButtonListing;
diff --git a/Content.Client/GameObjects/Components/PDA/PDAComponent.cs b/Content.Client/GameObjects/Components/PDA/PDAComponent.cs
index 8118d7ee33..bdeb4f7ffb 100644
--- a/Content.Client/GameObjects/Components/PDA/PDAComponent.cs
+++ b/Content.Client/GameObjects/Components/PDA/PDAComponent.cs
@@ -1,11 +1,32 @@
using Content.Shared.GameObjects.Components.PDA;
+using Robust.Client.GameObjects.EntitySystems;
+using Robust.Shared.Audio;
using Robust.Shared.GameObjects;
+using Robust.Shared.GameObjects.Systems;
+using Robust.Shared.Interfaces.Network;
+using Robust.Shared.Players;
namespace Content.Client.GameObjects.Components.PDA
{
[RegisterComponent]
public class PDAComponent : SharedPDAComponent
{
+ public override void HandleNetworkMessage(ComponentMessage message, INetChannel netChannel, ICommonSession session = null)
+ {
+ base.HandleNetworkMessage(message, netChannel, session);
+ switch(message)
+ {
+ case PDAUplinkBuySuccessMessage _ :
+ EntitySystem.Get().Play("/Audio/effects/kaching.ogg", Owner, AudioParams.Default.WithVolume(-2f));
+ break;
+
+ case PDAUplinkInsufficientFundsMessage _ :
+ EntitySystem.Get().Play("/Audio/effects/error.ogg", Owner, AudioParams.Default);
+ break;
+
+ }
+ }
+
}
}
diff --git a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs
index 52f9b4f670..9f88041a01 100644
--- a/Content.Server/GameObjects/Components/PDA/PDAComponent.cs
+++ b/Content.Server/GameObjects/Components/PDA/PDAComponent.cs
@@ -11,8 +11,10 @@ using Content.Shared.GameObjects.Components.PDA;
using Robust.Server.GameObjects;
using Robust.Server.GameObjects.Components.Container;
using Robust.Server.GameObjects.Components.UserInterface;
+using Robust.Server.GameObjects.EntitySystems;
using Robust.Server.Interfaces.GameObjects;
using Robust.Shared.GameObjects;
+using Robust.Shared.GameObjects.Systems;
using Robust.Shared.Interfaces.GameObjects;
using Robust.Shared.IoC;
using Robust.Shared.Localization;
@@ -69,7 +71,8 @@ namespace Content.Server.GameObjects.Components.PDA
_interface.OnReceiveMessage += UserInterfaceOnReceiveMessage;
var idCard = _entityManager.SpawnEntity(_startingIdCard, Owner.Transform.GridPosition);
var idCardComponent = idCard.GetComponent();
- InsertIdCard(idCardComponent);
+ _idSlot.Insert(idCardComponent.Owner);
+ ContainedID = idCardComponent;
UpdatePDAAppearance();
}
@@ -98,9 +101,11 @@ namespace Content.Server.GameObjects.Components.PDA
{
if (!_uplinkManager.TryPurchaseItem(_syndicateUplinkAccount, buyMsg.ListingToBuy))
{
- //TODO: Send a message that tells the buyer they are too poor or something.
+ SendNetworkMessage(new PDAUplinkInsufficientFundsMessage(), message.Session.ConnectedClient);
+ break;
}
+ SendNetworkMessage(new PDAUplinkBuySuccessMessage(), message.Session.ConnectedClient);
break;
}
}
@@ -186,12 +191,14 @@ namespace Content.Server.GameObjects.Components.PDA
OwnerMob = mob;
UpdatePDAUserInterface();
+
}
private void InsertIdCard(IdCardComponent card)
{
_idSlot.Insert(card.Owner);
ContainedID = card;
+ EntitySystem.Get().Play("/Audio/Guns/MagIn/batrifle_magin.ogg", Owner);
}
///
@@ -215,6 +222,7 @@ namespace Content.Server.GameObjects.Components.PDA
{
_lightOn = !_lightOn;
_pdaLight.Enabled = _lightOn;
+ EntitySystem.Get().Play("/Audio/items/flashlight_toggle.ogg", Owner);
UpdatePDAUserInterface();
}
@@ -232,6 +240,8 @@ namespace Content.Server.GameObjects.Components.PDA
var cardItemComponent = cardEntity.GetComponent();
hands.PutInHandOrDrop(cardItemComponent);
ContainedID = null;
+
+ EntitySystem.Get().Play("/Audio/machines/machine_switch.ogg", Owner);
UpdatePDAUserInterface();
}
diff --git a/Content.Server/PDA/PDAUplinkManager.cs b/Content.Server/PDA/PDAUplinkManager.cs
index 52c503ebea..7e199ce153 100644
--- a/Content.Server/PDA/PDAUplinkManager.cs
+++ b/Content.Server/PDA/PDAUplinkManager.cs
@@ -1,6 +1,4 @@
-using System;
using System.Collections.Generic;
-using System.Diagnostics;
using System.Linq;
using Content.Server.GameObjects;
using Content.Server.GameObjects.Components.Mobs;
@@ -31,7 +29,7 @@ namespace Content.Server.PDA
foreach (var item in _prototypeManager.EnumeratePrototypes())
{
var newListing = new UplinkListingData(item.ListingName, item.ItemId, item.Price, item.Category,
- item.Description, item.DisplayColor);
+ item.Description);
RegisterUplinkListing(newListing);
}
@@ -94,11 +92,15 @@ namespace Content.Server.PDA
return false;
}
+ if (!ChangeBalance(acc, -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);
+ return true;
}
diff --git a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs
index 16515d3f9d..567f7f8b2c 100644
--- a/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs
+++ b/Content.Shared/GameObjects/Components/PDA/SharedPDAComponent.cs
@@ -80,6 +80,16 @@ namespace Content.Shared.GameObjects.Components.PDA
}
}
+ [Serializable, NetSerializable]
+ public sealed class PDAUplinkBuySuccessMessage : ComponentMessage
+ {
+ }
+
+ [Serializable, NetSerializable]
+ public sealed class PDAUplinkInsufficientFundsMessage : ComponentMessage
+ {
+ }
+
[Serializable, NetSerializable]
public sealed class PDARequestUpdateInterfaceMessage : BoundUserInterfaceMessage
{
@@ -156,18 +166,16 @@ namespace Content.Shared.GameObjects.Components.PDA
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)
+ string description) : base(ContentNetIDs.PDA)
{
ListingName = listingName;
Price = price;
Category = category;
Description = description;
ItemId = itemId;
- DisplayColor = displayColor;
}
public bool Equals(UplinkListingData other)
diff --git a/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs
index 9dca94d517..13f8ad5245 100644
--- a/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs
+++ b/Content.Shared/GameObjects/Components/PDA/UplinkCategory.cs
@@ -2,7 +2,8 @@ namespace Content.Shared.GameObjects.Components.PDA
{
public enum UplinkCategory
{
- Weapon,
+ Weapons,
+ Ammo,
Utility,
}
}
diff --git a/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs b/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs
index 50f7097127..a4af3f9540 100644
--- a/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs
+++ b/Content.Shared/Prototypes/PDA/UplinkStoreListingPrototype.cs
@@ -16,7 +16,6 @@ namespace Content.Shared.Prototypes.PDA
private UplinkCategory _category;
private string _desc;
private string _name;
- private Color _displayColor;
public string ID => _id;
@@ -25,7 +24,6 @@ namespace Content.Shared.Prototypes.PDA
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);
@@ -35,7 +33,6 @@ namespace Content.Shared.Prototypes.PDA
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/Audio/effects/error.ogg b/Resources/Audio/effects/error.ogg
new file mode 100644
index 0000000000..4d7188e251
Binary files /dev/null and b/Resources/Audio/effects/error.ogg differ
diff --git a/Resources/Audio/effects/kaching.ogg b/Resources/Audio/effects/kaching.ogg
new file mode 100644
index 0000000000..ea642a56a9
Binary files /dev/null and b/Resources/Audio/effects/kaching.ogg differ
diff --git a/Resources/Prototypes/PDA/uplink_catalog.yml b/Resources/Prototypes/PDA/uplink_catalog.yml
index 11cced4cef..1c1542f2ef 100644
--- a/Resources/Prototypes/PDA/uplink_catalog.yml
+++ b/Resources/Prototypes/PDA/uplink_catalog.yml
@@ -1,29 +1,17 @@
+- type: uplinkListing
+ id: UplinkPistolClarissa
+ category: Weapons
+ itemId: PistolClarissa
+ price: 15
+
+- type: uplinkListing
+ id: UplinkPistol9mmMagazine
+ category: Ammo
+ itemId: magazine_9mm
+ price: 5
- 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