Files
beyond/Assets/Scripts/InvectorDerivatives/bItemManager.cs
2024-11-20 15:21:28 +01:00

2230 lines
79 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
using PixelCrushers;
using PixelCrushers.DialogueSystem;
using PixelCrushers.QuestMachine;
using UnityEngine;
using Action = System.Action;
using QuestState = PixelCrushers.QuestMachine.QuestState;
namespace Beyond
{
using Invector.vCharacterController;
using Invector.vEventSystems;
using System.Linq;
using Invector.vCharacterController.vActions;
using Invector;
using Invector.vItemManager;
[vClassHeader("ItemManager")]
public partial class bItemManager : vMonoBehaviour, IActionReceiver
{
#region Delegates
/// <summary>
/// Delegate to filter item usage
/// </summary>
/// <param name="item">target item</param>
/// <param name="validationList">Last results of filter</param>
public delegate void CanUseItemDelegate(bItem item, ref List<bool> validationList);
#endregion Delegates
#region Variables
[vHelpBox("Place a Inventory Prefab inside your Character, it will be auto-assigned when you enter Playmode." +
"\nYou can find the prefab at the Inventory/Prefabs folder", vHelpBoxAttribute.MessageType.Info)]
public bInventory inventory;
[vHelpBox(
"You can find the default ItemListData at the Inventory/ItemListData folder, or create a new list at the Invector Menu",
vHelpBoxAttribute.MessageType.Info)]
public bItemListData itemListData;
public List<ItemReference> startItems = new List<ItemReference>();
public List<EquipPoint> equipPoints;
public List<ApplyAttributeEvent> applyAttributeEvents;
public bool debugMode = false;
/// <summary>
/// Events called when item is changed or used
/// </summary>
public OnHandleItemEvent onStartItemUsage, onUseItem, onUseItemFail, onAddItem, onChangeItemAmount;
/// <summary>
/// Events called when add or remove a itemID
/// </summary>
public OnHandleItemIDEvent onAddItemID, onRemoveItemID;
public OnCollectItemEvent onCollectItem;
/// <summary>
/// Events called when item is Removed or Destroyed
/// </summary>
public OnChangeItemAmount onDestroyItem, onDropItem;
public event Action onFinishItemDestroy;
/// <summary>
/// Event called when inventory open or close
/// </summary>
public OnOpenCloseInventory onOpenCloseInventory;
/// <summary>
/// Events called in Equip or Unequip actions
/// </summary>
public OnChangeEquipmentEvent onEquipItem, onUnequipItem, onFinishEquipItem, onFinishUnequipItem;
/// <summary>
/// Event called whean <see cref="vEquipArea.isLockedToEquip"/> is changed from <see cref="CheckIsLockedToEquip"/> method;
/// </summary>
public OnSelectEquipArea onSetLockedToEquip;
/// <summary>
///Event called when save inventory items using <seealso cref="SaveItemsExample"/>
/// </summary>
public UnityEngine.Events.UnityEvent onSaveItems;
/// <summary>
///Event called when load inventory items using <seealso cref="LoadItemsExample"/>
/// </summary>
public UnityEngine.Events.UnityEvent onLoadItems;
/// <summary>
/// Equipments in EquipArea
/// </summary>
public Dictionary<bItem, bEquipment> equipments = new Dictionary<bItem, bEquipment>();
public Dictionary<GameObject, bEquipment> equipmentsObject = new Dictionary<GameObject, bEquipment>();
protected GameObject equipmentContainer;
public List<bItem> items;
internal bool inEquip;
private bool usingItem;
private float equipTimer;
private Animator animator;
protected bool inCollectItemRoutine;
protected List<ItemReference> itemsToCollect = new List<ItemReference>();
public vIAnimatorStateInfoController animatorStateInfos;
[HideInInspector] public List<bItemType> itemsFilter = new List<bItemType>() { 0 };
/// <summary>
/// Event to control when use or not an item
/// </summary>
public event CanUseItemDelegate canUseItemDelegate;
/// <summary>
/// Control if it needs to play the animation to Equip or Use the item
/// </summary>
internal bool playItemAnimation
{
get
{
return (inventory != null &&
((inventory.isOpen && inventory.playItemAnimation) || !inventory.isOpen)) &&
!temporarilyIgnoreItemAnimation;
}
}
public bool UsingItem { get => usingItem; }
/// <summary>
/// Temporarily ignore the <seealso cref="playItemAnimation"/>
/// </summary>
internal bool temporarilyIgnoreItemAnimation;
internal EquipPoint defaultLeftArmEquipPoint, defaultRightArmEquipPoint;
private GuiltGiver guiltGiver;
#endregion Variables
private IEnumerator Start()
{
vTime.useUnscaledTime = true;
// Finds a Inventory Prefab inside the character
if (!inventory)
{
inventory = transform.GetComponentInChildren<bInventory>();
}
if (!inventory)
{
if (debugMode)
{
UnityEngine.Debug.LogWarning(
"Missing Inventory prefab - You need to Drag and drop a Inventory Prefab inside the Character");
}
}
if (inventory)
{
equipmentContainer = new GameObject("Equipment Container");
equipmentContainer.transform.parent = transform;
equipmentContainer.transform.localPosition = Vector3.zero;
equipmentContainer.transform.localEulerAngles = Vector3.zero;
// Initialize all Inventory Actions
inventory.GetItemsHandler = GetItems;
inventory.GetItemsAllHandler = GetAllItems;
inventory.AddItemsHandler = AddItem;
inventory.GetAllAmount = GetAllAmount;
inventory.onEquipItem.AddListener(EquipItem);
inventory.onUnequipItem.AddListener(UnequipItem);
inventory.onDropItem.AddListener(DropItem);
inventory.onDestroyItem.AddListener(DestroyItem);
inventory.onUseItem.AddListener(UseItem);
inventory.onOpenCloseInventory.AddListener(OnOpenCloseInventory);
var melee = GetComponent<vMeleeCombatInput>();
if (melee)
{
// Check the vMeleeCombatInput to see the conditions to lock the Inventory Input
inventory.IsLockedEvent = () => { return melee.lockInventory; };
}
}
defaultLeftArmEquipPoint = equipPoints.Find(e => e.equipPointName.Equals("LeftArm"));
defaultRightArmEquipPoint = equipPoints.Find(e => e.equipPointName.Equals("RightArm"));
// Access the Animator
animator = GetComponent<Animator>();
animatorStateInfos = GetComponent<vIAnimatorStateInfoController>();
yield return new WaitForEndOfFrame();
RegisterDefaultEquipPointListeners();
// Initialize Items
items = new List<bItem>();
if (itemListData)
{
for (int i = 0; i < startItems.Count; i++)
{
AddItem(startItems[i], true, null, false);
}
}
guiltGiver = GetComponent<GuiltGiver>();
}
/// <summary>
/// Find and register all <see cref="IWeaponEquipmentListener"/> components to default equipPoints events
/// </summary>
public virtual void RegisterDefaultEquipPointListeners()
{
IWeaponEquipmentListener[] defaultEquipPointListeners = GetComponents<IWeaponEquipmentListener>();
if (defaultEquipPointListeners.Length > 0)
{
for (int i = 0; i < defaultEquipPointListeners.Length; i++)
{
if (defaultLeftArmEquipPoint != null)
{
defaultLeftArmEquipPoint.onInstantiateEquiment.AddListener(defaultEquipPointListeners[i]
.SetLeftWeapon);
}
if (defaultRightArmEquipPoint != null)
{
defaultRightArmEquipPoint.onInstantiateEquiment.AddListener(defaultEquipPointListeners[i]
.SetRightWeapon);
}
}
}
}
#region Generic Utils
/// <summary>
/// Use it to lock all the input from the vInventory
/// </summary>
/// <param name="value"></param>
public virtual void LockInventoryInput(bool value)
{
if (inventory)
{
inventory.lockInventoryInput = value;
}
}
/// <summary>
/// Use it to trigger events when Open or Close the Inventory
/// </summary>
/// <param name="value"></param>
protected virtual void OnOpenCloseInventory(bool value)
{
onOpenCloseInventory.Invoke(value);
}
/// <summary>
/// This is just an example of saving the current items <seealso cref="vSaveLoadInventory"/>
/// </summary>
public void SaveItemsExample()
{
this.SaveInventory();
}
/// <summary>
/// This is just an example of loading the saved items <seealso cref="vSaveLoadInventory"/>
/// </summary>
public void LoadItemsExample()
{
this.LoadInventory();
}
/// <summary>
/// Check vAnimatorTags from the Animator
/// </summary>
/// <param name="tag"></param>
/// <returns></returns>
public virtual bool IsAnimatorTag(string tag)
{
if (animator == null)
{
return false;
}
if (animatorStateInfos.isValid())
{
if (animatorStateInfos.animatorStateInfos.HasTag(tag))
{
return true;
}
}
return false;
}
#endregion Generic Utils
#region Check Items
/// <summary>
/// Check if Area need be locked, based in <see cref="bItem.twoHandWeapon"/>
/// </summary>
protected virtual void CheckIsLockedToEquip()
{
var rightArea = System.Array.Find(inventory.equipAreas, a => a.equipPointName.Equals("RightArm"));
var leftArea = System.Array.Find(inventory.equipAreas, a => a.equipPointName.Equals("LeftArm"));
if (rightArea == null || leftArea == null)
{
return;
}
var leftAreaLocked = false;
var rightAreaLocked = false;
leftAreaLocked = leftArea.currentEquippedItem && rightArea.currentEquippedItem &&
rightArea.currentEquippedItem.twoHandWeapon;
if (leftAreaLocked && leftArea.currentEquippedItem && equipments.ContainsKey(leftArea.currentEquippedItem))
{
var equipment = equipments[leftArea.currentEquippedItem];
if (equipment.gameObject.activeSelf)
{
equipment.gameObject.SetActive(false);
}
}
if (!leftAreaLocked)
{
rightAreaLocked = rightArea.currentEquippedItem && leftArea.currentEquippedItem &&
leftArea.currentEquippedItem.twoHandWeapon;
if (rightAreaLocked && rightArea.currentEquippedItem &&
equipments.ContainsKey(rightArea.currentEquippedItem))
{
var equipment = equipments[rightArea.currentEquippedItem];
if (equipment.gameObject.activeSelf)
{
equipment.gameObject.SetActive(false);
}
}
}
if (leftAreaLocked != leftArea.isLockedToEquip)
{
leftArea.isLockedToEquip = leftAreaLocked;
onSetLockedToEquip.Invoke(leftArea);
}
if (rightAreaLocked != rightArea.isLockedToEquip)
{
rightArea.isLockedToEquip = rightAreaLocked;
onSetLockedToEquip.Invoke(rightArea);
}
}
/// <summary>
/// Check if the current Item is checked with the option <seealso cref="bItem.twoHandWeapon"/>, if so, it will Unequip the opposite hand
/// </summary>
/// <param name="equipPoint"></param>
/// <param name="item"></param>
[System.Obsolete("This method will be removed in the future.\n use CheckIsLockedToEquip Method")]
protected virtual void CheckTwoHandItem(EquipPoint equipPoint, bItem item)
{
if (item == null)
{
return;
}
var opposite = equipPoints.Find(ePoint =>
ePoint.area != null && ePoint.equipPointName.Equals("LeftArm") &&
ePoint.area.currentEquippedItem != null);
if (equipPoint.equipPointName.Equals("LeftArm"))
{
opposite = equipPoints.Find(ePoint =>
ePoint.area != null && ePoint.equipPointName.Equals("RightArm") &&
ePoint.area.currentEquippedItem != null);
}
else if (!equipPoint.equipPointName.Equals("RightArm"))
{
return;
}
if (opposite != null && (item.twoHandWeapon || opposite.area.currentEquippedItem.twoHandWeapon))
{
opposite.area.RemoveCurrentItem();
}
}
/// <summary>
/// Check if the Item List contains a Item ID
/// </summary>
/// <param name="id">Item id</param>
/// <returns></returns>
public virtual bool ContainItem(int id)
{
return items.Exists(i => i.id == id);
}
/// <summary>
/// Check if the Item List contains a Item Name
/// </summary>
/// <param name="itemName">Item name</param>
/// <returns></returns>
public virtual bool ContainItem(string itemName)
{
return items.Exists(i => i.name == itemName);
}
/// <summary>
/// Check if the list contains a item with a certain amount, or more
/// </summary>
/// <param name="id">Item id</param>
/// <param name="amount">Item amount</param>
/// <returns></returns>
public virtual bool ContainItem(int id, int amount)
{
return GetAllAmount(id) >= amount;
}
/// <summary>
/// Check if the list contains a item name with certain amount, or more
/// </summary>
/// <param name="itemName">Item name</param>
/// <param name="amount">Item amount</param>
/// <returns></returns>
public virtual bool ContainItem(string itemName, int amount)
{
var item = items.Find(i => i.name == itemName && i.amount >= amount);
return item != null ? GetAllAmount(item.id) >= amount : false;
}
/// <summary>
/// Check if a EquipArea contains any item equipped
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="indexOfArea">index of equip area</param>
/// <returns></returns>
public virtual bool EquipAreaHasSomeItem(int indexOfArea)
{
var equipArea = inventory.equipAreas[indexOfArea];
return equipArea.equipSlots.Exists(slot => slot.item != null);
}
/// <summary>
/// Check if a specific Item ID is equipped on any EquipArea
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="id">Item id</param>
/// <returns></returns>
public virtual bool ItemIsInSomeEquipArea(int id)
{
if (!inventory || inventory.equipAreas.Length == 0)
{
return false;
}
for (int i = 0; i < inventory.equipAreas.Length; i++)
{
var equipArea = inventory.equipAreas[i];
if (equipArea.equipSlots.Exists(slot => slot.item.id.Equals(id)))
{
return true;
}
}
return false;
}
/// <summary>
/// Check if a specific Item Name is equipped on any EquipArea
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="itemName">Item name</param>
/// <returns></returns>
public virtual bool ItemIsInSomeEquipArea(string itemName)
{
if (!inventory || inventory.equipAreas.Length == 0)
{
return false;
}
for (int i = 0; i < inventory.equipAreas.Length; i++)
{
var equipArea = inventory.equipAreas[i];
if (equipArea.equipSlots.Exists(slot => slot.item.name.Equals(itemName)))
{
return true;
}
}
return false;
}
/// <summary>
/// Check if a specific Item ID is equipped on a specific EquipArea
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="id">Item id</param>
/// <param name="indexOfArea">index of equip area </param>
/// <returns></returns>
public virtual bool ItemIsInSpecificEquipArea(int id, int indexOfArea)
{
if (!inventory || inventory.equipAreas.Length == 0 || indexOfArea > inventory.equipAreas.Length - 1)
{
return false;
}
var equipArea = inventory.equipAreas[indexOfArea];
if (equipArea.equipSlots.Exists(slot => slot.item.id.Equals(id)))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Check if a specific Item Name is equipped on a specific EquipArea
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="itemName">Item name</param>
/// <param name="indexOfArea">index of equip area </param>
/// <returns></returns>
public virtual bool ItemIsInSpecificEquipArea(string itemName, int indexOfArea)
{
if (!inventory || inventory.equipAreas.Length == 0 || indexOfArea > inventory.equipAreas.Length - 1)
{
return false;
}
var equipArea = inventory.equipAreas[indexOfArea];
if (equipArea.equipSlots.Exists(slot => slot.item.name.Equals(itemName)))
{
return true;
}
else
{
return false;
}
}
/// <summary>
/// Check if a EquipPoint has any item equipped on it
/// <seealso cref="vItemManager.equipPoints"/>
/// </summary>
/// <param name="equipPointName">EquipPoint name</param>
/// <returns></returns>
public virtual bool EquipPointHasSomeItem(string equipPointName)
{
return equipPoints.Exists(ep =>
ep.equipPointName.Equals(equipPointName) && ep.equipmentReference != null &&
ep.equipmentReference.item != null);
}
/// <summary>
/// Check if a specific Item ID is equipped on any EquipPoint
/// <seealso cref="vItemManager.equipPoints"/>
/// </summary>
/// <param name="id">Item id</param>
/// <returns></returns>
public virtual bool ItemIsInSomeEquipPont(int id)
{
return equipPoints.Exists(ep =>
ep.equipmentReference != null && ep.equipmentReference.item != null &&
ep.equipmentReference.item.id.Equals(id));
}
/// <summary>
/// Check if a specific Item Name is equipped on any EquipPoint
/// <seealso cref="vItemManager.equipPoints"/>
/// </summary>
/// <param name="itemName">Item name</param>
/// <returns></returns>
public virtual bool ItemIsInSomeEquipPont(string itemName)
{
return equipPoints.Exists(ep =>
ep.equipmentReference != null && ep.equipmentReference.item != null &&
ep.equipmentReference.item.name.Equals(itemName));
}
/// <summary>
/// Check if a specific Item ID is equipped on specific EquipPoint
/// <seealso cref="vItemManager.equipPoints"/>
/// </summary>
/// <param name="id">Item id</param>
/// <param name="equipPointName">EquipPoint name</param>
/// <returns></returns>
public virtual bool ItemIsInSpecificEquipPoint(int id, string equipPointName)
{
return equipPoints.Exists(ep =>
ep.equipPointName.Equals(equipPointName) && ep.equipmentReference != null &&
ep.equipmentReference.item != null && ep.equipmentReference.item.id.Equals(id));
}
/// <summary>
/// Check if a specific Item Name is equipped on specific EquipPoint
/// <seealso cref="vItemManager.equipPoints"/>
/// </summary>
/// <param name="itemName">Item name</param>
/// <param name="equipPointName">EquipPoint name</param>
/// <returns></returns>
public virtual bool ItemIsInSpecificEquipPoint(string itemName, string equipPointName)
{
return equipPoints.Exists(ep =>
ep.equipPointName.Equals(equipPointName) && ep.equipmentReference != null &&
ep.equipmentReference.item != null && ep.equipmentReference.item.name.Equals(itemName));
}
#endregion Check Items
#region Get Items
/// <summary>
/// Get all item amount with the same id from your Inventory
/// </summary>
/// <param name="id"></param>
/// <returns></returns>
public virtual int GetAllAmount(int id)
{
var _items = GetItems(id);
int _amount = 0;
for (int i = 0; i < _items.Count; i++)
{
_amount += _items[i].amount;
}
return _amount;
}
/// <summary>
/// Return a list of all items that you have
/// </summary>
/// <returns></returns>
public virtual List<bItem> GetItems()
{
return items;
}
/// <summary>
/// Return a list of all items in your ItemListData
/// </summary>
/// <returns></returns>
public virtual List<bItem> GetAllItems()
{
return itemListData ? itemListData.items : null;
}
/// <summary>
/// Get a single Item with same id
/// <seealso cref="vItemManager.items"/>
/// </summary>
/// <param name="id">Item id</param>
/// <returns></returns>
public virtual bItem GetItem(int id)
{
return items.Find(i => i.id == id);
}
/// <summary>
/// Get a single Item with same name
/// <seealso cref="vItemManager.items"/>
/// </summary>
/// <param name="itemName">Item name</param>
/// <returns></returns>
public virtual bItem GetItem(string itemName)
{
return items.Find(i => i.name == itemName);
}
/// <summary>
/// Get the item from a specific equipPoint
/// </summary>
/// <param name="equipPointName">EquipPoint name</param>
/// <returns>Returns the Item (if equipped) on this EquipPoint</returns>
public virtual bItem GetItemInEquipPoint(string equipPointName)
{
var equipPoint = equipPoints.Find(ep => ep.equipPointName.Equals(equipPointName));
if (equipPoint != null && equipPoint.equipmentReference != null && equipPoint.equipmentReference.item)
{
return equipPoint.equipmentReference.item;
}
else
{
return null;
}
}
/// <summary>
/// Get All Items with same id
/// <seealso cref="vItemManager.items"/>
/// </summary>
/// <param name="id">Item id</param>
/// <returns></returns>
public virtual List<bItem> GetItems(int id)
{
var _items = items.FindAll(i => i.id == id);
return _items;
}
/// <summary>
/// Get All Items with same name
/// <seealso cref="vItemManager.items"/>
/// </summary>
/// <param name="itemName">Item Name</param>
/// <returns></returns>
public virtual List<bItem> GetItems(string itemName)
{
var _items = items.FindAll(i => i.name == itemName);
return _items;
}
/// <summary>
/// Get a list of all Items equipped in the same EquipArea
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <param name="indexOfArea">index of equip area</param>
/// <returns></returns>
public virtual List<bItem> GetItemsInEquipArea(int indexOfArea)
{
var list = new List<bItem>();
if (!inventory || inventory.equipAreas.Length == 0 || indexOfArea > inventory.equipAreas.Length - 1)
{
return list;
}
var equipArea = inventory.equipAreas[indexOfArea];
var validSlot = equipArea.ValidSlots;
for (int i = 0; i < validSlot.Count; i++)
{
if (validSlot[i].item != null)
{
list.Add(validSlot[i].item);
}
}
return list;
}
/// <summary>
/// Get a list of all Items equipped on all EquipAreas
/// <seealso cref="vInventory.equipAreas"/>
/// </summary>
/// <returns></returns>
public virtual List<bItem> GetAllItemInAllEquipAreas()
{
var list = new List<bItem>();
if (!inventory || inventory.equipAreas.Length == 0)
{
return list;
}
for (int i = 0; i < inventory.equipAreas.Length; i++)
{
var equipArea = inventory.equipAreas[i];
var validSlot = equipArea.ValidSlots;
for (int a = 0; a < validSlot.Count; a++)
{
if (validSlot[a].item != null)
{
list.Add(validSlot[a].item);
}
}
}
return list;
}
#endregion Get Items
#region Equipment Pooling
protected bEquipment EquipEquipment(bItem item, bool startActive = true)
{
if (equipments.ContainsKey(item))
{
if (!startActive)
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Disable Equipment {equipments[item].gameObject} </color>");
}
equipments[item].gameObject.SetActive(false);
}
else
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Enable Equipment {equipments[item].gameObject} </color>");
}
equipments[item].gameObject.SetActive(true);
}
return equipments[item];
}
else
{
if (item.originalObject)
{
var equipment = item.originalObject.GetComponent<bEquipment>();
if (equipment != null)
{
var equipmentClone = Instantiate(item.originalObject);
if (!startActive)
{
if (debugMode)
{
UnityEngine.Debug.Log(
$"<color=green>Instantiate and disable Equipment {equipmentClone.gameObject} </color>");
}
equipmentClone.gameObject.SetActive(false);
}
else
{
if (debugMode)
{
UnityEngine.Debug.Log(
$"<color=green>Instantiate and enable Equipment {equipmentClone.gameObject} </color>");
}
}
equipmentClone.transform.SetParent(equipmentContainer.transform);
equipmentClone.transform.localPosition = Vector3.zero;
equipmentClone.transform.localEulerAngles = Vector3.zero;
equipment = equipmentClone.GetComponent<bEquipment>();
equipments.Add(item, equipment);
equipmentsObject.Add(equipmentClone, equipment);
return equipment;
}
else
{
Debug.Log("eq is null");
}
}
}
return null;
}
protected bEquipment EquipEquipment(bItem item, Vector3 position, Quaternion rotation, Transform parent = null)
{
bEquipment equipment = EquipEquipment(item);
if (equipment)
{
if (parent)
{
equipment.transform.parent = parent;
}
equipment.transform.position = position;
equipment.transform.rotation = rotation;
equipment.OnEquip(item);
return equipment;
}
return null;
}
protected void UnequipEquipment(bItem item)
{
if (equipments.ContainsKey(item))
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=red>Disable Equipment {equipments[item].gameObject} </color>");
}
equipments[item].gameObject.SetActive(false);
equipments[item].gameObject.transform.SetParent(equipmentContainer.transform);
equipments[item].gameObject.transform.localPosition = Vector3.zero;
equipments[item].gameObject.transform.localEulerAngles = Vector3.zero;
equipments[item].equipPoint = null;
equipments[item].OnUnequip(item);
}
}
#endregion Equipment Pooling
#region Add/Equip/AutoEquip Item
public void AddItemByString(string itemName)
{
bItem newItem = itemListData.items.Find(item => item.name.Equals(itemName));
AddItem(newItem);
}
//only works with format itemId:Amount used for public events in editor
public void AddItemByID(string itemIdAndAmount)
{
var data = itemIdAndAmount.Split(':');
if (data.Length < 2)
{
return;
}
bItem newItem = itemListData.items.Find(item => item.id == Int32.Parse(data[0]));
AddItem(newItem, Int32.Parse(data[1]));
}
public void AddItemByID(int id)
{
bItem newItem = itemListData.items.Find(item => item.id == id);
AddItem(newItem);
}
public void AddItemsByID(int id, int amount)
{
bItem newItem = itemListData.items.Find(item => item.id == id);
AddItem(newItem, amount);
}
public void AddItem(bItem newItem, int amount = 1)
{
if (!newItem)
{
#if UNITY_EDITOR
Debug.Log("no item found");
#endif
return;
}
ItemReference itemReference = new ItemReference(newItem.id);
itemReference.amount = amount;
bItemType itemType = newItem.type;
itemReference.indexArea = itemType switch
{
bItemType.Swords or bItemType.Axes or bItemType.MeleeWeapon => 0,
bItemType.Quantas => 1,
bItemType.Guilts => 3,
_ => 2
};
AddItem(itemReference, true);
}
/// <summary>
/// Add a new Item Instance to the Inventory
/// </summary>
/// <param name="itemReference">Reference of the Item to be instantiate</param>
/// <param name="ignoreItemAnimation">Play the Enable/Disable animation of your item, you can assign an animation to your item in the ItemListData</param>
/// <param name="onFinish">Event called when item is created and added to inventory</param>
public virtual void AddItem(ItemReference itemReference, bool ignoreItemAnimation = false,
UnityEngine.Events.UnityAction<bItem> onFinish = null, bool showPopup = true)
{
if (itemReference != null && itemListData != null && itemListData.items.Count > 0)
{
var item = itemListData.items.Find(t => t.id.Equals(itemReference.id));
if (item)
{
var sameItems = items.FindAll(i => i.stackable && i.id == item.id && i.amount < i.maxStack);
if (sameItems.Count == 0)
{
var _item = Instantiate(item);
_item.name = _item.name.Replace("(Clone)", string.Empty);
if (itemReference.attributes != null && _item.attributes != null &&
item.attributes.Count == itemReference.attributes.Count)
{
for (int i = 0; i < _item.attributes.Count; i++)
{
itemReference.attributes[i].CopyTo(_item.attributes[i]);
}
}
_item.amount = 0;
for (int i = 0;
i < item.maxStack && _item.amount < _item.maxStack && itemReference.amount > 0;
i++)
{
_item.amount++;
itemReference.amount--;
}
//if item does not exist
items.Add(_item);
onAddItem.Invoke(_item);
onAddItemID.Invoke(_item.id);
if (showPopup)
{
CollectedItemInfo collectedItemInfo = new CollectedItemInfo();
collectedItemInfo.amount = _item.amount;
collectedItemInfo.item = _item;
DisplayCollectedItems(collectedItemInfo);
}
if (itemReference.addToEquipArea)
{
itemReference.addToEquipArea = false;
AutoEquipItem(_item, itemReference.indexArea, itemReference.autoEquip, ignoreItemAnimation);
}
if (itemReference.amount > 0) //if filled max stack, add another item->stack
{
AddItem(itemReference, onFinish: onFinish);
}
else
{
onFinish?.Invoke(_item);
}
}
else
{
//item exists
var indexOffItem = items.IndexOf(sameItems[0]);
bool changeAmount = false;
int diff = 0;
for (int i = 0;
i < items[indexOffItem].maxStack &&
items[indexOffItem].amount < items[indexOffItem].maxStack && itemReference.amount > 0;
i++)
{
//add amount of existing item up to max stack
items[indexOffItem].amount++;
itemReference.amount--;
diff++;
changeAmount = true;
}
if (showPopup)
{
CollectedItemInfo collectedItemInfo = new CollectedItemInfo();
collectedItemInfo.amount = diff;
collectedItemInfo.item = items[indexOffItem];
DisplayCollectedItems(collectedItemInfo);
}
if (changeAmount)
{
onChangeItemAmount.Invoke(items[indexOffItem]);
}
if (itemReference.amount > 0) //if filled max stack, add another item->stack
{
AddItem(itemReference, onFinish: onFinish);
}
else if (changeAmount)
{
onFinish?.Invoke(items[indexOffItem]);
}
}
}
}
inventory.UpdateInventory();
}
/// <summary>
/// Automatically equip the item to empty EquiSlot of a specific EquipArea
/// </summary>
/// <param name="item"></param>
/// <param name="indexArea">EquipArea (index) of the Inventory</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void AutoEquipItem(bItem item, int indexArea, bool autoEquip = false,
bool ignoreItemAnimation = true)
{
if (!inventory)
{
return;
}
if (inventory.equipAreas != null && inventory.equipAreas.Length > 0 &&
indexArea < inventory.equipAreas.Length)
{
var validSlot = inventory.equipAreas[indexArea].equipSlots.Find(slot =>
slot.isValid && slot.item == null && slot.itemType.Contains(item.type));
if (validSlot == null && autoEquip && inventory.equipAreas[indexArea].currentEquippedSlot &&
inventory.equipAreas[indexArea].currentEquippedSlot.item == null)
{
validSlot = inventory.equipAreas[indexArea].currentEquippedSlot;
}
if (validSlot && !inventory.equipAreas[indexArea].equipSlots.Exists(slot => slot.item == item))
{
var indexOfSlot = inventory.equipAreas[indexArea].equipSlots.IndexOf(validSlot);
if (validSlot.item != item)
{
EquipItemToEquipSlot(indexArea, indexOfSlot, item, autoEquip, ignoreItemAnimation);
}
}
}
else
{
if (debugMode)
{
UnityEngine.Debug.LogWarning("Fail to auto equip " + item.name + " on equipArea " + indexArea);
}
}
}
/// <summary>
/// Equip a specific Item to a specific EquipArea, this method is called internally by the Event from the Inventory
/// </summary>
/// <param name="equipArea"></param>
/// <param name="item"></param>
protected virtual void EquipItem(bEquipArea equipArea, bItem item)
{
CheckIsLockedToEquip();
if (!item)
{
return;
}
item.isEquiped = true;
onEquipItem.Invoke(equipArea, item);
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Start Equip {item} </color>");
}
inventory.UpdateInventory();
if (item != equipArea.currentEquippedItem)
{
if (debugMode)
{
UnityEngine.Debug.Log(
$"<color=green>Not Current Equip {item} </color>{equipArea.indexOfEquippedItem}",
equipArea.currentEquippedItem);
}
EquipEquipment(item, false);
onFinishEquipItem?.Invoke(equipArea, item);
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Finish Equip {item} </color>");
}
return;
}
else
{
UnityEngine.Debug.Log($"<color=red>equip area the same {item} </color>");
}
var equipPoint = equipPoints.Find(ep => ep.equipPointName == equipArea.equipPointName);
if (equipPoint != null && item != null && equipPoint.equipmentReference.item != item)
{
if (item.originalObject)
{
var equipment = item.originalObject.GetComponentInChildren<bEquipment>();
if (equipment != null)
{
equipPoint.area = equipArea;
StartCoroutine(EquipItemRoutine(equipPoint, item,
() => { onFinishEquipItem?.Invoke(equipArea, item); }));
}
}
}
}
/// <summary>
/// Equip Item Routine
/// </summary>
/// <param name="equipPoint"></param>
/// <param name="item"></param>
/// <returns></returns>
private IEnumerator EquipItemRoutine(EquipPoint equipPoint, bItem item, UnityEngine.Events.UnityAction onFinish)
{
LockInventoryInput(true);
//if (equipPoint != null)
//{
// CheckTwoHandItem(equipPoint, item);
//}
while (inEquip || IsAnimatorTag("IsEquipping"))
{
yield return new WaitForEndOfFrame();
}
if (!equipPoint.area.isLockedToEquip && playItemAnimation)
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Play Equip Animation {item} </color>");
}
equipTimer = item.enableDelayTime;
animator.SetBool("FlipEquip", equipPoint.equipPointName.Contains("Left"));
animator.CrossFade(item.EnableAnim, 0.25f);
}
if (!inEquip)
{
inEquip = true;
inventory.canEquip = false;
if (equipPoint != null)
{
if (item.originalObject)
{
if (equipPoint.equipmentReference != null &&
equipPoint.equipmentReference.equipedObject != null && equipPoint.equipmentReference.item)
{
UnequipEquipment(equipPoint.equipmentReference.item);
equipPoint.equipmentReference.item = null;
}
if (!equipPoint.area.isLockedToEquip && playItemAnimation &&
!string.IsNullOrEmpty(item.EnableAnim))
{
if (debugMode && equipTimer > 0)
{
UnityEngine.Debug.Log($"<color=green>In Equip delay {item} </color>");
}
while (equipTimer > 0)
{
// Debug.Log("equip timer: " + equipTimer + " " + vTime.deltaTime);
if (item == null)
{
break;
}
yield return null;
equipTimer -= vTime.deltaTime;
}
}
inEquip = false;
var point = equipPoint.handler.customHandlers.Find(p => p.name == item.customHandler);
var equipTransform = point != null ? point : equipPoint.handler.defaultHandler;
bEquipment equipedObject = EquipEquipment(item, equipTransform.position,
equipTransform.rotation, equipTransform);
if (equipPoint.area.isLockedToEquip)
{
equipedObject.gameObject.SetActive(false);
}
equipedObject.equipPoint = equipPoint;
equipPoint.equipmentReference.item = item;
equipPoint.equipmentReference.equipedObject = equipedObject.gameObject;
equipPoint.onInstantiateEquiment.Invoke(equipedObject.gameObject);
}
else if (equipPoint.equipmentReference != null &&
equipPoint.equipmentReference.equipedObject != null && equipPoint.equipmentReference.item)
{
UnequipEquipment(equipPoint.equipmentReference.item);
equipments[equipPoint.equipmentReference.item].equipPoint = null;
equipPoint.equipmentReference.item = null;
}
}
}
LockInventoryInput(false);
onFinish?.Invoke();
if (debugMode)
{
UnityEngine.Debug.Log($"<color=green>Finish Equip {item} </color>");
}
inEquip = false;
inventory.canEquip = true;
}
/// <summary>
/// Equip item to a equipArea on a specific equipSlot
/// </summary>
/// <param name="indexOfArea">Index of <seealso cref="vInventory.equipAreas"/></param>
/// <param name="indexOfSlot">Index of Slot in <seealso cref="vEquipArea"/></param>
/// <param name="item"><seealso cref="bItem"/> to Equip</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void EquipItemToEquipSlot(int indexOfArea, int indexOfSlot, bItem item, bool autoEquip = false,
bool ignoreItemAnimation = false)
{
if (!inventory)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
var area = inventory.equipAreas[indexOfArea];
if (area != null)
{
area.AddItemToEquipSlot(indexOfSlot, item, autoEquip);
}
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
/// <summary>
/// Equip or change Item to a current equipSlot from a specific equipArea
/// </summary>
/// <param name="item">Item to equip</param>
/// <param name="indexOfArea">Index of Equip area</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void EquipItemToCurrentEquipSlot(bItem item, int indexOfArea, bool ignoreItemAnimation = true)
{
if (!inventory && items.Count == 0)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
inventory.equipAreas[indexOfArea].AddCurrentItem(item);
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
#endregion Add/Equip/AutoEquip Item
#region Unequip Item
private float unequipTimer;
/// <summary>
/// Unequips a specific Item from a specific EquipArea, this method is called internally on a Event from the Inventory
/// </summary>
/// <param name="equipArea"></param>
/// <param name="item"></param>
protected virtual void UnequipItem(bEquipArea equipArea, bItem item)
{
if (!item)
{
return;
}
item.isEquiped = false;
onUnequipItem.Invoke(equipArea, item);
if (debugMode)
{
UnityEngine.Debug.Log($"<color=red>Start Unequip {item}</color>");
}
var equipPoint = equipPoints.Find(ep => ep.equipPointName == equipArea.equipPointName &&
ep.equipmentReference.item != null &&
ep.equipmentReference.item == item);
if (equipPoint != null && item != null)
{
equipPoint.onInstantiateEquiment.Invoke(null);
unequipTimer = item.disableDelayTime;
if (item.originalObject)
{
var equipment = item.originalObject.GetComponentInChildren<bEquipment>();
if (equipment != null)
{
if (!inventory.isOpen && playItemAnimation && !inEquip &&
equipPoint.equipmentReference.equipedObject.activeInHierarchy)
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=red>Play Unequip Animation {item}</color>");
}
animator.SetBool("FlipEquip", equipArea.equipPointName.Contains("Left"));
animator.CrossFade(item.DisableAnim, 0.25f);
}
StartCoroutine(UnequipItemRoutine(equipPoint, item,
() => { onFinishUnequipItem?.Invoke(equipArea, item); }));
}
}
}
else if (item != null)
{
if (debugMode)
{
UnityEngine.Debug.Log($"<color=red>Finish Unequip {item}</color>");
}
onFinishUnequipItem.Invoke(equipArea, item);
}
inventory.UpdateInventory();
CheckIsLockedToEquip();
}
/// <summary>
/// Unequips a specific Item
/// </summary>
/// <param name="item"></param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void UnequipItem(bItem item, bool ignoreItemAnimation = true)
{
var equipArea = System.Array.Find(inventory.equipAreas,
e => e.ValidSlots.Exists(s => s.item != null && s.item.id.Equals(item.id)));
if (equipArea != null)
{
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
UnequipItem(equipArea, item);
}
inventory.UpdateInventory();
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
/// <summary>
/// Unequip item of specific area and specific slot
/// </summary>
/// <param name="indexOfArea">Index of Equip Area</param>
/// <param name="indexOfSlot">Index of Slot in Equip Area</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void UnequipItemOfEquipSlot(int indexOfArea, int indexOfSlot, bool ignoreItemAnimation = true)
{
if (!inventory)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
var area = inventory.equipAreas[indexOfArea];
if (area != null)
{
area.RemoveItemOfEquipSlot(indexOfSlot);
}
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
/// <summary>
/// Unequip current equiped item of specific area
/// </summary>
/// <param name="indexOfArea">Index of Equip area</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void UnequipCurrentEquipedItem(int indexOfArea, bool ignoreItemAnimation = true)
{
if (!inventory && items.Count == 0)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
inventory.equipAreas[indexOfArea].RemoveCurrentItem();
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
private IEnumerator UnequipItemRoutine(EquipPoint equipPoint, bItem item,
UnityEngine.Events.UnityAction onFinish)
{
LockInventoryInput(true);
if (!inEquip)
{
inEquip = true;
inventory.canEquip = false;
if (equipPoint != null && equipPoint.equipmentReference != null &&
equipPoint.equipmentReference.equipedObject != null)
{
if (!inventory.isOpen && playItemAnimation)
{
if (debugMode && unequipTimer > 0)
{
UnityEngine.Debug.Log($"<color=red>In Unequip delay {item} </color>");
}
while (unequipTimer > 0 && !string.IsNullOrEmpty(item.DisableAnim))
{
unequipTimer -= vTime.deltaTime;
yield return null;
}
}
if (equipPoint != null && equipPoint.equipmentReference != null &&
equipPoint.equipmentReference.equipedObject)
{
UnequipEquipment(item);
equipPoint.equipmentReference.item = null;
}
}
inEquip = false;
inventory.canEquip = true;
}
else
{
}
if (debugMode)
{
UnityEngine.Debug.Log($"<color=red>Finish Unequip {item}</color>");
}
onFinish?.Invoke();
LockInventoryInput(false);
}
#endregion Unequip Item
#region Use Item
/// <summary>
/// Check if a item has any condition to be used
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
public bool CanUseItem(bItem item)
{
if (canUseItemDelegate != null)
{
List<bool> canUse = new List<bool>();
canUseItemDelegate.Invoke(item, ref canUse);
return !canUse.Contains(false);
}
return item.canBeUsed;
}
/// <summary>
/// Use a specific Item - Called internally on a Event from the Inventory
/// </summary>
/// <param name="item"></param>
public virtual void UseItem(bItem item)
{
if (item)
{
if (CanUseItem(item))
{
StartCoroutine(UseItemRoutine(item));
}
else
{
onUseItemFail.Invoke(item);
}
}
}
/// <summary>
/// Use Item Routine
/// </summary>
/// <param name="item"></param>
protected IEnumerator UseItemRoutine(bItem item)
{
usingItem = true;
LockInventoryInput(true);
onStartItemUsage.Invoke(item);
var canUse = CanUseItem(item);
if (canUse)
{
var time = item.enableDelayTime;
if (!inventory.isOpen && playItemAnimation && !string.IsNullOrEmpty(item.EnableAnim))
{
animator.SetBool("FlipAnimation", false);
animator.CrossFade(item.EnableAnim, 0.25f);
while (usingItem && time > 0 && canUse)
{
canUse = CanUseItem(item);
time -= vTime.deltaTime;
yield return null;
}
}
if (usingItem && canUse)
{
bool itemIsOfPopupType = item.type == bItemType.Consumable || item.type == bItemType.ConsumablesFaith || item.type == bItemType.PowerScroll ||
item.type == bItemType.Resources || item.type == bItemType.Gemstones;
//could maybe unify events on item use, so its not mixed between singletons fired and event subscriptions
if (bItemCollectionDisplay.Instance && itemIsOfPopupType && item)
{
var text = $"Used: {item.name}";
//in game
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
//in menu
if (PopupMenuController.Instance != null)
{
PopupMenuController.Instance.TryToShowPopupMesssage("Used: " + item.name);
}
}
if (item.destroyAfterUse)
{
item.amount--;
}
onUseItem.Invoke(item);
//handling item attributes here
if (item.attributes != null && item.attributes.Count > 0 && applyAttributeEvents.Count > 0 &&
item.type != bItemType.PowerScroll)
{
foreach (ApplyAttributeEvent attributeEvent in applyAttributeEvents)
{
var attributes = item.attributes.FindAll(a => a.name.Equals(attributeEvent.attribute));
var brightnessAttribute = attributes.Find(a => a.name == bItemAttributes.Brightness);
TryToGiveGuiltForEatingWrongFruit(attributes, brightnessAttribute);
foreach (bItemAttribute attribute in attributes)
{
attributeEvent.onApplyAttribute.Invoke(attribute.value);
}
}
}
if (item.destroyAfterUse && item.amount <= 0 && items.Contains(item))
{
DestroyItem(item);
}
else
{
onRemoveItemID.Invoke(item.id);
}
usingItem = false;
inventory.CheckEquipmentChanges();
}
else
{
onUseItemFail.Invoke(item);
}
}
else
{
onUseItemFail.Invoke(item);
}
LockInventoryInput(false);
inventory.UpdateInventory();
}
private void TryToGiveGuiltForEatingWrongFruit(List<bItemAttribute> attributes, bItemAttribute brightnessAttribute)
{
if (brightnessAttribute != null)
{
if (brightnessAttribute.value < 0)
{
guiltGiver.GiveGuilt();
attributes.Remove(brightnessAttribute);
}
}
}
#endregion Use Item
#region DestroyItem Item
/// <summary>
/// Destroy all amount of specific item
/// </summary>
/// <param name="item"></param>
public virtual void DestroyItem(bItem item)
{
DestroyItem(item, item.amount);
}
/// <summary>
/// Destroy a specific amount of a specific item
/// </summary>
/// <param name="item"></param>
/// <param name="amount"></param>
public virtual void DestroyItem(bItem item, int amount)
{
item.amount -= amount;
onDestroyItem.Invoke(item, amount);
if (item.amount <= 0)
{
var equipArea = System.Array.Find(inventory.equipAreas,
e => e.ValidSlots.Exists(s => s.item != null && s.item.id.Equals(item.id)));
if (equipArea != null)
{
temporarilyIgnoreItemAnimation = true;
equipArea.UnequipItem(item);
temporarilyIgnoreItemAnimation = false;
}
var _itemID = item.id;
if (items.Contains(item))
{
items.Remove(item);
}
if (equipments.ContainsKey(item))
{
var equipment = equipments[item];
if (equipment != null)
{
Destroy(equipment.gameObject);
}
equipments.Remove(item);
}
Destroy(item);
onRemoveItemID.Invoke(_itemID);
}
inventory.UpdateInventory();
onFinishItemDestroy?.Invoke();
}
/// <summary>
/// Destroy all Items from the Inventory
/// </summary>
public virtual void DestroyAllItems()
{
for (int i = items.Count - 1; i >= 0; i--)
{
DestroyItem(items[i]);
}
}
/// <summary>
/// DestroyItem current equiped item of specific EquipArea
/// </summary>
/// <param name="indexOfArea">Index of Equip Area</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void DestroyCurrentEquipedItem(int indexOfArea, bool ignoreItemAnimation = true)
{
if (!inventory && items.Count == 0)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
var item = inventory.equipAreas[indexOfArea].currentEquippedItem;
if (item)
{
DestroyItem(item, item.amount);
}
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
#endregion DestroyItem Item
#region Drop Item
/// <summary>
/// Drop all amount of specific item
/// </summary>
/// <param name="item"></param>
public virtual void DropItem(bItem item)
{
DropItem(item, item.amount);
}
/// <summary>
/// Drop a specific amount of a specific Item
/// </summary>
/// <param name="item"></param>
/// <param name="amount"></param>
public virtual void DropItem(bItem item, int amount)
{
item.amount -= amount;
if (item.dropObject != null)
{
var dropObject = Instantiate(item.dropObject, transform.position, transform.rotation);
bItemCollection collection = dropObject.GetComponent<bItemCollection>();
if (collection != null)
{
collection.items.Clear();
var itemReference = new ItemReference(item.id);
itemReference.amount = amount;
itemReference.attributes = new List<bItemAttribute>(item.attributes);
collection.items.Add(itemReference);
}
}
onDropItem.Invoke(item, amount);
if (item.amount <= 0 && items.Contains(item))
{
var equipArea = System.Array.Find(inventory.equipAreas,
e => e.ValidSlots.Exists(s => s.item != null && s.item.id.Equals(item.id)));
if (equipArea != null)
{
equipArea.UnequipItem(item);
}
items.Remove(item);
DestroyItem(item);
}
inventory.UpdateInventory();
}
/// <summary>
/// Drop all Items from the Inventory
/// </summary>
public virtual void DropAllItens()
{
List<ItemReference> itemReferences = new List<ItemReference>();
List<GameObject> dropObjects = new List<GameObject>();
///Remove All items and create Item Reference to Drop
for (int i = items.Count - 1; i >= 0; i--)
{
var item = items[i];
ItemReference itemReference = itemReferences.Find(_item => _item.id == item.id);
if (itemReference == null)
{
itemReference = new ItemReference(item.id);
itemReferences.Add(itemReference);
dropObjects.Add(item.dropObject);
}
itemReference.amount += item.amount;
DestroyItem(item);
}
///Instantiate all Item References
for (int i = 0; i < dropObjects.Count; i++)
{
var dropObjectPrefab = dropObjects[i];
ItemReference itemReference = itemReferences[i];
if (dropObjectPrefab)
{
var dropObject = Instantiate(dropObjectPrefab, transform.position, transform.rotation);
bItemCollection collection = dropObject.GetComponent<bItemCollection>();
if (!collection)
{
collection = dropObject.AddComponent<bItemCollection>();
}
if (collection != null)
{
collection.items.Clear();
collection.items.Add(itemReference);
}
}
}
}
/// <summary>
/// Drop the current equipped item from a specific EquipArea
/// </summary>
/// <param name="indexOfArea">Index of Equip Area</param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
public virtual void DropCurrentEquippedItem(int indexOfArea, bool ignoreItemAnimation = true)
{
if (!inventory && items.Count == 0)
{
return;
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = ignoreItemAnimation;
}
if (inventory.equipAreas != null && indexOfArea < inventory.equipAreas.Length)
{
var item = inventory.equipAreas[indexOfArea].currentEquippedItem;
if (item)
{
DropItem(item, item.amount);
}
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
#endregion Drop Item
#region Item Collector
/// <summary>
/// Collect a Item and display the Items collected with a delay
/// </summary>
/// <param name="itemRef">reference of target item</param>
/// <param name="onCollectDelay"></param>
/// <param name="textDelay"> delay to display Collected item, after the items have been added </param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
/// <returns></returns>
public virtual void CollectItem(ItemReference itemRef, float onCollectDelay = 0, float textDelay = 0,
bool ignoreItemAnimation = true)
{
if (!inCollectItemRoutine)
{
itemsToCollect.Add(itemRef);
StartCoroutine(CollectItemsRoutine(onCollectDelay, textDelay, ignoreItemAnimation));
}
else
{
itemsToCollect.Add(itemRef);
}
}
/// <summary>
/// Collect a List of Items and display the Items collected with a delay
/// </summary>
/// <param name="collection">List of references of target items</param>
/// <param name="onCollectDelay">Delay to add items to inventory</param>
/// <param name="textDelay"> Delay to display Collected item, after the items have been added </param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
/// <returns></returns>
public virtual void CollectItems(List<ItemReference> collection, float onCollectDelay = 0, float textDelay = 0,
bool ignoreItemAnimation = true)
{
foreach (ItemReference reference in collection)
{
CollectItem(reference, onCollectDelay, textDelay, ignoreItemAnimation);
}
}
/// <summary>
/// Coroutine to Add to inventory all items in <see cref="itemsToCollect"/>
/// </summary>
/// <param name="onCollectDelay">Delay to add items to inventory</param>
/// <param name="textDelay"> Delay to display Collected item, after the items have been added </param>
/// <param name="ignoreItemAnimation">Ignore the Enable/Disable animation of your item</param>
/// <returns></returns>
protected virtual IEnumerator CollectItemsRoutine(float onCollectDelay = 0, float textDelay = 0,
bool ignoreItemAnimation = true)
{
while (inCollectItemRoutine)
{
yield return null;
}
inCollectItemRoutine = true;
yield return new WaitForSeconds(onCollectDelay);
List<CollectedItemInfo> collectedItems = new List<CollectedItemInfo>();
for (int i = 0; i < inventory.equipAreas.Length; i++)
{
var area = inventory.equipAreas[i];
area.ignoreEquipEvents = true;
}
for (int i = 0; i < itemsToCollect.Count; i++)
{
var itemToCollect = itemsToCollect[i];
UnityEngine.Events.UnityAction<bItem> onFinish = null;
CollectedItemInfo collectedItemInfo = new CollectedItemInfo();
collectedItemInfo.amount = itemsToCollect[i].amount;
UnityEngine.Events.UnityAction<bItem> equipAction = null;
if (itemToCollect.addToEquipArea)
{
var autoEquip = itemsToCollect[i].autoEquip;
var indexOfArea = itemsToCollect[i].indexArea;
itemsToCollect[i].addToEquipArea = false;
itemsToCollect[i].autoEquip = false;
equipAction = (bItem _item) => { AutoEquipItem(_item, indexOfArea, autoEquip, true); };
}
onFinish = (bItem _item) =>
{
collectedItemInfo.item = _item;
collectedItems.Add(collectedItemInfo);
equipAction?.Invoke(_item);
};
AddItem(itemsToCollect[i].Clone(), ignoreItemAnimation, onFinish, true);
}
inCollectItemRoutine = false;
itemsToCollect.Clear();
// StartCoroutine(DisplayCollectedItems(textDelay, collectedItems.ToArray()));
List<CollectedItemInfo> autoEquipItems = new List<CollectedItemInfo>();
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = true;
}
for (int i = 0; i < inventory.equipAreas.Length; i++)
{
var area = inventory.equipAreas[i];
if (area.isLockedToEquip)
{
temporarilyIgnoreItemAnimation = true;
}
else
{
while (!ignoreItemAnimation && (inEquip || IsAnimatorTag("IsEquipping")))
{
yield return null;
}
}
area.ignoreEquipEvents = false;
area.EquipCurrentSlot();
if (area.isLockedToEquip)
{
temporarilyIgnoreItemAnimation = false;
}
}
if (ignoreItemAnimation)
{
temporarilyIgnoreItemAnimation = false;
}
}
/// <summary>
/// Show a list of collected item in <see cref="bItemCollectionDisplay"/>
/// </summary>
/// <param name="_items"></param>
/// <param name="delay"></param>
/// <returns></returns>
protected virtual IEnumerator DisplayCollectedItems(float delay, params CollectedItemInfo[] _items)
{
for (int i = 0; i < _items.Length; i++)
{
onCollectItem.Invoke(_items[i]);
if (bItemCollectionDisplay.Instance)
{
string amountText = (_items[i].amount > 1) ? _items[i].amount.ToString() : null;
var text = $"Acquired: {amountText} {_items[i].item.name}";
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
}
yield return new WaitForSeconds(delay);
}
}
protected virtual void DisplayCollectedItems(CollectedItemInfo item)
{
if (bItemCollectionDisplay.Instance)
{
CheckQuestRequirementsForScrolls();
string amountText = (item.amount > 1) ? item.amount.ToString() : null;
var text = $"Acquired: {amountText} {item.item.name}";
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
}
}
//method used to check if player has enough scrolls in quest 8
private void CheckQuestRequirementsForScrolls()
{
if (QuestMachine.GetQuestState("takeBackTheTemple") != QuestState.Active)
{
return;
}
bool condition = GetAllAmount(29) >= 5 && GetAllAmount(42) >= 8 && GetAllAmount(39) >= 10;
if (condition)
{
MessageSystem.SendMessage(this, "Scrolls", "Purchased");
}
}
public void DisplayRemovedItem(bItem item)
{
StartCoroutine(DisplayRemovedItemCoroutune(item));
}
protected virtual IEnumerator DisplayRemovedItemCoroutune(bItem item)
{
if (bItemCollectionDisplay.Instance)
{
string amountText = (item.amount > 1) ? item.amount.ToString() : null;
var text = $"Sold: {amountText} {item.name}";
bItemCollectionDisplay.Instance.FadeText(text, 4, 0.25f);
}
yield return new WaitForSeconds(0);
}
#endregion Item Collector
#region IActionReceiver methods
/// <summary>
/// Event called by <seealso cref="vActionListener"/>
/// </summary>
/// <param name="action"></param>
public virtual void OnReceiveAction(vTriggerGenericAction action)
{
var collection = action.GetComponentInChildren<bItemCollection>();
if (collection != null)
{
if (collection.items.Count > 0)
{
List<ItemReference> itemCol = collection.items.vCopy();
CollectItems(itemCol, collection.onCollectDelay, collection.textDelay,
collection.ignoreItemAnimation);
}
}
}
#endregion IActionReceiver methods
public struct CollectedItemInfo
{
public bItem item;
public int amount;
}
}
[System.Serializable]
public class ItemReference
{
public int id;
public string name;
public int amount;
public ItemReference(int id)
{
this.id = id;
this.addToEquipArea = true;
this.autoEquip = false;
}
public List<bItemAttribute> attributes;
public bool changeAttributes;
public bool autoEquip = false;
public bool addToEquipArea = true;
public int indexArea;
public ItemReference Clone()
{
ItemReference clone = new ItemReference(this.id);
clone.name = this.name;
clone.amount = this.amount;
clone.autoEquip = this.autoEquip;
clone.addToEquipArea = this.addToEquipArea;
clone.indexArea = this.indexArea;
clone.changeAttributes = this.changeAttributes;
clone.attributes = this.attributes;
return clone;
}
}
[System.Serializable]
public class EquipPoint
{
#region SeralizedProperties in CustomEditor
[SerializeField] public string equipPointName;
public EquipmentReference equipmentReference = new EquipmentReference();
[HideInInspector] public bEquipArea area;
public vHandler handler = new vHandler();
//public Transform defaultPoint;
//public List<Transform> customPoints = new List<Transform>();
public OnInstantiateItemObjectEvent onInstantiateEquiment = new OnInstantiateItemObjectEvent();
#endregion SeralizedProperties in CustomEditor
}
public class EquipmentReference
{
public GameObject equipedObject;
public bItem item;
}
[System.Serializable]
public class ApplyAttributeEvent
{
[SerializeField] public bItemAttributes attribute;
[SerializeField] public OnApplyAttribute onApplyAttribute;
}
/// <summary>
/// Interface used to register <see cref="EquipPoint.onInstantiateEquiment"/> event from <see cref="vItemManager.RegisterDefaultEquipPointListeners"/>
/// </summary>
public interface IWeaponEquipmentListener
{
void SetLeftWeapon(GameObject equipment);
void SetRightWeapon(GameObject equipment);
}
}