using UnityEngine;
using System.Linq;
using GameDevTV.Inventories;
using GameDevTV.Core.UI.Dragging;
using UnityEngine.EventSystems;
namespace GameDevTV.UI.Inventories
{
public class InventorySlotUI : MonoBehaviour, IItemHolder, IDragContainer<InventoryItem>, IPointerClickHandler
{
// CONFIG DATA
[SerializeField] InventoryItemIcon icon = null;
// STATE
int index;
InventoryItem item;
Inventory inventory;
// PUBLIC
public void Setup(Inventory inventory, int index)
{
this.inventory = inventory;
this.index = index;
icon.SetItem(inventory.GetItemInSlot(index), inventory.GetNumberInSlot(index));
}
public int MaxAcceptable(InventoryItem item)
{
if (inventory.HasSpaceFor(item))
{
return int.MaxValue;
}
return 0;
}
public void AddItems(InventoryItem item, int number)
{
inventory.AddItemToSlot(index, item, number);
}
public InventoryItem GetItem()
{
return inventory.GetItemInSlot(index);
}
public int GetNumber()
{
return inventory.GetNumberInSlot(index);
}
public void RemoveItems(int number)
{
inventory.RemoveFromSlot(index, number);
}
// Equipping a Weapon by clicking on it, and banking it if the bank is open:
public void TryHandleRightClick() {
InventoryItem item = inventory.GetItemInSlot(index);
int number = inventory.GetNumberInSlot(index);
if (item == null || number < 1) return; // inventory/bank slot is empty, so do nothing
if (!inventory.gameObject.CompareTag("Player")) {
TransferToOtherInventory(Inventory.GetPlayerInventory(), item, number);
return;
}
var otherInventoryUI = FindObjectsOfType<InventoryUI>().FirstOrDefault(ui => ui.IsOtherInventory); // returns other inventory, or null
if (otherInventoryUI != null && otherInventoryUI.gameObject.activeSelf && otherInventoryUI.SelectedInventory != null) {
Inventory otherInventory = otherInventoryUI.SelectedInventory;
TransferToOtherInventory(otherInventory, item, number);
return;
}
if (item is EquipableItem equipableItem) {
Equipment equipment = inventory.GetComponent<Equipment>();
EquipableItem equippedItem = equipment.GetItemInSlot(equipableItem.GetAllowedEquipLocation());
if (!equipableItem.CanEquip(equipableItem.GetAllowedEquipLocation(), equipment)) return; // The line solely responsible for checking for Predicate conditions, prior to being able to wield a weapon (if you're not high enough of a level, you can't wield that)
equipment.RemoveItem(equipableItem.GetAllowedEquipLocation());
equipment.AddItem(equipableItem.GetAllowedEquipLocation(), equipableItem);
RemoveItems(1);
if (equippedItem != null)
{
AddItems(equippedItem, 1);
}
}
else if (item is ActionItem actionItem) {
ActionStore actionStore = inventory.GetComponent<ActionStore>();
int slot = actionStore.GetFirstEmptySlot();
if (slot > -1) {
actionStore.AddAction(actionItem, slot, GetNumber());
RemoveItems(GetNumber());
}
}
}
// BELOW LIES THE CODE THAT ENSURES WE CAN CLICK ON STUFF IN OUR INVENTORY TO BANK IT:
// Static variable. Each time InventorySlotUI is clicked, this value is updated:
private static InventorySlotUI LastUIClicked;
// The 'OnPointerClick' method below checks to see if the Last UI Clicked Slot is 'this' inventory slot.
// if it isn't, set 'Last UI Clicked' to this, and a 'TimesUp()' timer (a timer that checks to see if we're the LastUIClicked. If so, clear 'LastUIClicked')
// is invoked
public void OnPointerClick(PointerEventData eventData) {
if (LastUIClicked != this) {
LastUIClicked = this;
Invoke(nameof(TimesUp), .5f);
Debug.Log($"{index} was clicked once");
}
else {
HandleDoubleClick();
}
}
// 'TimesUp' checks if we're the last UI clicked (if true, clear 'LastUIClicked')
private void TimesUp() {
if (LastUIClicked == this) LastUIClicked = null;
}
// HandleDoubleClicked() function deals with 3 states:
// 1. I am the player, and 'OtherInventory' (Bank) is Open
// 2. I am the bank, and 'OtherInventory' (Player) is Closed
// 3. I am the 'OtherInventory' (bank)
private void HandleDoubleClick() {
TimesUp(); // avoids triple clicking from starting another 'HandleDoubleClick'
InventoryItem item = inventory.GetItemInSlot(index);
int number = inventory.GetNumberInSlot(index);
if (item == null || number < 1) return;
if (inventory.gameObject.CompareTag("Player")) {
var otherInventoryUI = FindObjectsOfType<InventoryUI>().FirstOrDefault(ui => ui.IsOtherInventory);
if (otherInventoryUI != null && otherInventoryUI.gameObject.activeSelf && otherInventoryUI.SelectedInventory != null) {
Inventory otherInventory = otherInventoryUI.SelectedInventory;
TransferToOtherInventory(otherInventory, item, number);
}
else if (item is EquipableItem equipableItem && inventory.TryGetComponent(out Equipment equipment)) {
EquipItem(equipableItem, equipment, number);
}
}
else {
// The Code below ensures that when we double click on STACKED items in our bank to extract them, ONE ITEM AT A TIME COMES OUT (by swapping the last parameter from 'number' to '1'):
TransferToOtherInventory(Inventory.GetPlayerInventory(), item, 1);
}
}
// Transferring stuff from the Inventory to our Bank:
private void TransferToOtherInventory(Inventory otherInventory, InventoryItem item, int number) {
if (otherInventory.HasSpaceFor(item)) {
otherInventory.AddToFirstEmptySlot(inventory.GetItemInSlot(index), number);
inventory.RemoveItem(item, number);
Setup(inventory, index); // RECHECK Second argument, if it's 'item' or 'index'
}
}
// Equip item, if it's Equipable:
private void EquipItem(EquipableItem equipableItem, Equipment equipment, int number) {
if (equipableItem.CanEquip(equipableItem.GetAllowedEquipLocation(), equipment)) {
EquipableItem otherEquipableItem = equipment.GetItemInSlot(equipableItem.GetAllowedEquipLocation());
equipment.RemoveItem(equipableItem.GetAllowedEquipLocation());
inventory.RemoveFromSlot(index, number);
equipment.AddItem(equipableItem.GetAllowedEquipLocation(), equipableItem);
if (otherEquipableItem != null) inventory.AddItemToSlot(index, otherEquipableItem, 1);
Setup(inventory, index);
}
}
}
}