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

811 lines
29 KiB
C#

using System;
using Invector;
using Invector.vItemManager;
using System.Collections.Generic;
using System.Text;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.UI;
using System.Linq;
namespace Beyond
{
[vClassHeader("Equip Area", openClose = false)]
public class bEquipArea : vMonoBehaviour
{
public delegate void OnPickUpItem(bEquipArea area, bItemSlot slot);
private const int powerChargesMaxValue = 100;
public OnPickUpItem onPickUpItemCallBack;
public bInventory inventory;
public bItemManager itemManager;
public bItemWindow itemPicker;
[Tooltip("Set current equiped slot when submit an slot of this area")]
public bool setEquipSlotWhenSubmit;
[Tooltip("Skip empty slots when switching between slots")]
public bool skipEmptySlots;
public List<bEquipSlot> equipSlots;
public string equipPointName;
public Text displayNameText;
public Text displayTypeText;
public Text displayAmountText;
public Text displayDescriptionText;
public Text displayAttributesText;
[vHelpBox("You can ignore display Attributes using this property")]
public List<bItemAttributes> ignoreAttributes;
public UnityEngine.Events.UnityEvent onInitPickUpItem, onFinishPickUpItem;
public InputField.OnChangeEvent onChangeName;
public InputField.OnChangeEvent onChangeType;
public InputField.OnChangeEvent onChangeAmount;
public InputField.OnChangeEvent onChangeDescription;
public InputField.OnChangeEvent onChangeAttributes;
public OnChangeEquipmentEvent onEquipItem;
public OnChangeEquipmentEvent onUnequipItem;
public OnSelectEquipArea onSelectEquipArea;
public event Action OnItemUsed;
public UnityEngine.UI.Toggle.ToggleEvent onSetLockToEquip;
[HideInInspector]
public bEquipSlot currentSelectedSlot;
public bEquipSlot lastSelectedSlot;
[HideInInspector]
public int indexOfEquippedItem;
public bItem lastEquipedItem;
protected bool _isLockedToEquip;
[vHelpBox("Select what ItemType this EquipSlot will equip", vHelpBoxAttribute.MessageType.Warning)]
public List<bItemType> itemTypes;
private List<bItem> items = new();
private List<int> usedIndexes = new();
private List<bItem> gemableWeapons = new();
private bItem selectedPowerableItem;
private int selectedGemableItemIndex;
public bool isLockedToEquip
{
get
{
return _isLockedToEquip;
}
set
{
if (_isLockedToEquip != value) onSetLockToEquip.Invoke(value);
_isLockedToEquip = value;
}
}
public bool ignoreEquipEvents;
/// <summary>
/// used to ignore <see cref="onEquipItem"/> event. if true, the inventory will just add the equipment to area but dont will send to Equip the item. you will nedd to call <see cref="EquipCurrentSlot"/> to equip the item in the area.
/// </summary>
internal bool isInit;
public void Init()
{
if (!isInit) Start();
}
private void Start()
{
if (!isInit)
{
isInit = true;
//indexOfEquipedItem = -1;
inventory = GetComponentInParent<bInventory>();
itemManager = Player.Instance.GetComponent<bItemManager>();
//itemManager.onEquipItem
if (equipSlots.Count == 0)
{
var equipSlotsArray = GetComponentsInChildren<bEquipSlot>(true);
equipSlots = equipSlotsArray.vToList();
}
foreach (bEquipSlot slot in equipSlots)
{
slot.onSubmitSlotCallBack = OnSubmitSlot;
slot.onSelectSlotCallBack = OnSelectSlot;
slot.onDeselectSlotCallBack = OnDeselect;
onSetLockToEquip.AddListener(slot.SetLockToEquip);
if (slot.displayAmountText) slot.displayAmountText.text = "";
slot.onChangeAmount.Invoke("");
}
}
if (itemPicker)
{
itemPicker.onSelectSlot.AddListener(SetPowerableWeaponImage);
}
}
public void SetEquipmentWindow()
{
itemPicker.CreateEquipmentWindow(inventory.items, itemTypes, equipSlots[0].item, OnPickItem);
}
public void SetNewItemWindow(bItemWindow newItemPicker)
{
if (itemPicker)
{
DisableItemWindow();
}
itemPicker = newItemPicker;
EnableItemWindow();
}
public void DisableItemWindow()
{
itemPicker.gameObject.SetActive(false);
}
public void EnableItemWindow()
{
itemPicker.gameObject.SetActive(true);
}
public void SetEquipmentwindowWithFilter(List<bItemType> types)
{
itemPicker.CreateEquipmentWindow(inventory.items, types, null, OnPickItem);
//itemPicker.ReloadItems();
}
public void SetEquipmentWindowsUsableWithFilter(List<bItemType> types)
{
itemPicker.CreateEquipmentWindowUsable(inventory.items, types, equipSlots[0].item, OnPickItem);
}
private void SetOccupiedIndexes()
{
for (int i = 0; i < equipSlots.Count; i++)
{
if (equipSlots[i].isOcupad())
usedIndexes.Add(i);
}
}
public bool IsAnyItemEquipped()
{
for (int i = 0; i < equipSlots.Count; i++)
{
if (equipSlots[i].isOcupad())
{
return true;
}
}
return false;
}
/// <summary>
/// Current Equipped Slot
/// </summary>
public bEquipSlot currentEquippedSlot
{
get
{
return equipSlots[indexOfEquippedItem];
}
}
/// <summary>
/// Item in Current Equipped Slot
/// </summary>
public bItem currentEquippedItem
{
get
{
var validEquipSlots = ValidSlots;
if (validEquipSlots.Count > 0 && indexOfEquippedItem >= 0 && indexOfEquippedItem < validEquipSlots.Count) return validEquipSlots[indexOfEquippedItem].item;
return null;
}
}
/// <summary>
/// All valid slot <seealso cref="vItemSlot.isValid"/>
/// </summary>
public List<bEquipSlot> ValidSlots
{
get { return equipSlots.FindAll(slot => slot.isValid && (!skipEmptySlots || slot.item != null)); }
}
/// <summary>
/// Check if Item is in Area
/// </summary>
/// <param name="item">item to check</param>
/// <returns></returns>
public bool ContainsItem(vItem item)
{
return ValidSlots.Find(slot => slot.item == item) != null;
}
private void UseItemInternal(bItem item)
{
if (item.type == bItemType.Gemstones)
{
if (gemableWeapons.Count < 1 || gemableWeapons[selectedGemableItemIndex] == null)
{
if (bItemCollectionDisplay.Instance && item.type == bItemType.Gemstones && item)
{
Player.Instance.PlayFullyChargedSound();
//in menu
if (PopupMenuController.Instance != null)
{
PopupMenuController.Instance.TryToShowPopupMesssage("No proper weapons available");
} //cant use gemstone with no proper weapons available
return;
}
}
else //if (item.type == bItemType.Gemstones)
{
bItemAttribute powerAttribute = gemableWeapons[selectedGemableItemIndex].attributes.First(attribute => attribute.name == bItemAttributes.Power);
if (powerAttribute.value >= powerChargesMaxValue)
{
Player.Instance.PlayFullyChargedSound();
//Player.Instance.MeleeManager.onEquipWeapon
if (PopupMenuController.Instance != null)
{
PopupMenuController.Instance.TryToShowPopupMesssage(gemableWeapons[selectedGemableItemIndex].name + " is already fully charged");
} //cant use gemstone with no proper weapons available
return;
}
powerAttribute.value += item.GetItemAttribute(bItemAttributes.Power).value;
if (powerAttribute.value > powerChargesMaxValue)
{
powerAttribute.value = powerChargesMaxValue;
}
}
}
inventory.OnUseItem(item);
}
public void UseItem()
{
if (itemManager.UsingItem)
{
return;
}
//could move the logic to item manager
UseItemInternal(itemPicker.currentSelectedSlot.item);
/*
bItem itemBeingUsed = itemPicker.currentSelectedSlot.item;
//using here
if (itemBeingUsed.type == bItemType.Gemstones)
{
bItem item = itemBeingUsed;
if (gemableWeapons.Count < 1 || gemableWeapons[selectedGemableItemIndex] == null)
{
if (bItemCollectionDisplay.Instance && item.type == bItemType.Gemstones && item)
{
Player.Instance.PlayFullyChargedSound();
//in menu
if (PopupMenuController.Instance != null)
{
PopupMenuController.Instance.TryToShowPopupMesssage("No proper weapons available");
} //cant use gemstone with no proper weapons available
return;
}
}
else if (item.type == bItemType.Gemstones)
{
bItemAttribute powerAttribute = gemableWeapons[selectedGemableItemIndex].attributes.First(attribute => attribute.name == bItemAttributes.Power);
if (powerAttribute.value >= powerChargesMaxValue)
{
Player.Instance.PlayFullyChargedSound();
if (PopupMenuController.Instance != null)
{
PopupMenuController.Instance.TryToShowPopupMesssage(gemableWeapons[selectedGemableItemIndex].name + " is already fully charged");
} //cant use gemstone with no proper weapons available
return;
}
powerAttribute.value += item.GetItemAttribute(bItemAttributes.Power).value;
if (powerAttribute.value > powerChargesMaxValue)
{
powerAttribute.value = powerChargesMaxValue;
}
}
}
inventory.OnUseItem(itemBeingUsed);
*/
}
public void UseItem(bEquipSlot equipSlot)
{
bItem itemBeingUsed = equipSlot.item;
FindGemableWeapons();
UseItemInternal(itemBeingUsed);
//do some nice things here i think
//inventory.OnUseItem(itemBeingUsed);
}
public void UseEquippedItem()
{
inventory.OnUseItem(currentEquippedItem);
}
/// <summary>
/// Event called from Inventory slot UI on Submit
/// </summary>
/// <param name="slot"></param>
public void OnSubmitSlot(bItemSlot slot)
{
lastSelectedSlot = currentSelectedSlot;
if (itemPicker != null)
{
currentSelectedSlot = slot as bEquipSlot;
if (setEquipSlotWhenSubmit)
{
SetEquipSlot(equipSlots.IndexOf(currentSelectedSlot));
}
itemPicker.gameObject.SetActive(true);
itemPicker.onCancelSlot.RemoveAllListeners();
itemPicker.onCancelSlot.AddListener(CancelCurrentSlot);
itemPicker.CreateEquipmentWindow(inventory.items, currentSelectedSlot.itemType, slot.item, OnPickItem);
onInitPickUpItem.Invoke();
}
}
/// <summary>
/// Event called to cancel Submit action
/// </summary>
public void CancelCurrentSlot()
{
if (currentSelectedSlot == null)
currentSelectedSlot = lastSelectedSlot;
if (currentSelectedSlot != null)
currentSelectedSlot.OnCancel();
onFinishPickUpItem.Invoke();
}
/// <summary>
/// Unequip Item of the Slot
/// </summary>
/// <param name="slot">target slot</param>
public void UnequipItem(bEquipSlot slot)
{
if (slot)
{
bItem item = slot.item;
if (ValidSlots[indexOfEquippedItem].item == item)
lastEquipedItem = item;
slot.RemoveItem();
onUnequipItem.Invoke(this, item);
}
}
/// <summary>
/// Unequip Item if is present in slots
/// </summary>
/// <param name="item"></param>
public void UnequipItem(bItem item)
{
var slot = ValidSlots.Find(_slot => _slot.item == item);
if (slot)
{
if (ValidSlots[indexOfEquippedItem].item == item) lastEquipedItem = item;
slot.RemoveItem();
onUnequipItem.Invoke(this, item);
}
}
/// <summary>
/// Unequip <seealso cref="currentEquippedItem"/>
/// </summary>
public void UnequipCurrentItem()
{
if (currentSelectedSlot && currentSelectedSlot.item)
{
var _item = currentSelectedSlot.item;
if (ValidSlots[indexOfEquippedItem].item == _item) lastEquipedItem = _item;
currentSelectedSlot.RemoveItem();
onUnequipItem.Invoke(this, _item);
}
}
/// <summary>
/// Event called from inventory UI when select an slot
/// never fires apparently
/// </summary>
/// <param name="slot">target slot</param>
public void OnSelectSlot(bItemSlot slot)
{
if (equipSlots.Contains(slot as bEquipSlot))
currentSelectedSlot = slot as bEquipSlot;
else currentSelectedSlot = null;
onSelectEquipArea.Invoke(this);
CreateFullItemDescription(slot);
}
/// <summary>
/// Event called from inventory UI when unselect an slot
/// </summary>
/// <param name="slot">target slot</param>
public void OnDeselect(bItemSlot slot)
{
if (equipSlots.Contains(slot as bEquipSlot))
{
currentSelectedSlot = null;
}
}
/// <summary>
/// Create item description
/// </summary>
/// <param name="slot">target slot</param>
protected virtual void CreateFullItemDescription(bItemSlot slot)
{
var _name = slot.item ? slot.item.name : "";
var _type = slot.item ? slot.item.ItemTypeText() : "";
var _amount = slot.item ? slot.item.amount.ToString() : "";
var _description = slot.item ? slot.item.description : "";
var _attributes = slot.item ? slot.item.GetItemAttributesText(ignoreAttributes) : "";
if (displayNameText) displayNameText.text = _name;
onChangeName.Invoke(_name);
if (displayTypeText) displayTypeText.text = _type;
onChangeType.Invoke(_type);
if (displayAmountText) displayAmountText.text = _amount;
onChangeAmount.Invoke(_amount);
if (displayDescriptionText) displayDescriptionText.text = _description;
onChangeDescription.Invoke(_description);
if (displayAttributesText) displayAttributesText.text = _attributes;
onChangeAttributes.Invoke(_attributes);
Debug.LogError("happeingng?");
}
/// <summary>
/// Event called from inventory UI to open <see cref="vItemWindow"/> when submit slot
/// </summary>
/// <param name="slot">target slot</param>
public void OnPickItem(bItemSlot slot)
{
/*
//for gemstones it does something different, it switches internal idnex of currently selected sword
if (slot.item.type == bItemType.Gemstones)
{
SwitchPowerableWeapon();
return;
}
*/
//1 check if any slot has this item, if it does, unequip it
//2 if not fill the first free slot
//3 if no free slots available swap with the oldest one
if (usedIndexes.Count == 0)
{
SetOccupiedIndexes();
}
//1
if (slot.isChecked)
{
bEquipSlot occupiedSlot = equipSlots.Find(eSlot => eSlot.item == slot.item);
usedIndexes.Remove(equipSlots.IndexOf(occupiedSlot));
occupiedSlot.RemoveItem();
onUnequipItem.Invoke(this, slot.item);
onFinishPickUpItem.Invoke();
return;
}
//2
bEquipSlot freeSlot = equipSlots.Find(eslot => !eslot.isOcupad() && eslot.isValid && eslot.itemType.Contains(slot.item.type));
if (freeSlot)
{
onPickUpItemCallBack?.Invoke(this, slot);
freeSlot.AddItem(slot.item);
if (!ignoreEquipEvents)
{
onEquipItem.Invoke(this, slot.item);
}
onFinishPickUpItem.Invoke();
usedIndexes.Add(equipSlots.IndexOf(freeSlot));
return;
}
//3
//get last used index that is of valid type
bEquipSlot slotToBeTaken = equipSlots[0];
for (int i = 0; i < usedIndexes.Count; i++)
{
int tempIndex = usedIndexes[i];
if (equipSlots[tempIndex].itemType.Contains(slot.item.type))
{
slotToBeTaken = equipSlots[tempIndex];
usedIndexes.RemoveAt(i);
usedIndexes.Add(tempIndex);
i = usedIndexes.Count;
}
}
// bEquipSlot slotToBeTaken = equipSlots[usedIndexes[0]];
//remove old 1st
slotToBeTaken.RemoveItem();
onUnequipItem.Invoke(this, slot.item);
onFinishPickUpItem.Invoke();
//add new
onPickUpItemCallBack?.Invoke(this, slot);
slotToBeTaken.AddItem(slot.item);
if (!ignoreEquipEvents)
{
onEquipItem.Invoke(this, slot.item);
}
onFinishPickUpItem.Invoke();
return;
if (!currentSelectedSlot)
{
currentSelectedSlot = lastSelectedSlot;
}
if (!currentSelectedSlot)
{
return;
}
if (currentSelectedSlot.item != null && slot.item != currentSelectedSlot.item)
{
currentSelectedSlot.item.isInEquipArea = false;
var item = currentSelectedSlot.item;
if (item == slot.item) lastEquipedItem = item;
currentSelectedSlot.RemoveItem();
onUnequipItem.Invoke(this, item);
}
if (slot.item != currentSelectedSlot.item)
{
if (onPickUpItemCallBack != null)
onPickUpItemCallBack(this, slot);
currentSelectedSlot.AddItem(slot.item);
if (!ignoreEquipEvents) onEquipItem.Invoke(this, currentSelectedSlot.item);
}
currentSelectedSlot.OnCancel();
currentSelectedSlot = null;
lastSelectedSlot = null;
onFinishPickUpItem.Invoke();
}
void FindGemableWeapons()
{
List<bItemType> weaponTypes = new List<bItemType>() { bItemType.Swords, bItemType.Axes };
gemableWeapons = inventory.items.FindAll(item => weaponTypes.Contains(item.type) && item.GetItemAttribute(bItemAttributes.Power) != null);
selectedGemableItemIndex = 0;
}
private void SetPowerableWeaponImage(bItemSlot itemSelected)
{
if (itemSelected.item.type == bItemType.Gemstones)
{
//for gemstones reset selection of gemable weapon, no saving per gem as of now
FindGemableWeapons();
if (gemableWeapons.Count > 0)
{
selectedPowerableItem = gemableWeapons[selectedGemableItemIndex];
itemPicker.SetPowerableSwitchSwordImage(selectedPowerableItem);
}
}
}
public void SwitchPowerableWeapon()
{
if (gemableWeapons.Count < 1)
{
itemPicker.SetPowerableSwitchSwordImage(null);
return;
}
selectedGemableItemIndex++;
if (selectedGemableItemIndex >= gemableWeapons.Count)
{
selectedGemableItemIndex = 0;
}
selectedPowerableItem = gemableWeapons[selectedGemableItemIndex];
itemPicker.SetPowerableSwitchSwordImage(selectedPowerableItem);
//updaing ui
}
/// <summary>
/// Equip next slot <seealso cref="currentEquippedItem"/>
/// </summary>
public void NextEquipSlot()
{
if (equipSlots == null || equipSlots.Count == 0) return;
lastEquipedItem = currentEquippedItem;
var validEquipSlots = ValidSlots;
if (indexOfEquippedItem + 1 < validEquipSlots.Count)
indexOfEquippedItem++;
else
indexOfEquippedItem = 0;
if (currentEquippedItem != null && !ignoreEquipEvents)
onEquipItem.Invoke(this, currentEquippedItem);
onUnequipItem.Invoke(this, lastEquipedItem);
}
/// <summary>
/// Equip previous slot <seealso cref="currentEquippedItem"/>
/// </summary>
public void PreviousEquipSlot()
{
if (equipSlots == null || equipSlots.Count == 0) return;
lastEquipedItem = currentEquippedItem;
var validEquipSlots = ValidSlots;
if (indexOfEquippedItem - 1 >= 0)
indexOfEquippedItem--;
else
indexOfEquippedItem = validEquipSlots.Count - 1;
if (currentEquippedItem != null && !ignoreEquipEvents)
onEquipItem.Invoke(this, currentEquippedItem);
onUnequipItem.Invoke(this, lastEquipedItem);
}
/// <summary>
/// Equip slot <see cref="currentEquippedItem"/>
/// </summary>
/// <param name="indexOfSlot">index of target slot</param>
public void SetEquipSlot(int indexOfSlot)
{
if (equipSlots == null || equipSlots.Count == 0) return;
if (indexOfSlot < equipSlots.Count && indexOfSlot >= 0)
{
lastEquipedItem = currentEquippedItem;
indexOfEquippedItem = indexOfSlot;
if (currentEquippedItem != null && !ignoreEquipEvents)
{
onEquipItem.Invoke(this, currentEquippedItem);
}
if (currentEquippedItem != lastEquipedItem)
onUnequipItem.Invoke(this, lastEquipedItem);
}
}
public void EquipCurrentSlot()
{
if (!currentEquippedSlot || (currentEquippedSlot.item != null && currentEquippedSlot.item.isEquiped)) return;
if (currentEquippedItem) onEquipItem.Invoke(this, currentEquippedItem);
else if (lastEquipedItem) onUnequipItem.Invoke(this, lastEquipedItem);
}
/// <summary>
/// Add an item to an slot
/// </summary>
/// <param name="slot">target Slot</param>
/// <param name="item">target Item</param>
public void AddItemToEquipSlot(bItemSlot slot, bItem item, bool autoEquip = false)
{
if (slot is bEquipSlot && equipSlots.Contains(slot as bEquipSlot))
{
AddItemToEquipSlot(equipSlots.IndexOf(slot as bEquipSlot), item, autoEquip);
}
}
/// <summary>
/// Add an item to an slot
/// </summary>
/// <param name="indexOfSlot">index of target Slot</param>
/// <param name="item">target Item</param>
public void AddItemToEquipSlot(int indexOfSlot, bItem item, bool autoEquip = false)
{
if (indexOfSlot < equipSlots.Count && item != null && item.canBeUsed)
{
var slot = equipSlots[indexOfSlot];
if (slot != null && slot.isValid && slot.itemType.Contains(item.type))
{
var sameSlot = equipSlots.Find(s => s.item == item && s != slot);
if (sameSlot != null)
RemoveItemOfEquipSlot(equipSlots.IndexOf(sameSlot));
if (slot.item != null && slot.item != item)
{
if (currentEquippedItem == slot.item) lastEquipedItem = slot.item;
slot.item.isInEquipArea = false;
onUnequipItem.Invoke(this, slot.item);
}
item.checkColor = slot.checkColor;
item.isInEquipArea = true;
slot.AddItem(item);
if (autoEquip)
SetEquipSlot(indexOfSlot);
else if (!ignoreEquipEvents)
onEquipItem.Invoke(this, item);
}
}
}
/// <summary>
/// Remove item of an slot
/// </summary>
/// <param name="slot">target Slot</param>
public void RemoveItemOfEquipSlot(bItemSlot slot)
{
if (slot is bEquipSlot && equipSlots.Contains(slot as bEquipSlot))
{
RemoveItemOfEquipSlot(equipSlots.IndexOf(slot as bEquipSlot));
}
}
/// <summary>
/// Remove item of an slot
/// </summary>
/// <param name="slot">index of target Slot</param>
public void RemoveItemOfEquipSlot(int indexOfSlot)
{
if (indexOfSlot < equipSlots.Count)
{
var slot = equipSlots[indexOfSlot];
if (slot != null && slot.item != null)
{
var item = slot.item;
item.isInEquipArea = false;
if (currentEquippedItem == item) lastEquipedItem = currentEquippedItem;
slot.RemoveItem();
onUnequipItem.Invoke(this, item);
}
}
}
/// <summary>
/// Add item to current equiped slot
/// </summary>
/// <param name="item">target item</param>
public void AddCurrentItem(bItem item)
{
if (indexOfEquippedItem < equipSlots.Count)
{
var slot = equipSlots[indexOfEquippedItem];
if (slot.item != null && item != slot.item)
{
if (currentEquippedItem == slot.item) lastEquipedItem = slot.item;
slot.item.isInEquipArea = false;
onUnequipItem.Invoke(this, currentSelectedSlot.item);
}
slot.AddItem(item);
if (!ignoreEquipEvents) onEquipItem.Invoke(this, item);
}
}
/// <summary>
/// Remove current equiped Item
/// </summary>
public void RemoveCurrentItem()
{
if (!currentEquippedItem) return;
lastEquipedItem = currentEquippedItem;
ValidSlots[indexOfEquippedItem].RemoveItem();
onUnequipItem.Invoke(this, lastEquipedItem);
}
}
}