using Godot; using System; using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; using Zennysoft.Ma.Adapter; namespace Zennysoft.Game.Ma; public class ItemDatabase { private static readonly Lazy lazy = new Lazy(() => new ItemDatabase()); public static ItemDatabase Instance { get { return lazy.Value; } } public ImmutableList Items { get; set; } public T PickItem(T itemToExclude = null) where T : InventoryItem { var itemsToSelectFrom = Items; return PickItemInternal(itemsToSelectFrom, itemToExclude); } public T PickRareItem(T itemToExclude = null) where T : InventoryItem { var getRareItems = Items.Where(x => x.SpawnRate < 0.1f); return PickItemInternal(getRareItems, itemToExclude); } public T PickBasicItem(T itemToExclude = null) where T : InventoryItem { var getBasicItems = Items.Where(x => x.SpawnRate > 0.5f); return PickItemInternal(getBasicItems, itemToExclude); } private T PickItemInternal(IEnumerable itemsToSelectFrom, T itemToExclude = null) where T : InventoryItem { var rng = new RandomNumberGenerator(); rng.Randomize(); if (itemToExclude is not null) itemsToSelectFrom = [.. itemsToSelectFrom.OfType().Where(x => x.ItemName != itemToExclude.ItemName)]; var weights = itemsToSelectFrom.Select(x => x.SpawnRate).ToArray(); var selectedItem = itemsToSelectFrom.ToArray()[rng.RandWeighted(weights)]; if (selectedItem is ThrowableItem throwableItem) throwableItem.SetCount(rng.RandiRange(throwableItem.Stats.MinimumCount, throwableItem.Stats.MaximumCount)); return (T)selectedItem; } private ItemDatabase() { var database = new List(); var armorResources = DirAccess.GetFilesAt("res://src/items/armor/resources/"); var weaponResources = DirAccess.GetFilesAt("res://src/items/weapons/resources/"); var accessoryResources = DirAccess.GetFilesAt("res://src/items/accessory/resources/"); var throwableResources = DirAccess.GetFilesAt("res://src/items/throwable/resources/"); var consumableResources = DirAccess.GetFilesAt("res://src/items/consumable/resources/"); var effectResources = DirAccess.GetFilesAt("res://src/items/effect/resources/"); foreach (var armor in armorResources) { var armorInfo = GD.Load($"res://src/items/armor/resources/{armor}"); var armorScene = ResourceLoader.Load("res://src/items/armor/Armor.tscn").Instantiate(); armorScene.Stats = armorInfo; if (!database.Contains(armorScene)) database.Add(armorScene); } foreach (var weapon in weaponResources) { var weaponInfo = GD.Load($"res://src/items/weapons/resources/{weapon}"); var weaponScene = ResourceLoader.Load("res://src/items/weapons/Weapon.tscn").Instantiate(); weaponScene.Stats = weaponInfo; if (!database.Contains(weaponScene)) database.Add(weaponScene); } foreach (var accessory in accessoryResources) { var accessoryInfo = GD.Load($"res://src/items/accessory/resources/{accessory}"); var accessoryScene = ResourceLoader.Load("res://src/items/accessory/Accessory.tscn").Instantiate(); accessoryScene.Stats = accessoryInfo; if (!database.Contains(accessoryScene)) database.Add(accessoryScene); } foreach (var throwable in throwableResources) { var throwableItemInfo = GD.Load($"res://src/items/throwable/resources/{throwable}"); var throwableItemScene = ResourceLoader.Load("res://src/items/throwable/ThrowableItem.tscn").Instantiate(); throwableItemScene.Stats = throwableItemInfo; if (!database.Contains(throwableItemScene)) database.Add(throwableItemScene); } foreach (var consumable in consumableResources) { var consumableItemInfo = GD.Load($"res://src/items/consumable/resources/{consumable}"); var consumableItemScene = ResourceLoader.Load("res://src/items/consumable/ConsumableItem.tscn").Instantiate(); consumableItemScene.Stats = consumableItemInfo; if (!database.Contains(consumableItemScene)) database.Add(consumableItemScene); } foreach (var effectItem in effectResources) { var effectItemInfo = GD.Load($"res://src/items/effect/resources/{effectItem}"); var effectItemScene = ResourceLoader.Load("res://src/items/effect/EffectItem.tscn").Instantiate(); effectItemScene.Stats = effectItemInfo; if (!database.Contains(effectItemScene)) database.Add(effectItemScene); } Items = [.. database]; } }