From cac1c48aa37fde5c0b41def5f87b191acbe24e3b Mon Sep 17 00:00:00 2001 From: Nilanth Animosus Date: Fri, 20 Jul 2018 18:01:38 +0100 Subject: [PATCH] Redesigned campaign buymenu to use a quantity field Additionally sorts the bought items by name then type to attempt to mirror the tabs (Not perfect) --- .../GameModes/MultiPlayerCampaign.cs | 10 +- .../Source/Screens/CampaignUI.cs | 90 ++++++++---- .../Source/GameSession/CargoManager.cs | 136 +++++++++++------- .../GameModes/MultiPlayerCampaign.cs | 20 +-- .../Source/Networking/GameServer.cs | 7 +- 5 files changed, 167 insertions(+), 96 deletions(-) diff --git a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs index 66b46f085..30e711662 100644 --- a/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaClient/Source/GameSession/GameModes/MultiPlayerCampaign.cs @@ -92,9 +92,10 @@ namespace Barotrauma msg.Write(map.SelectedLocationIndex == -1 ? UInt16.MaxValue : (UInt16)map.SelectedLocationIndex); msg.Write((UInt16)CargoManager.PurchasedItems.Count); - foreach (ItemPrefab ip in CargoManager.PurchasedItems) + foreach (PurchasedItem pi in CargoManager.PurchasedItems) { - msg.Write((UInt16)MapEntityPrefab.List.IndexOf(ip)); + msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.itemPrefab)); + msg.Write((UInt16)pi.quantity); } } @@ -111,11 +112,12 @@ namespace Barotrauma int money = msg.ReadInt32(); UInt16 purchasedItemCount = msg.ReadUInt16(); - List purchasedItems = new List(); + List purchasedItems = new List(); for (int i = 0; i < purchasedItemCount; i++) { UInt16 itemPrefabIndex = msg.ReadUInt16(); - purchasedItems.Add(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab); + UInt16 itemQuantity = msg.ReadUInt16(); + purchasedItems.Add(new PurchasedItem(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab, itemQuantity)); } MultiPlayerCampaign campaign = GameMain.GameSession?.GameMode as MultiPlayerCampaign; diff --git a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs index 1e821b151..6ac7b4783 100644 --- a/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs +++ b/Barotrauma/BarotraumaClient/Source/Screens/CampaignUI.cs @@ -85,7 +85,7 @@ namespace Barotrauma int sellColumnWidth = (tabs[(int)Tab.Store].Rect.Width - 40) / 2 - 20; selectedItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, "", tabs[(int)Tab.Store]); - selectedItemList.OnSelected = SellItem; + //selectedItemList.OnSelected = SellItem; storeItemList = new GUIListBox(new Rectangle(0, 30, sellColumnWidth, tabs[(int)Tab.Store].Rect.Height - 80), Color.White * 0.7f, Alignment.TopRight, "", tabs[(int)Tab.Store]); storeItemList.OnSelected = BuyItem; @@ -218,55 +218,91 @@ namespace Barotrauma OnLocationSelected?.Invoke(location, connection); } - private void CreateItemFrame(MapEntityPrefab ep, GUIListBox listBox, int width) + private void CreateItemFrame(PurchasedItem pi, GUIListBox listBox, int width) { GUIFrame frame = new GUIFrame(new Rectangle(0, 0, 0, 50), "ListBoxElement", listBox); - frame.UserData = ep; + frame.UserData = pi; frame.Padding = new Vector4(5.0f, 5.0f, 5.0f, 5.0f); - frame.ToolTip = ep.Description; + frame.ToolTip = pi.itemPrefab.Description; ScalableFont font = listBox.Rect.Width < 280 ? GUI.SmallFont : GUI.Font; GUITextBlock textBlock = new GUITextBlock( new Rectangle(50, 0, 0, 25), - ep.Name, + pi.itemPrefab.Name, null, null, Alignment.Left, Alignment.CenterX | Alignment.Left, "", frame); textBlock.Font = font; textBlock.Padding = new Vector4(5.0f, 0.0f, 5.0f, 0.0f); - textBlock.ToolTip = ep.Description; + textBlock.ToolTip = pi.itemPrefab.Description; - if (ep.sprite != null) + if (pi.itemPrefab.sprite != null) { - GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), ep.sprite, Alignment.CenterLeft, frame); - img.Color = ep.SpriteColor; + GUIImage img = new GUIImage(new Rectangle(0, 0, 40, 40), pi.itemPrefab.sprite, Alignment.CenterLeft, frame); + img.Color = pi.itemPrefab.SpriteColor; img.Scale = Math.Min(Math.Min(40.0f / img.SourceRect.Width, 40.0f / img.SourceRect.Height), 1.0f); } textBlock = new GUITextBlock( - new Rectangle(width - 80, 0, 80, 25), - ep.Price.ToString(), + new Rectangle(width - 160, 0, 80, 25), + pi.itemPrefab.Price.ToString(), null, null, Alignment.TopLeft, Alignment.TopLeft, "", frame); textBlock.Font = font; - textBlock.ToolTip = ep.Description; + textBlock.ToolTip = pi.itemPrefab.Description; + + //If its the store menu, quantity will always be 0 + if (pi.quantity > 0) + { + var amountInput = new GUINumberInput(new Rectangle(width - 80, 0, 50, 40), "", GUINumberInput.NumberType.Int, frame); + amountInput.MinValueInt = 0; + amountInput.MaxValueInt = 1000; + amountInput.UserData = pi; + amountInput.IntValue = pi.quantity; + amountInput.OnValueChanged += (numberInput) => + { + PurchasedItem purchasedItem = numberInput.UserData as PurchasedItem; + + //Attempting to buy + if (numberInput.IntValue > purchasedItem.quantity) + { + int quantity = numberInput.IntValue - purchasedItem.quantity; + //Cap the numberbox based on the amount we can afford. + quantity = Math.Max((quantity * (purchasedItem.itemPrefab.Price / Campaign.Money)), quantity); + for (int i = 0; i < quantity; i++) + { + BuyItem(numberInput, purchasedItem); + } + numberInput.IntValue = purchasedItem.quantity; + } + //Attempting to sell + else + { + int quantity = purchasedItem.quantity - numberInput.IntValue; + for (int i = 0; i < quantity; i++) + { + SellItem(numberInput, purchasedItem); + } + } + }; + } } private bool BuyItem(GUIComponent component, object obj) { - ItemPrefab prefab = obj as ItemPrefab; - if (prefab == null) return false; + PurchasedItem pi = obj as PurchasedItem; + if (pi == null || pi.itemPrefab == null) return false; if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign)) { return false; } - if (prefab.Price > campaign.Money) return false; + if (pi.itemPrefab.Price > campaign.Money) return false; - campaign.CargoManager.PurchaseItem(prefab); + campaign.CargoManager.PurchaseItem(pi.itemPrefab, 1); GameMain.Client?.SendCampaignState(); return false; @@ -274,15 +310,15 @@ namespace Barotrauma private bool SellItem(GUIComponent component, object obj) { - ItemPrefab prefab = obj as ItemPrefab; - if (prefab == null) return false; + PurchasedItem pi = obj as PurchasedItem; + if (pi == null || pi.itemPrefab == null) return false; if (GameMain.Client != null && !GameMain.Client.HasPermission(Networking.ClientPermissions.ManageCampaign)) { return false; } - campaign.CargoManager.SellItem(prefab); + campaign.CargoManager.SellItem(pi.itemPrefab,1); GameMain.Client?.SendCampaignState(); return false; @@ -291,10 +327,12 @@ namespace Barotrauma private void RefreshItemTab() { selectedItemList.ClearChildren(); - foreach (ItemPrefab ip in campaign.CargoManager.PurchasedItems) + foreach (PurchasedItem pi in campaign.CargoManager.PurchasedItems) { - CreateItemFrame(ip, selectedItemList, selectedItemList.Rect.Width); - } + CreateItemFrame(pi, selectedItemList, selectedItemList.Rect.Width); + } + selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name)); + selectedItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Category.CompareTo((y.UserData as PurchasedItem).itemPrefab.Category)); selectedItemList.UpdateScrollBarSize(); } @@ -314,16 +352,16 @@ namespace Barotrauma storeItemList.ClearChildren(); MapEntityCategory category = (MapEntityCategory)selection; - var items = MapEntityPrefab.List.FindAll(ep => ep.Price > 0.0f && ep.Category.HasFlag(category)); + var items = MapEntityPrefab.List.FindAll(ep => ep.Price > 0.0f && ep.Category.HasFlag(category) && ep is ItemPrefab); int width = storeItemList.Rect.Width; - foreach (MapEntityPrefab ep in items) + foreach (ItemPrefab ep in items) { - CreateItemFrame(ep, storeItemList, width); + CreateItemFrame(new PurchasedItem((ItemPrefab)ep,0), storeItemList, width); } - storeItemList.children.Sort((x, y) => (x.UserData as MapEntityPrefab).Name.CompareTo((y.UserData as MapEntityPrefab).Name)); + storeItemList.children.Sort((x, y) => (x.UserData as PurchasedItem).itemPrefab.Name.CompareTo((y.UserData as PurchasedItem).itemPrefab.Name)); foreach (GUIComponent child in button.Parent.children) { diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs b/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs index 580321792..24b1c9c03 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSession/CargoManager.cs @@ -6,26 +6,38 @@ using System.Linq; namespace Barotrauma { + class PurchasedItem + { + public ItemPrefab itemPrefab; + public int quantity; + + public PurchasedItem(ItemPrefab itemPrefab, int quantity) + { + this.itemPrefab = itemPrefab; + this.quantity = quantity; + } + } + class CargoManager { - private readonly List purchasedItems; + private readonly List purchasedItems; private readonly CampaignMode campaign; public Action OnItemsChanged; - public List PurchasedItems + public List PurchasedItems { get { return purchasedItems; } } public CargoManager(CampaignMode campaign) { - purchasedItems = new List(); + purchasedItems = new List(); this.campaign = campaign; } - public void SetPurchasedItems(List items) + public void SetPurchasedItems(List items) { purchasedItems.Clear(); purchasedItems.AddRange(items); @@ -33,25 +45,44 @@ namespace Barotrauma OnItemsChanged?.Invoke(); } - public void PurchaseItem(ItemPrefab item) + public void PurchaseItem(ItemPrefab item, int Quantity = 1) { - campaign.Money -= item.Price; - purchasedItems.Add(item); + PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item); + + if(purchasedItem != null && Quantity == 1) + { + campaign.Money -= item.Price; + purchasedItem.quantity += 1; + } + else + { + campaign.Money -= (item.Price * Quantity); + purchasedItem = new PurchasedItem(item, Quantity); + purchasedItems.Add(purchasedItem); + } OnItemsChanged?.Invoke(); } - public void SellItem(ItemPrefab item) + public void SellItem(ItemPrefab item, int quantity = 1) { - campaign.Money += item.Price; - purchasedItems.Remove(item); + campaign.Money += (item.Price * quantity); + PurchasedItem purchasedItem = PurchasedItems.Find(pi => pi.itemPrefab == item); + if (purchasedItem != null && purchasedItem.quantity - quantity > 0) + { + purchasedItem.quantity -= quantity; + } + else + { + PurchasedItems.Remove(purchasedItem); + } OnItemsChanged?.Invoke(); } public int GetTotalItemCost() { - return purchasedItems.Sum(i => i.Price); + return purchasedItems.Sum(i => (i.itemPrefab.Price * i.quantity)); } public void CreateItems() @@ -60,7 +91,7 @@ namespace Barotrauma OnItemsChanged?.Invoke(); } - public static void CreateItems(List itemsToSpawn) + public static void CreateItems(List itemsToSpawn) { WayPoint wp = WayPoint.GetRandom(SpawnType.Cargo, null, Submarine.MainSub); @@ -79,24 +110,24 @@ namespace Barotrauma } Dictionary availableContainers = new Dictionary(); - foreach (ItemPrefab prefab in itemsToSpawn) + foreach (PurchasedItem Pi in itemsToSpawn) { Vector2 position = new Vector2( Rand.Range(cargoRoom.Rect.X + 20, cargoRoom.Rect.Right - 20), - cargoRoom.Rect.Y - cargoRoom.Rect.Height + prefab.Size.Y / 2); + cargoRoom.Rect.Y - cargoRoom.Rect.Height + Pi.itemPrefab.Size.Y / 2); ItemContainer itemContainer = null; - if (!string.IsNullOrEmpty(prefab.CargoContainerName)) + if (!string.IsNullOrEmpty(Pi.itemPrefab.CargoContainerName)) { itemContainer = availableContainers.Keys.ToList().Find(ac => - ac.Item.Prefab.NameMatches(prefab.CargoContainerName) || - ac.Item.Prefab.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant())); + ac.Item.Prefab.NameMatches(Pi.itemPrefab.CargoContainerName) || + ac.Item.Prefab.Tags.Contains(Pi.itemPrefab.CargoContainerName.ToLowerInvariant())); if (itemContainer == null) { var containerPrefab = MapEntityPrefab.List.Find(ep => - ep.NameMatches(prefab.CargoContainerName) || - (ep.Tags != null && ep.Tags.Contains(prefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab; + ep.NameMatches(Pi.itemPrefab.CargoContainerName) || + (ep.Tags != null && ep.Tags.Contains(Pi.itemPrefab.CargoContainerName.ToLowerInvariant()))) as ItemPrefab; if (containerPrefab == null) { @@ -118,41 +149,42 @@ namespace Barotrauma } } } - - if (itemContainer == null) - { - //no container, place at the waypoint - if (GameMain.Server != null) - { - Entity.Spawner.AddToSpawnQueue(prefab, position, wp.Submarine); - } - else - { - new Item(prefab, position, wp.Submarine); - } - } - else - { - //place in the container - if (GameMain.Server != null) - { - Entity.Spawner.AddToSpawnQueue(prefab, itemContainer.Inventory); - } - else - { - var item = new Item(prefab, position, wp.Submarine); - itemContainer.Inventory.TryPutItem(item, null); - } - - //reduce the number of available slots in the container - availableContainers[itemContainer]--; - if (availableContainers[itemContainer] <= 0) - { - availableContainers.Remove(itemContainer); - } + for (int i = 0; i < Pi.quantity; i++) + { + if (itemContainer == null) + { + //no container, place at the waypoint + if (GameMain.Server != null) + { + Entity.Spawner.AddToSpawnQueue(Pi.itemPrefab, position, wp.Submarine); + } + else + { + new Item(Pi.itemPrefab, position, wp.Submarine); + } + } + else + { + //place in the container + if (GameMain.Server != null) + { + Entity.Spawner.AddToSpawnQueue(Pi.itemPrefab, itemContainer.Inventory); + } + else + { + var item = new Item(Pi.itemPrefab, position, wp.Submarine); + itemContainer.Inventory.TryPutItem(item, null); + } + + //reduce the number of available slots in the container + availableContainers[itemContainer]--; + if (availableContainers[itemContainer] <= 0) + { + availableContainers.Remove(itemContainer); + } + } } } - itemsToSpawn.Clear(); } } diff --git a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiPlayerCampaign.cs b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiPlayerCampaign.cs index 54155e44a..35cfdea93 100644 --- a/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiPlayerCampaign.cs +++ b/Barotrauma/BarotraumaShared/Source/GameSession/GameModes/MultiPlayerCampaign.cs @@ -194,9 +194,10 @@ namespace Barotrauma msg.Write(Money); msg.Write((UInt16)CargoManager.PurchasedItems.Count); - foreach (ItemPrefab ip in CargoManager.PurchasedItems) + foreach (PurchasedItem pi in CargoManager.PurchasedItems) { - msg.Write((UInt16)MapEntityPrefab.List.IndexOf(ip)); + msg.Write((UInt16)MapEntityPrefab.List.IndexOf(pi.itemPrefab)); + msg.Write((UInt16)pi.quantity); } } @@ -205,11 +206,12 @@ namespace Barotrauma UInt16 selectedLocIndex = msg.ReadUInt16(); UInt16 purchasedItemCount = msg.ReadUInt16(); - List purchasedItems = new List(); + List purchasedItems = new List(); for (int i = 0; i < purchasedItemCount; i++) { UInt16 itemPrefabIndex = msg.ReadUInt16(); - purchasedItems.Add(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab); + UInt16 itemQuantity = msg.ReadUInt16(); + purchasedItems.Add(new PurchasedItem(MapEntityPrefab.List[itemPrefabIndex] as ItemPrefab, itemQuantity)); } if (!sender.HasPermission(ClientPermissions.ManageCampaign)) @@ -220,15 +222,15 @@ namespace Barotrauma Map.SelectLocation(selectedLocIndex == UInt16.MaxValue ? -1 : selectedLocIndex); - List currentItems = new List(CargoManager.PurchasedItems); - foreach (ItemPrefab ip in currentItems) + List currentItems = new List(CargoManager.PurchasedItems); + foreach (PurchasedItem pi in currentItems) { - CargoManager.SellItem(ip); + CargoManager.SellItem(pi.itemPrefab, pi.quantity); } - foreach (ItemPrefab ip in purchasedItems) + foreach (PurchasedItem pi in purchasedItems) { - CargoManager.PurchaseItem(ip); + CargoManager.PurchaseItem(pi.itemPrefab, pi.quantity); } } } diff --git a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs index a0da30a20..6cd095e1a 100644 --- a/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs +++ b/Barotrauma/BarotraumaShared/Source/Networking/GameServer.cs @@ -1334,13 +1334,10 @@ namespace Barotrauma.Networking { if (sub == null) continue; - List spawnList = new List(); + List spawnList = new List(); foreach (KeyValuePair kvp in extraCargo) { - for (int i = 0; i < kvp.Value; i++) - { - spawnList.Add(kvp.Key); - } + spawnList.Add(new PurchasedItem(kvp.Key, kvp.Value)); } CargoManager.CreateItems(spawnList);