using Godot; using System; using System.Collections.Generic; using System.Linq; using Cirno.Scripts; using Cirno.Scripts.Resources; public partial class InventoryManager : Node { public static InventoryManager Instance { get; private set; } public ItemsDatabase ItemsDatabase { get; set; } private Dictionary _itemsDict = new(); public List Items => _itemsDict.Where(x => x.Value.Count > 0).Select(x => x.Value).ToList(); [Signal] public delegate void ItemAddedEventHandler(LootItem item, int currentAmount); [Signal] public delegate void ItemRemovedEventHandler(string itemKey, int currentAmount); /// /// Use when equipping a weapon from the inventory screen /// [Signal] public delegate void WeaponEquipEventHandler(string itemKey); /// /// Use when updating the weapon shown on the hud /// [Signal] public delegate void WeaponUpdateEventHandler(string itemKey); [Signal] public delegate void ItemUsedEventHandler(LootItem itemKey, int totalCount); [Signal] public delegate void TotalAmmoChangedEventHandler(StringName ammoKey, int count); [Signal] public delegate void LoadedAmmoChangedEventHandler(StringName weaponKey, int count); public override void _Ready() { Instance = this; GD.Print("Loading items"); Load(GlobalState.Session.Items); } // Called every frame. 'delta' is the elapsed time since the previous frame. public override void _Process(double delta) { } public bool TryGetItem(string key, out ItemContainer item) { return _itemsDict.TryGetValue(key, out item); } public LootItem FindItemInDb(string key) { return ItemsDatabase.GetLootItem(key); } public bool HasItems(IList itemKeys) { return itemKeys.Aggregate(false, (current, item) => current || GetItemCount(item) > 0); } public int GetItemCount(string itemKey) { return _itemsDict.TryGetValue(itemKey, out var itm) ? itm.Count : 0; } public int RemoveItem(LootItem item) { return RemoveItem(item.ItemKey, 9999); } public int RemoveItem(string itemKey, int amount) { if (!_itemsDict.TryGetValue(itemKey, out var itm)) return 0; int removed = Math.Min(itm.Count, amount); itm.Count -= amount; if (itm.Count < 0) { itm.Count = 0; //_itemsDict.Remove(itemKey); } EmitSignal(SignalName.ItemRemoved, itemKey, itm.Count); if (itm.Item.Item is ItemTypes.Ammo) { EmitSignal(SignalName.TotalAmmoChanged, itemKey, itm.Count); } return removed; } public bool CanAddItem(string itemKey) { var found = TryGetItem(itemKey, out var itm); if (found) { return (itm.Count < itm.Item.Max); } var dbItem = FindItemInDb(itemKey); return dbItem != null; } public bool AddItem(LootItem item) { //var item = new LootItem() { Item = type, Amount = amount }; if (!_itemsDict.TryGetValue(item.ItemKey, out var itm)) { _itemsDict.Add(item.ItemKey, new ItemContainer() { Item = item, Count = item.Amount, }); GD.Print($"Added new ({item.ItemKey}) {item.Item} x{item.Amount}"); EmitSignal(SignalName.ItemAdded, item, item.Amount); } else { if (itm.Count < item.Max) { itm.Count += item.Amount; } else { if (item.PickupIfMaxed) { itm.Count = item.Max; } else { return false; } } EmitSignal(SignalName.ItemAdded, item, itm.Count); } return true; } public bool UseItem(StringName itemKey) { if (!_itemsDict.TryGetValue(itemKey, out var itm)) return false; if (itm.Count == 0) return false; GD.Print($"Used item in manager {itemKey}"); switch (itm.Item.Item) { case ItemTypes.Medkit: case ItemTypes.FrogBomb: case ItemTypes.Bomb: case ItemTypes.Mine: case ItemTypes.Battery: EmitSignal(SignalName.ItemUsed, itm.Item, itm.Count); if (itm.Item.ConsumeOnUse) { RemoveItem(itm.Item.ItemKey, 1); } break; case ItemTypes.Weapon: // Equip weapon EmitSignal(SignalName.WeaponEquip, itm.Item.ItemKey); break; } return true; } public void NotifyLoadedAmmoChange(StringName weaponDataItemKey, int loadedAmmo) { EmitSignal(SignalName.LoadedAmmoChanged, weaponDataItemKey, loadedAmmo); } public Godot.Collections.Dictionary Save() { Godot.Collections.Dictionary dict = new(); foreach (var item in _itemsDict) { dict.Add(item.Key, item.Value.Count); } return dict; } public void Load(Godot.Collections.Dictionary items) { ItemsDatabase = ResourceLoader.Load("uid://cdi84udi6gldt"); _itemsDict.Clear(); _itemsDict = items.ToDictionary(x => x.Key, x => new ItemContainer() { Item = ItemsDatabase.LootItems.FirstOrDefault(y => y.ItemKey == x.Key), Count = x.Value }); GD.Print($"Items after loading: {_itemsDict.Count}"); } public void UpdateEquippedWeapon(string itemKey) { EmitSignalWeaponUpdate(itemKey); } } public class ItemContainer { public LootItem Item { get; set; } public int Count { get; set; } }