using System;
using System.Collections.Generic;
using UnityEngine;
///
/// Inventory holds and managed a list of slots which can contain an item.
///
public class Inventory : MonoBehaviour
{
// Actions -> Used for Callback in other scripts
public static Action OnPlayerInventoryChanged;
public static Action OnPlayerItemAdded;
public static Action OnPlayerItemRemoved;
// Serialized
[Header("Inventory")]
[Tooltip("The number of slots a player has in the inventory.")]
[SerializeField]
int numberOfSlots = 20;
[Tooltip("Maximal count of items in ONE slot. How big is one stack.")]
[SerializeField]
int maxSpaceOfSlots = 10;
[Tooltip("Is this inventory owned by the player")]
[SerializeField]
bool isPlayerInventory = true;
[Tooltip("List of the slots ('The inventory').")]
[SerializeField]
List inventory = new List();
public static Inventory PlayerInstance { get; private set; } // instance of PlayerInventory
public List GetInventory() => inventory;
///
/// Add slots to the inventory. You can extend the inventory space.
///
/// The count of slots which should be added to the inventory
public void AddSlots(int _numberOfSlots)
{
for (int i = 0; i < _numberOfSlots; i++)
{
inventory.Add(new Slot());
}
if(isPlayerInventory)
OnPlayerInventoryChanged?.Invoke();
}
///
/// GetEmptySlot gives you the first empty slot in the inventory.
///
/// An empty slot of the inventory
Slot GetEmptySlot()
{
foreach (Slot slot in inventory)
{
if (slot.GetItem() == null)
return slot;
}
return null;
}
///
/// GetSlotByItem lets you find a slot by the item it's containing.
///
///
/// Slot with the specified item.
Slot GetSlotByItem(Item item)
{
foreach (Slot slot in inventory)
{
if (slot.GetItem() != null)
{
if (slot.GetItem().id == item.id)
return slot;
}
}
return null;
}
///
/// GetRest calculates the rest count of an item and a slot.
/// Example: Slot has a capacity of 20. Count of item is 22. Returns 2.
///
/// The rest count of an item and a slot.
int GetRest(int count, Slot slot)
{
if (CountFitsInSlot(count, slot))
{
return 0;
}
else
{
return (count - (maxSpaceOfSlots - slot.GetCount()));
}
}
///
/// CountFitsInSlot calculates if the item count fits in the slot capacity
///
///
///
/// True: Count fits. False: Count does not fit.
bool CountFitsInSlot(int count, Slot slot)
{
int leftSize = maxSpaceOfSlots - slot.GetCount();
if (leftSize > count)
{
return true;
}
else
{
return false;
}
}
///
/// IndexIsInRange looks if an index of the inventory list is in range.
///
///
/// True: Is in range. False: Is not in range.
public bool IndexIsInRange(int index)
{
// Returns true if a given index is in the bounds of the inventory.
// Example (maxSize = 10) index = -10 : false , index = 100: false, index = 7 : true
if (index < inventory.Count && index >= 0)
{
return true;
}
else
{
return false;
}
}
///
/// Remove removes an item/s of the inventory list. It can be based in a specific index.
///
/// which item should be removed
/// Count of the item you want to remove
/// (optional) Index of the inventory list
/// The rest of the count, which could not be removed.
public int Remove(Item itemType, int count, int invIndex = -1)
{
Slot slot = null;
Item item = Instantiate(itemType);
if (item == null)
return -1;
// Get Slot
if (invIndex > -1)
{
if (IndexIsInRange(invIndex))
slot = inventory[invIndex];
}
else
{
slot = GetSlotByItem(item);
}
if (slot == null)
return -1;
// remove
if (slot.GetItem() != null && slot.GetItem().id == item.id) // Wenn im Slot schon das gleiche item ist
{
int rest = 0;
if (slot.GetCount() >= count)
{
slot.RemoveCount(count);
}
else
{
rest = count - slot.GetCount();
slot.Clear();
}
if (isPlayerInventory)
{
OnPlayerInventoryChanged?.Invoke();
OnPlayerItemRemoved?.Invoke();
}
return rest;
}
else
return -1;
}
///
/// Add adds an item/s of the inventory list. It can be based in a specific index.
///
/// which item should be added
/// Count of the item you want to add
/// (optional) Index of the inventory list
/// The rest of the count, which could not be added.
public int Add(Item itemType, int count, int invIndex = -1)
{
int rest = 0;
Slot slot = null;
Item item = Instantiate(itemType);
if (item == null)
return -1;
// Get Slot
if (invIndex > -1)
{
if(IndexIsInRange(invIndex))
slot = inventory[invIndex];
}
else
{
slot = GetSlotByItem(item);
if (slot == null)
slot = GetEmptySlot();
}
if (slot == null)
return -1;
// add
if (slot.GetItem() != null && slot.GetItem().id == item.id) // Wenn im Slot schon das selbe item ist
{
if (CountFitsInSlot(count, slot))
{
slot.AddCount(count);
}
else
{
rest = GetRest(count, slot);
slot.Set(item, maxSpaceOfSlots);
}
}
else if (slot.GetItem() == null)
{
if (CountFitsInSlot(count, slot))
{
slot.Set(item, count);
}
else
{
rest = GetRest(count, slot);
slot.Set(item, maxSpaceOfSlots);
}
}
else
return -1;
if (isPlayerInventory)
{
OnPlayerInventoryChanged?.Invoke();
OnPlayerItemAdded?.Invoke();
}
return rest;
}
void Awake()
{
// Initialize Inventory Slots
AddSlots(numberOfSlots);
if (isPlayerInventory)
PlayerInstance = this;
}
}