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