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(params T[] itemsToExclude) where T : IBaseInventoryItem { var itemsToSelectFrom = Items.OfType(); return PickItemInternal(itemsToSelectFrom, itemsToExclude); } public T PickRareItem(params T[] itemsToExclude) where T : IBaseInventoryItem { var getRareItems = Items.OfType().Where(x => x.SpawnRate < 0.1f); return PickItemInternal(getRareItems, itemsToExclude); } public T PickBasicItem(params T[] itemsToExclude) where T : IBaseInventoryItem { var getBasicItems = Items.OfType().Where(x => x.SpawnRate > 0.5f); return PickItemInternal(getBasicItems, itemsToExclude); } private T PickItemInternal(IEnumerable itemsToSelectFrom, params T[] itemsToExclude) where T : IBaseInventoryItem { var rng = new RandomNumberGenerator(); rng.Randomize(); if (itemsToExclude.Any()) itemsToSelectFrom.Except(itemsToExclude); var weights = itemsToSelectFrom.Select(x => x.SpawnRate).ToArray(); var selectedItem = itemsToSelectFrom.ToArray()[rng.RandWeighted(weights)]; return 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/"); var boxResources = DirAccess.GetFilesAt("res://src/items/box/resources/"); var ammoResources = DirAccess.GetFilesAt("res://src/items/ammo/resources/"); var jewelResources = DirAccess.GetFilesAt("res://src/items/jewels/resources/"); foreach (var armor in armorResources) { var armorInfo = GD.Load($"res://src/items/armor/resources/{armor}".TrimSuffix(".remap")); 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}".TrimSuffix(".remap")); 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}".TrimSuffix(".remap")); 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}".TrimSuffix(".remap")); 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}".TrimSuffix(".remap")); 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}".TrimSuffix(".remap")); var effectItemScene = ResourceLoader.Load("res://src/items/effect/EffectItem.tscn").Instantiate(); effectItemScene.Stats = effectItemInfo; if (!database.Contains(effectItemScene)) database.Add(effectItemScene); } foreach (var boxItem in boxResources) { var boxItemInfo = GD.Load($"res://src/items/box/resources/{boxItem}".TrimSuffix(".remap")); var boxItemScene = ResourceLoader.Load("res://src/items/box/BoxItem.tscn").Instantiate(); boxItemScene.Stats = boxItemInfo; if (!database.Contains(boxItemScene)) database.Add(boxItemScene); } foreach (var ammoItem in ammoResources) { var ammoItemInfo = GD.Load($"res://src/items/ammo/resources/{ammoItem}".TrimSuffix(".remap")); var ammoItemScene = ResourceLoader.Load("res://src/items/ammo/Ammo.tscn").Instantiate(); ammoItemScene.Stats = ammoItemInfo; if (!database.Contains(ammoItemScene)) database.Add(ammoItemScene); } foreach (var jewelItem in jewelResources) { var jewelItemInfo = GD.Load($"res://src/items/jewels/resources/{jewelItem}".TrimSuffix(".remap")); var jewelItemScene = ResourceLoader.Load("res://src/items/jewels/Jewel.tscn").Instantiate(); jewelItemScene.Stats = jewelItemInfo; if (!database.Contains(jewelItemScene)) database.Add(jewelItemScene); } Items = [.. database]; } }