using System; using System.Collections.Generic; using System.Linq; using Assets.HeroEditor4D.Common.Scripts.Common; using Assets.HeroEditor4D.InventorySystem.Scripts.Data; using Assets.HeroEditor4D.InventorySystem.Scripts.Enums; using Assets.HeroEditor4D.InventorySystem.Scripts.Elements; using UnityEngine; using UnityEngine.UI; namespace Assets.HeroEditor4D.InventorySystem.Scripts { /// /// High-level inventory interface. /// public class InventoryBase : ItemWorkspace { public Equipment Equipment; public ScrollInventory PlayerInventory; public ScrollInventory Materials; public Button EquipButton; public Button RemoveButton; public Button CraftButton; public Button LearnButton; public Button UseButton; public Button AssembleButton; public AudioClip EquipSound; public AudioClip CraftSound; public AudioClip UseSound; public AudioSource AudioSource; public bool InitializeExample; // These callbacks can be used outside; public Action OnRefresh; public Action OnEquip; public Func CanEquip = i => true; public void Awake() { ItemCollection.Active = ItemCollection; } public void Start() { if (InitializeExample) { TestInitialize(); } } /// /// Initialize owned items (just for example). /// public void TestInitialize() { var inventory = ItemCollection.Active.Items.Select(i => new Item(i.Id)).ToList(); // inventory.Clear(); var equipped = new List(); Initialize(ref inventory, ref equipped, 6, null); } public void Initialize(ref List inventory, ref List equipped, int bagSize, Action onRefresh) { RegisterCallbacks(); PlayerInventory.Initialize(ref inventory); Equipment.SetBagSize(bagSize); Equipment.Initialize(ref equipped); Equipment.OnRefresh = onRefresh; if (!Equipment.SelectAny() && !PlayerInventory.SelectAny()) { ItemInfo.Reset(); } } public void RegisterCallbacks() { InventoryItem.OnLeftClick = SelectItem; InventoryItem.OnRightClick = InventoryItem.OnDoubleClick = QuickAction; } private void QuickAction(Item item) { SelectItem(item); if (Equipment.Items.Contains(item)) { Remove(); } else if (CanEquipSelectedItem()) { Equip(); } } public void SelectItem(Item item) { SelectedItem = item; ItemInfo.Initialize(SelectedItem, SelectedItem.Params.Price); Refresh(); } public void Equip() { if (!CanEquip(SelectedItem)) return; var equipped = SelectedItem.IsFirearm ? Equipment.Items.Where(i => i.IsFirearm).ToList() : Equipment.Items.Where(i => i.Params.Type == SelectedItem.Params.Type && !i.IsFirearm).ToList(); if (equipped.Any()) { AutoRemove(equipped, Equipment.Slots.Count(i => i.Supports(SelectedItem))); } if (SelectedItem.IsTwoHanded) AutoRemove(Equipment.Items.Where(i => i.IsShield).ToList()); if (SelectedItem.IsShield) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsTwoHanded).ToList()); if (SelectedItem.IsFirearm) AutoRemove(Equipment.Items.Where(i => i.IsShield).ToList()); if (SelectedItem.IsFirearm) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsTwoHanded).ToList()); if (SelectedItem.IsTwoHanded || SelectedItem.IsShield) AutoRemove(Equipment.Items.Where(i => i.IsWeapon && i.IsFirearm).ToList()); MoveItem(SelectedItem, PlayerInventory, Equipment); AudioSource.PlayOneShot(EquipSound, SfxVolume); OnEquip?.Invoke(SelectedItem); } public void Remove() { MoveItem(SelectedItem, Equipment, PlayerInventory); SelectItem(SelectedItem); AudioSource.PlayOneShot(EquipSound, SfxVolume); } public void Craft() { var materials = MaterialList; if (CanCraft(materials)) { materials.ForEach(i => PlayerInventory.Items.Single(j => j.Hash == i.Hash).Count -= i.Count); PlayerInventory.Items.RemoveAll(i => i.Count == 0); var itemId = SelectedItem.Params.FindProperty(PropertyId.Craft).Value; var existed = PlayerInventory.Items.SingleOrDefault(i => i.Id == itemId && i.Modifier == null); if (existed == null) { PlayerInventory.Items.Add(new Item(itemId)); } else { existed.Count++; } PlayerInventory.Refresh(SelectedItem); CraftButton.interactable = CanCraft(materials); AudioSource.PlayOneShot(CraftSound, SfxVolume); } else { Debug.Log("No materials."); } } public void Learn() { // Implement your logic here! } public void Use() { Use(UseSound); } public void Use(AudioClip sound) { if (SelectedItem.Count == 1) { PlayerInventory.Items.Remove(SelectedItem); SelectedItem = PlayerInventory.Items.FirstOrDefault(); if (SelectedItem == null) { PlayerInventory.Refresh(null); SelectedItem = Equipment.Items.FirstOrDefault(); if (SelectedItem != null) { Equipment.Refresh(SelectedItem); } } else { PlayerInventory.Refresh(SelectedItem); } } else { SelectedItem.Count--; PlayerInventory.Refresh(SelectedItem); } Equipment.OnRefresh?.Invoke(); if (sound != null) { AudioSource.PlayOneShot(sound, SfxVolume); } } public Item Assemble() { if (SelectedItem != null && SelectedItem.Params.Type == ItemType.Fragment && SelectedItem.Count >= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt) { SelectedItem.Count -= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt; var crafted = new Item(SelectedItem.Params.FindProperty(PropertyId.Craft).Value); var existed = PlayerInventory.Items.SingleOrDefault(i => i.Hash == crafted.Hash); if (existed == null) { PlayerInventory.Items.Add(crafted); } else { existed.Count++; } if (SelectedItem.Count == 0) { PlayerInventory.Items.Remove(SelectedItem); SelectedItem = crafted; } PlayerInventory.Refresh(SelectedItem); return crafted; } return null; } public override void Refresh() { if (SelectedItem == null) { ItemInfo.Reset(); EquipButton.SetActive(false); RemoveButton.SetActive(false); } else { var equipped = Equipment.Items.Contains(SelectedItem); EquipButton.SetActive(!equipped && CanEquipSelectedItem()); RemoveButton.SetActive(equipped); } UseButton.SetActive(SelectedItem != null && CanUse()); AssembleButton.SetActive(SelectedItem != null && SelectedItem.Params.Type == ItemType.Fragment && SelectedItem.Count >= SelectedItem.Params.FindProperty(PropertyId.Fragments).ValueInt); var receipt = SelectedItem != null && SelectedItem.Params.Type == ItemType.Recipe; if (CraftButton != null) CraftButton.SetActive(false); if (LearnButton != null) LearnButton.SetActive(false); if (receipt) { if (LearnButton == null) { var materialSelected = !PlayerInventory.Items.Contains(SelectedItem) && !Equipment.Items.Contains(SelectedItem); CraftButton.SetActive(true); Materials.SetActive(materialSelected); Equipment.Scheme.SetActive(!materialSelected); var materials = MaterialList; Materials.Initialize(ref materials); } else { LearnButton.SetActive(true); } } OnRefresh?.Invoke(SelectedItem); } private List MaterialList => SelectedItem.Params.FindProperty(PropertyId.Materials).Value.Split(',').Select(i => i.Split(':')).Select(i => new Item(i[0], int.Parse(i[1]))).ToList(); private bool CanEquipSelectedItem() { return PlayerInventory.Items.Contains(SelectedItem) && Equipment.Slots.Any(i => i.Supports(SelectedItem)); } private bool CanUse() { switch (SelectedItem.Params.Type) { case ItemType.Container: case ItemType.Booster: case ItemType.Coupon: return true; default: return false; } } private bool CanCraft(List materials) { return materials.All(i => PlayerInventory.Items.Any(j => j.Hash == i.Hash && j.Count >= i.Count)); } /// /// Automatically removes items if target slot is busy. /// private void AutoRemove(List items, int max = 1) { long sum = 0; foreach (var p in items) { sum += p.Count; } if (sum == max) { MoveItemSilent(items.LastOrDefault(i => i.Id != SelectedItem.Id) ?? items.Last(), Equipment, PlayerInventory); } } } }