using Chickensoft.AutoInject; using Chickensoft.Introspection; using Chickensoft.Serialization; using Godot; using System; using System.Collections.Generic; using System.Linq; using Zennysoft.Game.Abstractions; using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; [Meta(typeof(IAutoNode)), Id("inventory")] public partial class Inventory : Node, IInventory { public override void _Notification(int what) => this.Notify(what); // TODO: Constants class with export private const int _maxInventorySize = 20; public event Action BroadcastMessage; public event Action InventoryChanged; public Inventory() { Items = []; } [Save("inventory_items")] public List Items { get; private set; } public bool PickUpItem(InventoryItem item) { var isAdded = TryAdd(item); if (isAdded) { BroadcastMessage?.Invoke($"{item.ItemName} picked up."); SfxDatabase.Instance.Play(SoundEffect.PickupItem); } else BroadcastMessage?.Invoke($"Could not pick up {item.ItemName}."); return isAdded; } public bool TryAdd(InventoryItem inventoryItem) { if (Items.Count >= _maxInventorySize) return false; Items.Add(inventoryItem); InventoryChanged?.Invoke(); return true; } public bool TryInsert(InventoryItem inventoryItem, int index) { if (Items.Count >= _maxInventorySize || index >= _maxInventorySize || index < 0) return false; Items.Insert(index, inventoryItem); InventoryChanged?.Invoke(); return true; } public void Remove(InventoryItem inventoryItem) { Items.Remove(inventoryItem); InventoryChanged?.Invoke(); } public bool Sort(EquipableItem currentWeapon, EquipableItem currentArmor, EquipableItem currentAccessory) { var initialList = Items; var equippedWeapon = Items.OfType().Where(x => x == currentWeapon); var equippedArmor = Items.OfType().Where(x => x == currentArmor); var equippedAccessory = Items.OfType().Where(x => x == currentAccessory); var equippedItems = new List(); equippedItems.AddRange(equippedWeapon); equippedItems.AddRange(equippedArmor); equippedItems.AddRange(equippedAccessory); var listToSort = Items.Except(equippedItems); var weapons = listToSort.Where(x => x is Weapon).OrderBy(x => x as Weapon, new WeaponComparer()); var armor = listToSort.Where(x => x is Armor).OrderBy(x => x as Armor, new ArmorComparer()); var accessories = listToSort.Where(x => x is Accessory).OrderBy(x => x as Accessory, new AccessoryComparer()); var consumables = listToSort.Where(x => x is ConsumableItem).OrderBy(x => x as ConsumableItem, new ConsumableComparer()); var throwables = listToSort.Where(x => x is ThrowableItem).OrderBy(x => x as ThrowableItem, new ThrowableComparer()); var effectItems = listToSort.Where(x => x is EffectItem).OrderBy(x => x as EffectItem, new EffectComparer()); Items = [.. equippedItems, .. weapons, .. armor, .. accessories, .. consumables, .. throwables, .. effectItems]; var stackableItems = Items.OfType(); var itemsToStack = stackableItems.GroupBy(x => ((InventoryItem)x).ItemName).Where(x => x.Count() > 1); foreach (var itemStack in itemsToStack) { var firstItem = itemStack.First(); firstItem.SetCount(itemStack.Count()); var itemsToRemove = itemStack.Except([firstItem]).Cast(); Items = [.. Items.Except(itemsToRemove)]; } return !Items.SequenceEqual(initialList); } public class WeaponComparer : IComparer { public int Compare(Weapon x, Weapon y) { if (x.BonusAttack == y.BonusAttack) return x.ItemName.CompareTo(y.ItemName); return x.BonusAttack < y.BonusAttack ? 1 : -1; } } public class ArmorComparer : IComparer { public int Compare(Armor x, Armor y) { if (x.BonusDefense == y.BonusDefense) return x.ItemName.CompareTo(y.ItemName); return x.BonusDefense < y.BonusDefense ? 1 : -1; } } public class AccessoryComparer : IComparer { public int Compare(Accessory x, Accessory y) { return x.ItemName.CompareTo(y.ItemName); } } public class ConsumableComparer : IComparer { public int Compare(ConsumableItem x, ConsumableItem y) { return x.ItemName.CompareTo(y.ItemName); } } public class ThrowableComparer : IComparer { public int Compare(ThrowableItem x, ThrowableItem y) { return x.ItemName.CompareTo(y.ItemName); } } public class EffectComparer : IComparer { public int Compare(EffectItem x, EffectItem y) { return x.ItemName.CompareTo(y.ItemName); } } }