using System; using System.Collections.Generic; using UnityEngine; [Serializable] public class Inventory { [SerializeField] private List<InventorySlot> items; private GameObject gameObject; public GameObject GameObject => gameObject; public int Count => items.Count; public int Capacity => items.Capacity; // Event triggered when inventory changes public event Action InventoryChanged; //Constructor public Inventory(int capacity, GameObject gameObject) { items = new List<InventorySlot>(capacity); this.gameObject = gameObject; } //Adds an item to the inventory public void AddItem(Item item, int amount = 1) { //Checks if the item already exists on the inventory slots InventorySlot existentSlot = FindSlotByItem(item); //If a slot is available increment the number of the item on that slot if (existentSlot != null) { int totalAmount = existentSlot.Amount + amount; if (totalAmount > existentSlot.MaxAmount) { int possibleAmountToAdd = existentSlot.MaxAmount - existentSlot.Amount; existentSlot.Amount += possibleAmountToAdd; //Creates a new slot if possible with the rest of the amount if (!IsFull()) { InventorySlot slot = new InventorySlot(item, amount - possibleAmountToAdd); items.Add(slot); } } else { existentSlot.Amount += amount; } Debug.Log($"Added item: {item.ItemName}"); InventoryChanged?.Invoke(); return; } //Checks if the inventory is not full if (!IsFull()) { Debug.Log($"Added item: {item.ItemName}"); //If there are no items of that reference on the inventory //Creates a new slot with that item reference InventorySlot slot = new InventorySlot(item, amount); items.Add(slot); InventoryChanged?.Invoke(); return; } Debug.LogWarning("Inventory is full!"); } //Removes an item from a slot public void RemoveItem(int index) { if (items[index] != null) { items.RemoveAt(index); InventoryChanged?.Invoke(); } } private void RemoveItem(int index, int amount) { if (items[index] != null) { int targetAmountLeft = items[index].Amount - amount; if (targetAmountLeft == 0) { items.RemoveAt(index); } else { items[index].Amount -= amount; } InventoryChanged?.Invoke(); } } //Swaps items to another slot public void SwapItemSlot(int index, int swapIndex) { InventorySlot slot = items[index]; items[index] = items[swapIndex]; items[swapIndex] = slot; InventoryChanged?.Invoke(); } public void SplitSlot(int index) { if (!IsFull()) { if (CanSplitItemSlot(index, out InventorySlot slot)) { int amountToTransfer = CalculateStackDivision(slot.Amount); slot.Amount = amountToTransfer; // Creates a new slot with the split amount and adds it to inventory InventorySlot newSlot = new InventorySlot(slot.Item, amountToTransfer); items.Add(newSlot); InventoryChanged?.Invoke(); return; } Debug.Log("Slot is not stackable or doesn't have enough items to split the stack"); return; } Debug.Log("Inventory is Full"); } //Check if the item is stackable //Returns true if the item is stackable //And also returns the slot of the item private bool CanSplitItemSlot(int index, out InventorySlot slot) { Item item = items[index].Item; slot = items[index]; return item != null && item.IsStackable && slot.Amount > 1; } //Gets an item public Item GetItem(int index) => items[index].Item; public InventorySlot InventorySlot(int index) => items[index]; //Calculates the division of the stack private int CalculateStackDivision(int amount) => Mathf.CeilToInt(amount / 2f); //Checks if a slot exists with same item private InventorySlot FindSlotByItem(Item item) { for (int i = 0; i < items.Count; i++) { if (items[i] != null && items[i].Item != null) { if (items[i].Item.Equals(item) && !items[i].IsSlotFull()) { return items[i]; } Debug.Log("The item is not the same or the slot is FULL"); } } return null; } public void DropItem(int index, int amount) { Item item = GetItem(index); GameObject go = GameManager.Instance.itemStack; if (go != null) { Vector3 targePos = new Vector3(gameObject.transform.position.x, gameObject.transform.position.y, 0); GameObject obj = UnityEngine.Object.Instantiate(go, targePos, Quaternion.identity); ItemStack stack = obj.GetComponent<ItemStack>(); stack.ItemStackInit(item, amount); RemoveItem(index, amount); return; } else { Debug.LogError($"Item stack is Null"); } } public InventorySlot GetSlot(int index) => items[index]; //Checks if the inventory is full public bool IsFull() => items.Count >= items.Capacity; } [Serializable] public class InventorySlot { //Variables [SerializeField] private Item item; [SerializeField] private int amount; [SerializeField] private int maxAmount; //Properties public Item Item => item; public int MaxAmount => maxAmount; public int Amount { get => amount; set => amount = value; } //Constructor public InventorySlot(Item item = null, int amount = 0) { this.item = item; this.amount = amount; maxAmount = item.StackAmount; } //Checks id the slot is full public bool IsSlotFull() => amount == maxAmount; public bool IsEmpty() => item == null; }