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

735 lines
27 KiB
C#

using Invector;
using Invector.vItemManager;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using TMPro;
using UnityEngine;
using UnityEngine.Events;
using UnityEngine.EventSystems;
using UnityEngine.UI;
namespace Beyond
{
[System.Serializable]
public class OnHandleSlot : UnityEngine.Events.UnityEvent<bItemSlot>
{ }
[System.Serializable]
public class OnCompleteSlotList : UnityEngine.Events.UnityEvent<List<bItemSlot>>
{ }
[vClassHeader("Item Window", openClose = false)]
public class bItemWindow : vMonoBehaviour
{
[vReadOnly] public bItem currentItem;
private List<bItem> items;
public bItemSlot slotPrefab;
public RectTransform contentWindow;
public List<bItemSlot> slots;
public List<bItemType> supportedItems;
public bool updateSlotCount = true;
public TMP_Text displayNameText;
public Image rarityImage;
public Text displayTypeText;
public Text displayAmountText;
public TMP_Text displayDescriptionText, changeableAttributesText;
public Image powerSwordImage;
public Text displayAttributesText;
public Image displayItemImage, secondaryItemImage, teriaryItemImage;
[SerializeField] private Sprite defaultSprite;
[Header("Additional things")]
public bItemSlot currentSelectedSlot;
[SerializeField] private TMP_Text submitButtonText, consumeButtonText;
[SerializeField] private RectTransform descriptionTransform;
[SerializeField] private Scrollbar descriptionScroolbar;
[SerializeField] private string useButtonString = "";
[SerializeField]
private GameObject button, consumeButton;
[SerializeField]
private bool isTradeWindow = false;
[vHelpBox("You can ignore display Attributes using this property")]
public List<bItemAttributes> ignoreAttributes;
[vEditorToolbar("Text Events")]
public InputField.OnChangeEvent onChangeName;
public InputField.OnChangeEvent onChangeType;
public InputField.OnChangeEvent onChangeAmount;
public InputField.OnChangeEvent onChangeDescription;
public InputField.OnChangeEvent onChangeAttributes;
// public InputField.OnChangeEvent onChangeImage;
[vEditorToolbar("Events")]
public OnCompleteSlotList onCompleteSlotListCallBack;
public OnHandleSlot onSubmitSlot;
public OnHandleSlot onSelectSlot;
public UnityEvent onCancelSlot;
[Tooltip("Called when item window has slots on enable")]
public UnityEvent onAddSlots;
[Tooltip("Called when item window dont have slots on enable")]
public UnityEvent onClearSlots;
private UnityAction<bItemSlot> onSubmitSlotCallback;
private UnityAction<bItemSlot> onSelectCallback;
private readonly WaitForEndOfFrame WaitForEndOfFrame = new WaitForEndOfFrame();
private List<bItemType> chroniclesTypes = new List<bItemType> { bItemType.ChronicleResources, bItemType.Locations, bItemType.Science, bItemType.Characters };
private void OnEnable()
{
if (descriptionScroolbar)
{
StartCoroutine(RebuildLayoutCoroutine());
}
}
private void OnDisable()
{
//unload stuff
UnloadCurrentImage();
}
private void UnloadCurrentImage()
{
// Sprite spriteToUnload = displayItemImage.sprite;
if (displayItemImage)
{
Resources.UnloadAsset(displayItemImage.sprite);
}
if (secondaryItemImage)
{
Resources.UnloadAsset(secondaryItemImage.sprite);
}
if (teriaryItemImage)
{
Resources.UnloadAsset(teriaryItemImage.sprite);
}
if (powerSwordImage)
{
Resources.UnloadAsset(powerSwordImage.sprite);
}
// displayItemImage.sprite = null;
// secondaryItemImage.sprite = null;
// teriaryItemImage.sprite = null;
// Resources.UnloadAsset(spriteToUnload);
//Resources.UnloadUnusedAssets();
}
public void ReloadItems()
{
ReloadItems(items);
}
public void ClearSlots()
{
int slotsCount = slots.Count;
for (int i = 0; i < slotsCount; i++)
{
Destroy(slots[i].gameObject);
}
slots.Clear();
currentSelectedSlot = null;
}
public void ReloadItems(List<bItem> items)
{
int indexOfSlot = slots.Contains(currentSelectedSlot) ? slots.IndexOf(currentSelectedSlot) : 0;
for (int i = 0; i < slots.Count; i++)
{
if (i >= 0 && i < slots.Count)
{
if (slots[i] != null && (slots[i].item == null || !items.Contains(slots[i].item)))
{
Destroy(slots[i].gameObject);
slots.Remove(slots[i]);
if (i == indexOfSlot)
{
currentSelectedSlot = i - 1 >= 0 ? slots[i - 1] : slots.Count - 1 > 0 ? slots[0] : null;
if (currentSelectedSlot != null) CreateFullItemDescription(currentSelectedSlot);
}
i--;
}
else if (slots[i] == null)
{
slots.RemoveAt(i);
i--;
}
}
}
if (currentSelectedSlot == null || currentSelectedSlot.item == null || slots.Count == 0)
{
CreateFullItemDescription(null);
if (slots.Count == 0) onClearSlots.Invoke();
}
else CreateFullItemDescription(currentSelectedSlot);
}
public virtual void CreateEquipmentWindow(List<bItem> items, UnityAction<bItemSlot> onPickUpItemCallBack = null, UnityAction<bItemSlot> onSelectSlotCallBack = null, bool destroyAdictionSlots = true)
{
StartCoroutine(CreateEquipmentWindowRoutine(items, onPickUpItemCallBack, onSelectSlotCallBack, destroyAdictionSlots));
}
public virtual void CreateEquipmentWindow(List<bItem> items, List<bItemType> type, bItem currentItem = null, UnityAction<bItemSlot> onPickUpItemCallback = null, UnityAction<bItemSlot> onSelectSlotCallBack = null)
{
this.items = items.FindAll(item => type.Contains(item.type));
List<bItem> list = new List<bItem>();
foreach (var bItem in this.items.OrderBy(item => item.type)
.ThenBy(item => item.name))
list.Add(bItem);
this.items = list;
this.currentItem = currentItem;
if (!this.currentItem && this.items.Count > 0)
{
this.currentItem = this.items[0];
}
CreateEquipmentWindowNormal(this.items, onPickUpItemCallback, destroyAdictionSlots: true);
}
public virtual void CreateEquipmentWindowUsable(List<bItem> items, List<bItemType> type, bItem currentItem = null, UnityAction<bItemSlot> onPickUpItemCallback = null, UnityAction<bItemSlot> onSelectSlotCallBack = null)
{
this.currentItem = currentItem;
var _items = items.FindAll(item => type.Contains(item.type));
var _itemsUsable = _items.FindAll(item => item.canBeUsed);
CreateEquipmentWindowNormal(_itemsUsable, onPickUpItemCallback, destroyAdictionSlots: true);
}
public void CreateEquipmentWindowNormal(List<bItem> items, UnityAction<bItemSlot> onPickUpItemCallBack = null, UnityAction<bItemSlot> onSelectSlotCallBack = null, bool destroyAdictionSlots = true)
{
var _items = supportedItems.Count == 0 ? items : items.FindAll(i => supportedItems.Contains(i.type));
if (_items.Count == 0)
{
CreateFullItemDescription(null);
onClearSlots.Invoke();
if (slots.Count > 0 && destroyAdictionSlots && updateSlotCount)
{
for (int i = 0; i < slots.Count; i++)
{
// yield return null;
Destroy(slots[i].gameObject);
}
slots.Clear();
}
currentSelectedSlot = null;
}
else
{
if (slots.Count > _items.Count && destroyAdictionSlots && updateSlotCount)
{
int difference = slots.Count - _items.Count;
for (int i = 0; i < difference; i++)
{
// yield return null;
Destroy(slots[0].gameObject);
slots.RemoveAt(0);
}
}
bool selecItem = false;
onSubmitSlotCallback = onPickUpItemCallBack;
onSelectCallback = onSelectSlotCallBack;
if (slots == null) slots = new List<bItemSlot>();
var count = items.Count;
if (updateSlotCount)
{
for (int i = 0; i < _items.Count; i++)
{
bItemSlot slot = null;
if (i < slots.Count)
{
slot = slots[i];
}
else
{
slot = Instantiate(slotPrefab) as bItemSlot;
slots.Add(slot);
var rectTranform = slot.GetComponent<RectTransform>();
rectTranform.SetParent(contentWindow);
rectTranform.localPosition = Vector3.zero;
rectTranform.localScale = Vector3.one;
rectTranform.localRotation = Quaternion.identity;
// yield return null;
}
// slot = slots[i];
slot.AddItem(_items[i]);
if (slot.item.type == bItemType.PowerScroll && slot.item.canBeDroped)
{
slot.TryToMarkAsSpeciallEquipped();
}
else
{
slot.CheckItem(_items[i].isInEquipArea);
}
slot.onSubmitSlotCallBack = OnSubmit;
slot.onSelectSlotCallBack = OnSelect;
if (currentItem != null && currentItem == _items[i])
{
if (currentSelectedSlot)
{
currentSelectedSlot.MarkSlotAsDeselected();
}
selecItem = true;
currentSelectedSlot = slot;
OnSelect(slot);
}
slot.UpdateDisplays();
}
}
if (slots.Count > 0 && !selecItem)
{
currentSelectedSlot = slots[0];
//StartCoroutine(SetSelectableHandle(slots[0].gameObject));
}
}
SetSubmitButton(currentSelectedSlot);
if (slots.Count > 0)
{
onAddSlots.Invoke();
EnableDescriptionObjects();
CreateFullItemDescription(currentSelectedSlot);
}
else
{
DisableDescriptionObjects();
}
onCompleteSlotListCallBack.Invoke(slots);
}
public void EnableDescriptionObjects()
{
displayNameText.enabled = true;
descriptionTransform.gameObject.SetActive(true);
}
public void DisableDescriptionObjects()
{
displayNameText.enabled = false;
descriptionTransform.gameObject.SetActive(false);
}
protected virtual IEnumerator CreateEquipmentWindowRoutine(List<bItem> items, UnityAction<bItemSlot> onPickUpItemCallBack = null, UnityAction<bItemSlot> onSelectSlotCallBack = null, bool destroyAdictionSlots = true)
{
var _items = supportedItems.Count == 0 ? items : items.FindAll(i => supportedItems.Contains(i.type));
if (_items.Count == 0)
{
CreateFullItemDescription(null);
onClearSlots.Invoke();
if (slots.Count > 0 && destroyAdictionSlots && updateSlotCount)
{
for (int i = 0; i < slots.Count; i++)
{
// yield return null;
Destroy(slots[i].gameObject);
}
slots.Clear();
currentSelectedSlot = null;
}
}
else
{
if (slots.Count > _items.Count && destroyAdictionSlots && updateSlotCount)
{
int difference = slots.Count - _items.Count;
for (int i = 0; i < difference; i++)
{
yield return null;
Destroy(slots[0].gameObject);
slots.RemoveAt(0);
}
}
bool selecItem = false;
onSubmitSlotCallback = onPickUpItemCallBack;
onSelectCallback = onSelectSlotCallBack;
if (slots == null) slots = new List<bItemSlot>();
var count = items.Count;
// if (updateSlotCount)
{
for (int i = 0; i < _items.Count; i++)
{
bItemSlot slot = null;
if (i < slots.Count)
{
slot = slots[i];
}
else
{
slot = Instantiate(slotPrefab) as bItemSlot;
slots.Add(slot);
var rectTranform = slot.GetComponent<RectTransform>();
rectTranform.SetParent(contentWindow);
rectTranform.localPosition = Vector3.zero;
rectTranform.localScale = Vector3.one;
// yield return null;
}
// slot = slots[i];
slot.AddItem(_items[i]);
slot.CheckItem(_items[i].isInEquipArea);
slot.onSubmitSlotCallBack = OnSubmit;
slot.onSelectSlotCallBack = OnSelect;
if (currentItem != null && currentItem == _items[i])
{
selecItem = true;
currentSelectedSlot = slot;
SetSelectable(slot.gameObject);
}
slot.UpdateDisplays();
}
}
if (slots.Count > 0 && !selecItem)
{
currentSelectedSlot = slots[0];
StartCoroutine(SetSelectableHandle(slots[0].gameObject));
}
}
if (slots.Count > 0)
{
onAddSlots.Invoke();
CreateFullItemDescription(currentSelectedSlot);
}
onCompleteSlotListCallBack.Invoke(slots);
}
public virtual IEnumerator SetSelectableHandle(GameObject target)
{
if (this.enabled)
{
yield return WaitForEndOfFrame;
SetSelectable(target);
}
}
public virtual void SetSelectable(GameObject target)
{
var pointer = new PointerEventData(EventSystem.current);
ExecuteEvents.Execute(EventSystem.current.currentSelectedGameObject, pointer, ExecuteEvents.pointerExitHandler);
EventSystem.current.SetSelectedGameObject(target, new BaseEventData(EventSystem.current));
ExecuteEvents.Execute(target, pointer, ExecuteEvents.selectHandler);
}
public virtual void OnSubmit(bItemSlot slot)
{
if (ShouldDissalowUseOfScrolls(slot))
{
PopupMenuController.Instance.TryToShowPopupMesssage("Skill Required: " + SkillsManager.instance.GetStringNameOf(Skills.MasterOfScrolls));
}
else
{
currentSelectedSlot = slot;
onSubmitSlotCallback?.Invoke(slot);
SetSubmitButton(slot);
onSubmitSlot.Invoke(slot);
}
}
private bool ShouldDissalowUseOfScrolls(bItemSlot slot)
{
return slot.item.type == bItemType.PowerScroll && SkillsManager.instance.GetSkillLevelOf(Skills.MasterOfScrolls) == 0 && PopupMenuController.Instance != null && !isTradeWindow;
}
private void SetSubmitButton(bItemSlot slot)
{
if (!slot)
{
button.SetActive(false);
if (consumeButton)
{
consumeButton.SetActive(false);
}
return;
}
else
{
button.SetActive(true);
}
if (useButtonString != "")
{
submitButtonText.text = useButtonString;
return;
}
bItemType itemType = slot.item.type;
switch (itemType)
{
case bItemType.MeleeWeapon:
case bItemType.Swords:
case bItemType.Axes:
case bItemType.QuantaPower:
case bItemType.Gemstones:
submitButtonText.text = slot.isChecked ? "Unequip" : "Equip";
break;
case bItemType.PowerScroll:
if (!slot.item.canBeDroped)
{
submitButtonText.text = slot.isChecked ? "Unequip" : "Equip";
}
else
{
button.SetActive(false);
}
break;
case bItemType.Builder:
submitButtonText.text = "Create";
break;
case bItemType.Consumable:
case bItemType.ConsumablesFaith:
submitButtonText.text = slot.isChecked ? "Unequip" : "Equip";
consumeButton.SetActive(true);
consumeButtonText.text = "Consume";
break;
/*
case bItemType.Gemstones:
submitButtonText.text = "Switch Weapon";
consumeButton.SetActive(true);
consumeButtonText.text = "Equip";
break;
*/
case bItemType.Guilts:
submitButtonText.text = "Agree";
break;
default:
button.SetActive(false);
if (consumeButton)
{
consumeButton.SetActive(false);
}
break;
}
}
public void SetPowerableSwitchSwordImage(bItem selectedPowerableItem)
{
Resources.UnloadAsset(powerSwordImage.sprite);
if (!selectedPowerableItem)
{
powerSwordImage.enabled = false;
}
else
{
powerSwordImage.enabled = true;
powerSwordImage.sprite = Resources.Load<Sprite>(selectedPowerableItem.iconPath);
}
}
public void OnSubmit()
{
OnSubmit(currentSelectedSlot);
}
public virtual void OnSelect(bItemSlot slot)
{
if (slot == null || slot.item == null)
{
return;
}
if (currentSelectedSlot)
{
currentSelectedSlot.MarkSlotAsDeselected();
}
currentSelectedSlot = slot;
slot.MarkSlotAsSelected();
CreateFullItemDescription(slot);
onSelectCallback?.Invoke(slot);
SetSubmitButton(slot);
onSelectSlot.Invoke(slot);
}
protected virtual void CreateFullItemDescription(bItemSlot slot)
{
if (!slot)
{
return;
}
var _name = slot.item ? slot.item.name : "";
var _rarity = -1;
if (ItemIsRarityInterested(slot))
{
bItemAttribute rarityAttribute = slot.item.GetItemAttribute(bItemAttributes.Rarity);
_rarity = rarityAttribute != null ? rarityAttribute.value : 0; // 0 means ordinary, 1 ancient, 2 mystical
}
var _description = slot.item ? slot.item.description : "";
var _image = slot.item ? Resources.Load<Sprite>(slot.item.iconPath) /* slot.item.icon */: defaultSprite;
var _secondaryImage = slot.item ? Resources.Load<Sprite>(slot.item.secondaryIconPath) : null;
var _teriaryImage = slot.item ? Resources.Load<Sprite>(slot.item.teriaryIconPath) : null;
var _type = slot.item ? slot.item.ItemTypeText() : "";
var _amount = slot.item ? slot.item.amount.ToString() : "";
var _attributes = slot.item ? slot.item.GetItemAttributesText(ignoreAttributes) : "";
var _power = slot.item ? slot.item.GetItemAttribute(bItemAttributes.Power) : null;
var _Damage = slot.item ? slot.item.GetItemAttribute(bItemAttributes.Damage) : null;
if (displayNameText) displayNameText.text = _name;
onChangeName.Invoke(_name);
if (rarityImage && _rarity >= 0)
{
rarityImage.gameObject.SetActive(true);
rarityImage.sprite = slot.raritySprites[_rarity];
}
else
{
rarityImage.gameObject.SetActive(false);
}
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);
if (chroniclesTypes.Contains(slot.item.type))
{
displayItemImage.sprite = (Sprite)_secondaryImage;
}
else if (displayItemImage)
{
displayItemImage.sprite = (Sprite)_image;
}
bItemAttribute yOffsetAttribute = slot.item.GetItemAttribute(bItemAttributes.ImageYDescOffset);
bItemAttribute xOffsetAttribute = slot.item.GetItemAttribute(bItemAttributes.ImageXDescOffset);
Vector3 imagePosition = displayItemImage.transform.localPosition;
float yOffset = 0;
float xOffset = 0;
if (yOffsetAttribute != null)
{
yOffset = yOffsetAttribute.value;
}
if (xOffsetAttribute != null)
{
xOffset = xOffsetAttribute.value;
}
displayItemImage.transform.localPosition = new Vector3(xOffset, yOffset, imagePosition.z);
if (secondaryItemImage) secondaryItemImage.sprite = _secondaryImage;
if (teriaryItemImage) teriaryItemImage.sprite = _teriaryImage;
if (slot.item.type == bItemType.Gemstones)
{
if (powerSwordImage && powerSwordImage.sprite)
{
powerSwordImage.gameObject.SetActive(true);
}
else //in case we have no valid weapons for gemstone
{
powerSwordImage.gameObject.SetActive(false);
}
// //for gemstones power value is constant
changeableAttributesText.gameObject.SetActive(true);
changeableAttributesText.text = "<color=blue>+" + _power.value.ToString() + " Quantum Charge</color>";
}
else if (_power != null) //powerable weapons
{
// < color = blue > (+15) </ color > Damage </ color >
//< color = purple > 0 < color = blue > (+30) </ color > Spectral Damage </ color ></ align >
changeableAttributesText.gameObject.SetActive(true);
changeableAttributesText.text = "<color=blue>" + _power.value.ToString() + "/100 Quantum Charge </color>";
if (_power.value > 0)
{
changeableAttributesText.text += "<color=grey>\n" + (_Damage.value * 2).ToString() + " Damage</color>" +
"<color=purple>\n" + (_Damage.value * 2).ToString() + " Spectral Damage</color>";
}
else
{
changeableAttributesText.text += "<color=grey>\n" + (_Damage.value).ToString() + " Damage</color>" +
"<color=purple>\n" + "0" + " Spectral Damage</color>";
}
}
else
{
if (changeableAttributesText)
{
changeableAttributesText.gameObject.SetActive(false);
}
if (powerSwordImage)
{
powerSwordImage.gameObject.SetActive(false);
}
}
if (descriptionTransform)
{
LayoutRebuilder.ForceRebuildLayoutImmediate(descriptionTransform);
}
}
//need to handle equip
private static bool ItemIsRarityInterested(bItemSlot slot)
{
return slot.item && slot.rarityInterestedType.Contains(slot.item.type);
}
private IEnumerator RebuildLayoutCoroutine()
{
yield return new WaitForSecondsRealtime(Time.fixedDeltaTime);
LayoutRebuilder.ForceRebuildLayoutImmediate(descriptionTransform);
}
public virtual void OnCancel()
{
onCancelSlot.Invoke();
}
public void BlockAllButGaze(bool b)
{
BlockSlots(b, 43);
}
public void BlockSlots(bool block, int exceptionItem)
{
foreach (var s in slots)
{
if (block)
{
if (s.item.id != exceptionItem)
{
s.Clickable = false;
}
}
else
{
s.Clickable = true;
}
}
}
}
}