Inventory.cs 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330
  1. using System.Collections.Generic;
  2. using System.Collections;
  3. using UnityEngine;
  4. using Random = UnityEngine.Random;
  5. namespace HQFPSWeapons
  6. {
  7. public class Inventory : LivingEntityComponent
  8. {
  9. public Message ContainerChanged = new Message();
  10. public List<ItemContainer> Containers
  11. {
  12. get
  13. {
  14. if(m_AllContainers == null)
  15. InitiateContainers();
  16. return m_AllContainers;
  17. }
  18. }
  19. [BHeader("Storage")]
  20. [SerializeField]
  21. private ContainerGenerator[] m_InitialContainers = null;
  22. [BHeader("Item Drop")]
  23. [SerializeField]
  24. private bool m_DropItemsOnDeath = true;
  25. [SerializeField]
  26. private SoundPlayer m_DropSounds = null;
  27. [Space]
  28. [SerializeField]
  29. private Vector3 m_DropOffset = new Vector3(0f, 0f, 0.8f);
  30. [SerializeField]
  31. private float m_DropAngularFactor = 150f;
  32. [SerializeField]
  33. private float m_DropSpeed = 8f;
  34. [SerializeField]
  35. private LayerMask m_WallsLayer = new LayerMask();
  36. private List<ItemContainer> m_SavableContainers;
  37. private List<ItemContainer> m_AllContainers;
  38. public void AddContainer(ItemContainer itemContainer, bool add)
  39. {
  40. if(add && !Containers.Contains(itemContainer))
  41. {
  42. Containers.Add(itemContainer);
  43. AddListeners(itemContainer, true);
  44. }
  45. else if(!add && Containers.Contains(itemContainer))
  46. {
  47. Containers.Remove(itemContainer);
  48. AddListeners(itemContainer, false);
  49. }
  50. }
  51. public bool HasContainerWithFlags(ItemContainerFlags flags)
  52. {
  53. for(int i = 0;i < Containers.Count;i ++)
  54. if(flags.HasFlag(Containers[i].Flag))
  55. return true;
  56. return false;
  57. }
  58. public ItemContainer GetContainerWithFlags(ItemContainerFlags flags)
  59. {
  60. for(int i = 0;i < Containers.Count;i ++)
  61. if(flags.HasFlag(Containers[i].Flag))
  62. return Containers[i];
  63. return null;
  64. }
  65. public ItemContainer GetContainerWithName(string name)
  66. {
  67. for(int i = 0;i < Containers.Count;i ++)
  68. if(Containers[i].Name == name)
  69. return Containers[i];
  70. return null;
  71. }
  72. public bool AddItem(SaveableItem item, ItemContainerFlags flags)
  73. {
  74. for(int i = 0;i < Containers.Count;i ++)
  75. {
  76. if(flags.HasFlag(Containers[i].Flag))
  77. {
  78. bool added = Containers[i].AddItem(item);
  79. if(added)
  80. return true;
  81. }
  82. }
  83. return false;
  84. }
  85. /// <summary>
  86. /// </summary>
  87. public int AddItem(string itemName, int amountToAdd, ItemContainerFlags flags)
  88. {
  89. int addedInTotal = 0;
  90. for(int i = 0;i < Containers.Count;i ++)
  91. {
  92. if(flags.HasFlag(m_AllContainers[i].Flag))
  93. {
  94. int addedNow = Containers[i].AddItem(itemName, amountToAdd);
  95. addedInTotal += addedNow;
  96. if(addedNow == addedInTotal)
  97. return addedInTotal;
  98. }
  99. }
  100. return addedInTotal;
  101. }
  102. public bool RemoveItem(SaveableItem item)
  103. {
  104. for(int i = 0;i < Containers.Count;i ++)
  105. {
  106. if(m_AllContainers[i].RemoveItem(item))
  107. return true;
  108. }
  109. return false;
  110. }
  111. /// <summary>
  112. /// </summary>
  113. public int RemoveItems(string itemName, int amountToRemove, ItemContainerFlags flags)
  114. {
  115. int removedInTotal = 0;
  116. for(int i = 0;i < Containers.Count;i ++)
  117. {
  118. if(flags.HasFlag(Containers[i].Flag))
  119. {
  120. int removedNow = Containers[i].RemoveItem(itemName, amountToRemove);
  121. removedInTotal += removedNow;
  122. if (removedInTotal == amountToRemove)
  123. break;
  124. }
  125. }
  126. return removedInTotal;
  127. }
  128. /// <summary>
  129. /// Counts all the items with name itemName, from all containers.
  130. /// </summary>
  131. public int GetItemCount(string itemName)
  132. {
  133. int count = 0;
  134. for(int i = 0;i < Containers.Count;i ++)
  135. count += Containers[i].GetItemCount(itemName);
  136. return count;
  137. }
  138. public ItemSlot GetItemSlot(SaveableItem item)
  139. {
  140. foreach (var container in m_SavableContainers)
  141. {
  142. foreach (ItemSlot slot in container)
  143. {
  144. if (slot.Item == item)
  145. return slot;
  146. }
  147. }
  148. return null;
  149. }
  150. public bool TryDropItem(SaveableItem item, bool tryRemoveFromContainers = false)
  151. {
  152. bool canBeDropped = item != null && item.Data.WorldObject != null && (!tryRemoveFromContainers || RemoveItem(item));
  153. if(canBeDropped)
  154. {
  155. Player player = Entity as Player;
  156. float crouchHeightDrop = 1f;
  157. if (player != null)
  158. crouchHeightDrop = 1f;
  159. StartCoroutine(C_Drop(item, crouchHeightDrop));
  160. return true;
  161. }
  162. return false;
  163. }
  164. private IEnumerator C_Drop(SaveableItem item, float heightDropMultiplier)
  165. {
  166. if (item == null)
  167. yield return null;
  168. bool nearWall = false;
  169. Vector3 dropPosition;
  170. Quaternion dropRotation;
  171. if (Physics.Raycast(transform.position, transform.InverseTransformDirection(Vector3.forward), m_DropOffset.z, m_WallsLayer))
  172. {
  173. dropPosition = transform.position + transform.TransformVector(new Vector3(0f, m_DropOffset.y * heightDropMultiplier, -0.2f));
  174. dropRotation = Quaternion.LookRotation(Entity.LookDirection.Get());
  175. nearWall = true;
  176. }
  177. else
  178. {
  179. dropPosition = transform.position + transform.TransformVector(new Vector3(m_DropOffset.x, m_DropOffset.y * heightDropMultiplier, m_DropOffset.z));
  180. dropRotation = Random.rotationUniform;
  181. }
  182. GameObject droppedItem = Instantiate(item.Data.WorldObject, dropPosition, dropRotation) as GameObject;
  183. var rigidbody = droppedItem.GetComponent<Rigidbody>();
  184. var collider = droppedItem.GetComponent<Collider>();
  185. if (rigidbody != null)
  186. {
  187. Physics.IgnoreCollision(GetComponent<Collider>(), collider);
  188. rigidbody.isKinematic = false;
  189. if (rigidbody != null && !nearWall)
  190. {
  191. rigidbody.AddTorque(Random.rotation.eulerAngles * m_DropAngularFactor);
  192. rigidbody.AddForce(Entity.LookDirection.Get() * m_DropSpeed, ForceMode.VelocityChange);
  193. }
  194. }
  195. m_DropSounds.Play2D(ItemSelection.Method.RandomExcludeLast);
  196. var pickup = droppedItem.GetComponent<ItemPickup>();
  197. if (pickup != null)
  198. pickup.SetItem(item);
  199. }
  200. private void Awake()
  201. {
  202. if(ItemDatabase.Default == null)
  203. {
  204. Debug.LogError("No ItemDatabase found, this storage component will be disabled!", this);
  205. enabled = false;
  206. return;
  207. }
  208. Entity.Death.AddListener(OnEntityDeath);
  209. InitiateContainers();
  210. }
  211. private void InitiateContainers()
  212. {
  213. m_SavableContainers = new List<ItemContainer>();
  214. for (int i = 0; i < m_InitialContainers.Length; i++)
  215. {
  216. var container = m_InitialContainers[i].GenerateContainer(transform);
  217. m_SavableContainers.Add(container);
  218. AddListeners(container, true);
  219. }
  220. m_AllContainers = new List<ItemContainer>(m_SavableContainers);
  221. }
  222. private void AddListeners(ItemContainer container, bool add)
  223. {
  224. if (add)
  225. container.Changed.AddListener(OnContainerChanged);
  226. else
  227. container.Changed.RemoveListener(OnContainerChanged);
  228. }
  229. private void OnContainerChanged(ItemSlot slot)
  230. {
  231. try
  232. {
  233. ContainerChanged.Send();
  234. }
  235. catch {
  236. };
  237. }
  238. private void OnEntityDeath()
  239. {
  240. if(m_DropItemsOnDeath)
  241. {
  242. for(int i = 0; i < m_AllContainers.Count; i ++)
  243. {
  244. for(int j = 0; j < m_AllContainers[i].Slots.Length; j ++)
  245. {
  246. var slot = m_AllContainers[i].Slots[j];
  247. if(slot.Item)
  248. {
  249. TryDropItem(slot.Item);
  250. slot.SetItem(null);
  251. }
  252. }
  253. }
  254. }
  255. }
  256. }
  257. public class NestedContainer
  258. {
  259. public ItemContainer Container;
  260. public ItemSlot Slot;
  261. }
  262. }