InventoryBase.cs 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Assets.HeroEditor4D.Common.Scripts.Common;
  5. using Assets.HeroEditor4D.InventorySystem.Scripts.Data;
  6. using Assets.HeroEditor4D.InventorySystem.Scripts.Enums;
  7. using Assets.HeroEditor4D.InventorySystem.Scripts.Elements;
  8. using UnityEngine;
  9. using UnityEngine.UI;
  10. namespace Assets.HeroEditor4D.InventorySystem.Scripts
  11. {
  12. /// <summary>
  13. /// High-level inventory interface.
  14. /// </summary>
  15. public class InventoryBase : ItemWorkspace
  16. {
  17. public Equipment Equipment;
  18. public ScrollInventory PlayerInventory;
  19. public ScrollInventory Materials;
  20. public Button EquipButton;
  21. public Button RemoveButton;
  22. public Button CraftButton;
  23. public Button LearnButton;
  24. public Button UseButton;
  25. public Button AssembleButton;
  26. public AudioClip EquipSound;
  27. public AudioClip CraftSound;
  28. public AudioClip UseSound;
  29. public AudioSource AudioSource;
  30. public bool InitializeExample;
  31. // These callbacks can be used outside;
  32. public Action<Item> OnRefresh;
  33. public Action<Item> OnEquip;
  34. public Func<Item, bool> CanEquip = i => true;
  35. public void Awake()
  36. {
  37. ItemCollection.Active = ItemCollection;
  38. }
  39. public void Start()
  40. {
  41. if (InitializeExample)
  42. {
  43. TestInitialize();
  44. }
  45. }
  46. /// <summary>
  47. /// Initialize owned items (just for example).
  48. /// </summary>
  49. public void TestInitialize()
  50. {
  51. var inventory = ItemCollection.Active.Items.Select(i => new Item(i.Id)).ToList(); // inventory.Clear();
  52. var equipped = new List<Item>();
  53. Initialize(ref inventory, ref equipped, 6, null);
  54. }
  55. public void Initialize(ref List<Item> inventory, ref List<Item> equipped, int bagSize, Action onRefresh)
  56. {
  57. RegisterCallbacks();
  58. PlayerInventory.Initialize(ref inventory);
  59. Equipment.SetBagSize(bagSize);
  60. Equipment.Initialize(ref equipped);
  61. Equipment.OnRefresh = onRefresh;
  62. if (!Equipment.SelectAny() && !PlayerInventory.SelectAny())
  63. {
  64. ItemInfo.Reset();
  65. }
  66. }
  67. public void RegisterCallbacks()
  68. {
  69. InventoryItem.OnLeftClick = SelectItem;
  70. InventoryItem.OnRightClick = InventoryItem.OnDoubleClick = QuickAction;
  71. }
  72. private void QuickAction(Item item)
  73. {
  74. SelectItem(item);
  75. if (Equipment.Items.Contains(item))
  76. {
  77. Remove();
  78. }
  79. else if (CanEquipSelectedItem())
  80. {
  81. Equip();
  82. }
  83. }
  84. public void SelectItem(Item item)
  85. {
  86. SelectedItem = item;
  87. ItemInfo.Initialize(SelectedItem, SelectedItem.Params.Price);
  88. Refresh();
  89. }
  90. public void Equip()
  91. {
  92. if (!CanEquip(SelectedItem)) return;
  93. var equipped = SelectedItem.IsFirearm
  94. ? Equipment.Items.Where(i => i.IsFirearm).ToList()
  95. : Equipment.Items.Where(i => i.Params.Type == SelectedItem.Params.Type && !i.IsFirearm).ToList();
  96. if (equipped.Any())
  97. {
  98. AutoRemove(equipped, Equipment.Slots.Count(i => i.Supports(SelectedItem)));
  99. }
  100. if (SelectedItem.IsTwoHanded) AutoRemove(Equipment.Items.Where(i => i.IsShield).ToList());
  101. if (SelectedItem.IsShield) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsTwoHanded).ToList());
  102. if (SelectedItem.IsFirearm) AutoRemove(Equipment.Items.Where(i => i.IsShield).ToList());
  103. if (SelectedItem.IsFirearm) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsTwoHanded).ToList());
  104. if (SelectedItem.IsTwoHanded || SelectedItem.IsShield) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsFirearm).ToList());
  105. MoveItem(SelectedItem, PlayerInventory, Equipment);
  106. AudioSource.PlayOneShot(EquipSound, SfxVolume);
  107. OnEquip?.Invoke(SelectedItem);
  108. }
  109. public void Remove()
  110. {
  111. MoveItem(SelectedItem, Equipment, PlayerInventory);
  112. SelectItem(SelectedItem);
  113. AudioSource.PlayOneShot(EquipSound, SfxVolume);
  114. }
  115. public void Craft()
  116. {
  117. var materials = MaterialList;
  118. if (CanCraft(materials))
  119. {
  120. materials.ForEach(i => PlayerInventory.Items.Single(j => j.Hash == i.Hash).Count -= i.Count);
  121. PlayerInventory.Items.RemoveAll(i => i.Count == 0);
  122. var itemId = SelectedItem.Params.FindProperty(PropertyId.Craft).Value;
  123. var existed = PlayerInventory.Items.SingleOrDefault(i => i.Id == itemId && i.Modifier == null);
  124. if (existed == null)
  125. {
  126. PlayerInventory.Items.Add(new Item(itemId));
  127. }
  128. else
  129. {
  130. existed.Count++;
  131. }
  132. PlayerInventory.Refresh(SelectedItem);
  133. CraftButton.interactable = CanCraft(materials);
  134. AudioSource.PlayOneShot(CraftSound, SfxVolume);
  135. }
  136. else
  137. {
  138. Debug.Log("No materials.");
  139. }
  140. }
  141. public void Learn()
  142. {
  143. // Implement your logic here!
  144. }
  145. public void Use()
  146. {
  147. Use(UseSound);
  148. }
  149. public void Use(AudioClip sound)
  150. {
  151. if (SelectedItem.Count == 1)
  152. {
  153. PlayerInventory.Items.Remove(SelectedItem);
  154. SelectedItem = PlayerInventory.Items.FirstOrDefault();
  155. if (SelectedItem == null)
  156. {
  157. PlayerInventory.Refresh(null);
  158. SelectedItem = Equipment.Items.FirstOrDefault();
  159. if (SelectedItem != null)
  160. {
  161. Equipment.Refresh(SelectedItem);
  162. }
  163. }
  164. else
  165. {
  166. PlayerInventory.Refresh(SelectedItem);
  167. }
  168. }
  169. else
  170. {
  171. SelectedItem.Count--;
  172. PlayerInventory.Refresh(SelectedItem);
  173. }
  174. Equipment.OnRefresh?.Invoke();
  175. if (sound != null)
  176. {
  177. AudioSource.PlayOneShot(sound, SfxVolume);
  178. }
  179. }
  180. public Item Assemble()
  181. {
  182. if (SelectedItem != null && SelectedItem.Params.Type == ItemType.Fragment && SelectedItem.Count >= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt)
  183. {
  184. SelectedItem.Count -= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt;
  185. var crafted = new Item(SelectedItem.Params.FindProperty(PropertyId.Craft).Value);
  186. var existed = PlayerInventory.Items.SingleOrDefault(i => i.Hash == crafted.Hash);
  187. if (existed == null)
  188. {
  189. PlayerInventory.Items.Add(crafted);
  190. }
  191. else
  192. {
  193. existed.Count++;
  194. }
  195. if (SelectedItem.Count == 0)
  196. {
  197. PlayerInventory.Items.Remove(SelectedItem);
  198. SelectedItem = crafted;
  199. }
  200. PlayerInventory.Refresh(SelectedItem);
  201. return crafted;
  202. }
  203. return null;
  204. }
  205. public override void Refresh()
  206. {
  207. if (SelectedItem == null)
  208. {
  209. ItemInfo.Reset();
  210. EquipButton.SetActive(false);
  211. RemoveButton.SetActive(false);
  212. }
  213. else
  214. {
  215. var equipped = Equipment.Items.Contains(SelectedItem);
  216. EquipButton.SetActive(!equipped && CanEquipSelectedItem());
  217. RemoveButton.SetActive(equipped);
  218. }
  219. UseButton.SetActive(SelectedItem != null && CanUse());
  220. AssembleButton.SetActive(SelectedItem != null && SelectedItem.Params.Type == ItemType.Fragment && SelectedItem.Count >= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt);
  221. var receipt = SelectedItem != null && SelectedItem.Params.Type == ItemType.Recipe;
  222. if (CraftButton != null) CraftButton.SetActive(false);
  223. if (LearnButton != null) LearnButton.SetActive(false);
  224. if (receipt)
  225. {
  226. if (LearnButton == null)
  227. {
  228. var materialSelected = !PlayerInventory.Items.Contains(SelectedItem) && !Equipment.Items.Contains(SelectedItem);
  229. CraftButton.SetActive(true);
  230. Materials.SetActive(materialSelected);
  231. Equipment.Scheme.SetActive(!materialSelected);
  232. var materials = MaterialList;
  233. Materials.Initialize(ref materials);
  234. }
  235. else
  236. {
  237. LearnButton.SetActive(true);
  238. }
  239. }
  240. OnRefresh?.Invoke(SelectedItem);
  241. }
  242. private List<Item> MaterialList => SelectedItem.Params.FindProperty(PropertyId.Materials).Value.Split(',').Select(i => i.Split(':')).Select(i => new Item(i[0], int.Parse(i[1]))).ToList();
  243. private bool CanEquipSelectedItem()
  244. {
  245. return PlayerInventory.Items.Contains(SelectedItem) && Equipment.Slots.Any(i => i.Supports(SelectedItem));
  246. }
  247. private bool CanUse()
  248. {
  249. switch (SelectedItem.Params.Type)
  250. {
  251. case ItemType.Container:
  252. case ItemType.Booster:
  253. case ItemType.Coupon:
  254. return true;
  255. default:
  256. return false;
  257. }
  258. }
  259. private bool CanCraft(List<Item> materials)
  260. {
  261. return materials.All(i => PlayerInventory.Items.Any(j => j.Hash == i.Hash && j.Count >= i.Count));
  262. }
  263. /// <summary>
  264. /// Automatically removes items if target slot is busy.
  265. /// </summary>
  266. private void AutoRemove(List<Item> items, int max = 1)
  267. {
  268. long sum = 0;
  269. foreach (var p in items)
  270. {
  271. sum += p.Count;
  272. }
  273. if (sum == max)
  274. {
  275. MoveItemSilent(items.LastOrDefault(i => i.Id != SelectedItem.Id) ?? items.Last(), Equipment, PlayerInventory);
  276. }
  277. }
  278. }
  279. }