331 lines
9.1 KiB
C#
331 lines
9.1 KiB
C#
|
|
using UnityEngine;
|
||
|
|
using System.Collections.Generic;
|
||
|
|
|
||
|
|
[CreateAssetMenu(fileName = "NewItem", menuName = "Inventory/Item")]
|
||
|
|
public class Item : ScriptableObject
|
||
|
|
{
|
||
|
|
public string itemName;
|
||
|
|
public string itemDescription;
|
||
|
|
public int itemID;
|
||
|
|
public int maxStackSize = 1;
|
||
|
|
public bool isStackable;
|
||
|
|
public enum ItemType { Weapon, Armor, Consumable, QuestItem, Miscellaneous }
|
||
|
|
public ItemType itemType;
|
||
|
|
public Sprite itemIcon;
|
||
|
|
}
|
||
|
|
|
||
|
|
[System.Serializable]
|
||
|
|
public class InventorySlot
|
||
|
|
{
|
||
|
|
public Item item;
|
||
|
|
public int quantity;
|
||
|
|
|
||
|
|
public InventorySlot(Item newItem, int qty)
|
||
|
|
{
|
||
|
|
item = newItem;
|
||
|
|
quantity = qty;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
public class Inventory : MonoBehaviour
|
||
|
|
{
|
||
|
|
[SerializeField] private GameObject inventoryUI;
|
||
|
|
[SerializeField] private int maxCapacity = 20;
|
||
|
|
[SerializeField] private List<Item> allItems = new List<Item>(); // All available items in game
|
||
|
|
private List<InventorySlot> inventorySlots = new List<InventorySlot>();
|
||
|
|
|
||
|
|
// Equipment slots
|
||
|
|
private Item equippedWeapon;
|
||
|
|
private Item equippedArmor;
|
||
|
|
|
||
|
|
private Item FindItemByName(string itemName)
|
||
|
|
{
|
||
|
|
return allItems.Find(i => i.itemName == itemName);
|
||
|
|
}
|
||
|
|
|
||
|
|
private Item FindItemByID(int itemID)
|
||
|
|
{
|
||
|
|
return allItems.Find(i => i.itemID == itemID);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool AddItem(string itemName, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item '{itemName}' not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return AddItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool AddItem(int itemID, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return AddItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool AddItemInternal(Item item, int quantity = 1)
|
||
|
|
{
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("Tried to add null item to inventory.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
// Try to add to existing stack if stackable
|
||
|
|
if (item.isStackable)
|
||
|
|
{
|
||
|
|
foreach (var slot in inventorySlots)
|
||
|
|
{
|
||
|
|
if (slot.item == item && slot.quantity < item.maxStackSize)
|
||
|
|
{
|
||
|
|
int spaceAvailable = item.maxStackSize - slot.quantity;
|
||
|
|
int amountToAdd = Mathf.Min(quantity, spaceAvailable);
|
||
|
|
slot.quantity += amountToAdd;
|
||
|
|
Debug.Log($"Added {amountToAdd} {item.itemName} to existing stack. Stack size: {slot.quantity}");
|
||
|
|
|
||
|
|
if (amountToAdd < quantity)
|
||
|
|
{
|
||
|
|
// Recursively add remaining items
|
||
|
|
return AddItemInternal(item, quantity - amountToAdd);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// Add new slot if space available
|
||
|
|
if (inventorySlots.Count < maxCapacity)
|
||
|
|
{
|
||
|
|
inventorySlots.Add(new InventorySlot(item, quantity));
|
||
|
|
Debug.Log($"Added {quantity} {item.itemName} to inventory. Slots used: {inventorySlots.Count}/{maxCapacity}");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
|
||
|
|
Debug.Log("Inventory is full!");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RemoveItem(string itemName, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item '{itemName}' not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return RemoveItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool RemoveItem(int itemID, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return RemoveItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool RemoveItemInternal(Item item, int quantity = 1)
|
||
|
|
{
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning("Tried to remove null item from inventory.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
foreach (var slot in inventorySlots)
|
||
|
|
{
|
||
|
|
if (slot.item == item)
|
||
|
|
{
|
||
|
|
if (slot.quantity >= quantity)
|
||
|
|
{
|
||
|
|
slot.quantity -= quantity;
|
||
|
|
Debug.Log($"Removed {quantity} {item.itemName} from inventory.");
|
||
|
|
|
||
|
|
// Remove slot if empty
|
||
|
|
if (slot.quantity <= 0)
|
||
|
|
{
|
||
|
|
inventorySlots.Remove(slot);
|
||
|
|
}
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Not enough {item.itemName} in inventory. Have: {slot.quantity}, Need: {quantity}");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
Debug.LogWarning($"{item.itemName} not found in inventory.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public int GetItemQuantity(string itemName)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null) return 0;
|
||
|
|
return GetItemQuantityInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
public int GetItemQuantity(int itemID)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null) return 0;
|
||
|
|
return GetItemQuantityInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
private int GetItemQuantityInternal(Item item)
|
||
|
|
{
|
||
|
|
foreach (var slot in inventorySlots)
|
||
|
|
{
|
||
|
|
if (slot.item == item)
|
||
|
|
return slot.quantity;
|
||
|
|
}
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
public List<InventorySlot> GetInventorySlots()
|
||
|
|
{
|
||
|
|
return new List<InventorySlot>(inventorySlots);
|
||
|
|
}
|
||
|
|
|
||
|
|
public int GetAvailableSlots()
|
||
|
|
{
|
||
|
|
return maxCapacity - inventorySlots.Count;
|
||
|
|
}
|
||
|
|
|
||
|
|
public void ClearInventory()
|
||
|
|
{
|
||
|
|
inventorySlots.Clear();
|
||
|
|
Debug.Log("Inventory cleared.");
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool EquipItem(string itemName)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item '{itemName}' not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return EquipItemInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool EquipItem(int itemID)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return EquipItemInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool EquipItemInternal(Item item)
|
||
|
|
{
|
||
|
|
if (item == null) return false;
|
||
|
|
|
||
|
|
if (item.itemType == Item.ItemType.Weapon)
|
||
|
|
{
|
||
|
|
if (equippedWeapon != null)
|
||
|
|
AddItemInternal(equippedWeapon);
|
||
|
|
equippedWeapon = item;
|
||
|
|
RemoveItemInternal(item, 1);
|
||
|
|
Debug.Log($"Equipped weapon: {item.itemName}");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
else if (item.itemType == Item.ItemType.Armor)
|
||
|
|
{
|
||
|
|
if (equippedArmor != null)
|
||
|
|
AddItemInternal(equippedArmor);
|
||
|
|
equippedArmor = item;
|
||
|
|
RemoveItemInternal(item, 1);
|
||
|
|
Debug.Log($"Equipped armor: {item.itemName}");
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public Item GetEquippedItem(Item.ItemType type)
|
||
|
|
{
|
||
|
|
return type == Item.ItemType.Weapon ? equippedWeapon :
|
||
|
|
type == Item.ItemType.Armor ? equippedArmor : null;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool UseItem(string itemName)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item '{itemName}' not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return UseItemInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool UseItem(int itemID)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return UseItemInternal(item);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool UseItemInternal(Item item)
|
||
|
|
{
|
||
|
|
if (item.itemType == Item.ItemType.Consumable)
|
||
|
|
{
|
||
|
|
Debug.Log($"Used {item.itemName}");
|
||
|
|
RemoveItemInternal(item, 1);
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool DropItem(string itemName, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByName(itemName);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item '{itemName}' not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return DropItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
public bool DropItem(int itemID, int quantity = 1)
|
||
|
|
{
|
||
|
|
Item item = FindItemByID(itemID);
|
||
|
|
if (item == null)
|
||
|
|
{
|
||
|
|
Debug.LogWarning($"Item with ID {itemID} not found.");
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
return DropItemInternal(item, quantity);
|
||
|
|
}
|
||
|
|
|
||
|
|
private bool DropItemInternal(Item item, int quantity = 1)
|
||
|
|
{
|
||
|
|
if (RemoveItemInternal(item, quantity))
|
||
|
|
{
|
||
|
|
Debug.Log($"Dropped {quantity} {item.itemName}");
|
||
|
|
// TODO: Instantiate item drop in world
|
||
|
|
return true;
|
||
|
|
}
|
||
|
|
return false;
|
||
|
|
}
|
||
|
|
}
|