using Kryz.CharacterStats.Examples; using System.Collections.Generic; using UnityEngine; public class EquippableItemGenerator : MonoBehaviour { [Header("Generation Settings")] public int minStatRolls = 2; public int maxStatRolls = 6; public float baseStatValue = 10f; public float statVariance = 0.3f; // 30% variance public float percentStatBaseValue = 0.05f; // 5% base for percent stats // Add this field to your EquippableItemGenerator class [Header("Path Mapping")] private Dictionary spritePathMap = new Dictionary(); [Header("Stat Roll Weights by Equipment Type")] [SerializeField] private StatWeights armorWeights = new StatWeights(); [SerializeField] private StatWeights weaponWeights = new StatWeights(); public List HelmetIcons = new List(); public List ShoulderIcons = new List(); public List ChestIcons = new List(); public List BeltIcons = new List(); public List LegsIcons = new List(); public List BracersIcons = new List(); public List GlovesIcons = new List(); public List BootsIcons = new List(); public List StaffIcons = new List(); public List SpearIcons = new List(); public List ScytheIcons = new List(); public List HammerIcons = new List(); public List BowIcons = new List(); public List CrossbowIcons = new List(); public List AxeIcons = new List(); public List SwordIcons = new List(); public List ShieldIcons = new List(); public List DaggerIcons = new List(); public List BookIcons = new List(); [System.Serializable] public class StatWeights { [Header("Damage Stats")] public float attackDamage = 1f; public float spellDamage = 1f; public float critChance = 0.8f; public float critDamage = 0.8f; [Header("Defensive Stats")] public float maxHealth = 1f; public float armor = 1f; public float magicResistance = 1f; public float dodgeChance = 0.6f; public float blockChance = 0.4f; public float blockEffectiveness = 0.4f; [Header("Resource Stats")] public float healthRegen = 0.7f; public float maxMana = 0.8f; public float manaRegen = 0.7f; [Header("Utility Stats")] public float attackSpeed = 0.8f; public float areaEffectiveness = 0.5f; public float cooldownReduction = 0.6f; public float movementSpeed = 0.4f; public float reputationGain = 0.3f; public float goldCostReduction = 0.3f; } public enum ItemTier { Common, Uncommon, Rare, Epic, Legendary } #region Singleton private static EquippableItemGenerator _instance; // Public reference to the singleton instance public static EquippableItemGenerator Instance { get { // If the instance doesn't exist, try to find it in the scene if (_instance == null) { _instance = FindObjectOfType(); } return _instance; } } #endregion private void Awake() { UpdateListsFromResources(); } [ContextMenu("Update Lists From Resources")] private void UpdateListsFromResources() { // Clear existing mappings if (spritePathMap == null) spritePathMap = new Dictionary(); spritePathMap.Clear(); // Armor pieces HelmetIcons.Clear(); Sprite[] helmetSprites = Resources.LoadAll("Armor/Helmets"); foreach (Sprite sprite in helmetSprites) { HelmetIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Helmets/{sprite.name}"; } ShoulderIcons.Clear(); Sprite[] shoulderSprites = Resources.LoadAll("Armor/Shoulders"); foreach (Sprite sprite in shoulderSprites) { ShoulderIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Shoulders/{sprite.name}"; } ChestIcons.Clear(); Sprite[] chestSprites = Resources.LoadAll("Armor/Chests"); foreach (Sprite sprite in chestSprites) { ChestIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Chests/{sprite.name}"; } BeltIcons.Clear(); Sprite[] beltSprites = Resources.LoadAll("Armor/Belts"); foreach (Sprite sprite in beltSprites) { BeltIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Belts/{sprite.name}"; } LegsIcons.Clear(); Sprite[] legsSprites = Resources.LoadAll("Armor/Legs"); foreach (Sprite sprite in legsSprites) { LegsIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Legs/{sprite.name}"; } BracersIcons.Clear(); Sprite[] bracersSprites = Resources.LoadAll("Armor/Bracers"); foreach (Sprite sprite in bracersSprites) { BracersIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Bracers/{sprite.name}"; } GlovesIcons.Clear(); Sprite[] glovesSprites = Resources.LoadAll("Armor/Gloves"); foreach (Sprite sprite in glovesSprites) { GlovesIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Gloves/{sprite.name}"; } BootsIcons.Clear(); Sprite[] bootsSprites = Resources.LoadAll("Armor/Boots"); foreach (Sprite sprite in bootsSprites) { BootsIcons.Add(sprite); spritePathMap[sprite] = $"Armor/Boots/{sprite.name}"; } // Two-handed weapons StaffIcons.Clear(); Sprite[] staffSprites = Resources.LoadAll("Weapons/Staffs"); foreach (Sprite sprite in staffSprites) { StaffIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Staffs/{sprite.name}"; } SpearIcons.Clear(); Sprite[] spearSprites = Resources.LoadAll("Weapons/Spears"); foreach (Sprite sprite in spearSprites) { SpearIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Spears/{sprite.name}"; } ScytheIcons.Clear(); Sprite[] scytheSprites = Resources.LoadAll("Weapons/Scythes"); foreach (Sprite sprite in scytheSprites) { ScytheIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Scythes/{sprite.name}"; } HammerIcons.Clear(); Sprite[] hammerSprites = Resources.LoadAll("Weapons/Hammers"); foreach (Sprite sprite in hammerSprites) { HammerIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Hammers/{sprite.name}"; } BowIcons.Clear(); Sprite[] bowSprites = Resources.LoadAll("Weapons/Bows"); foreach (Sprite sprite in bowSprites) { BowIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Bows/{sprite.name}"; } CrossbowIcons.Clear(); Sprite[] crossbowSprites = Resources.LoadAll("Weapons/Crossbows"); foreach (Sprite sprite in crossbowSprites) { CrossbowIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Crossbows/{sprite.name}"; } AxeIcons.Clear(); Sprite[] axeSprites = Resources.LoadAll("Weapons/Axes"); foreach (Sprite sprite in axeSprites) { AxeIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Axes/{sprite.name}"; } // One-handed weapons SwordIcons.Clear(); Sprite[] swordSprites = Resources.LoadAll("Weapons/Swords"); foreach (Sprite sprite in swordSprites) { SwordIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Swords/{sprite.name}"; } ShieldIcons.Clear(); Sprite[] shieldSprites = Resources.LoadAll("Weapons/Shields"); foreach (Sprite sprite in shieldSprites) { ShieldIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Shields/{sprite.name}"; } DaggerIcons.Clear(); Sprite[] daggerSprites = Resources.LoadAll("Weapons/Daggers"); foreach (Sprite sprite in daggerSprites) { DaggerIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Daggers/{sprite.name}"; } BookIcons.Clear(); Sprite[] bookSprites = Resources.LoadAll("Weapons/Books"); foreach (Sprite sprite in bookSprites) { BookIcons.Add(sprite); spritePathMap[sprite] = $"Weapons/Books/{sprite.name}"; } Debug.Log($"Updated all icon lists from Resources folders. Loaded {spritePathMap.Count} sprites with paths."); } public EquippableItemInstance GenerateEquippableItemInstance() { EquippableItemInstance generatedItem = new EquippableItemInstance(); //Do stuff return generatedItem; } [ContextMenu("Generate Random Item To Inventory")] private void TestGenerateItemToInventory() { EquipmentType typeToGenerate = (EquipmentType)Random.Range(0, 10); if (typeToGenerate == EquipmentType.Weapon1 || typeToGenerate == EquipmentType.Weapon2) { WeaponType weaponType = (WeaponType)Random.Range(0, 11); Inventory.Instance.AddItem(GenerateWeapon(weaponType, (ItemTier)Random.Range(0, 5), 1)); } else { Inventory.Instance.AddItem(GenerateEquippableItemInstance(typeToGenerate, (ItemTier)Random.Range(0, 5), 1)); } } public EquippableItemInstance GenerateEquippableItemInstance(EquipmentType equipmentType, ItemTier tier = ItemTier.Common, int playerLevel = 1) { EquippableItemInstance item = new EquippableItemInstance(); // Set basic properties item.EquipmentType = equipmentType; item.ItemName = GenerateItemName(equipmentType, tier); item.Icon = GetRandomIcon(equipmentType, item); Debug.Log("Generated: " + item.ItemName + " icon " + item.Icon.name); // Set weapon type if it's a weapon if (equipmentType == EquipmentType.Weapon1 || equipmentType == EquipmentType.Weapon2) { item.WeaponType = GetRandomWeaponType(); } // Generate stats based on tier and level GenerateStatsForItem(item, tier, playerLevel); Debug.Log("Generated: " + item.ItemName + " icon " + item.Icon.name); return item; } // Generate weapon by weapon type (recommended approach) public EquippableItemInstance GenerateWeapon(WeaponType weaponType, ItemTier tier = ItemTier.Common, int playerLevel = 1) { EquippableItemInstance item = new EquippableItemInstance(); // All weapons use Weapon1 as default - the equipment system handles slot assignment item.EquipmentType = EquipmentType.Weapon1; item.WeaponType = weaponType; item.ItemName = GenerateWeaponName(weaponType, tier); item.Icon = GetWeaponIcon(weaponType, item); Debug.Log("Generated: " + item.ItemName + " icon " + item.Icon.name); GenerateStatsForItem(item, tier, playerLevel); Debug.Log("Generated: " + item.ItemName + " icon " + item.Icon.name); return item; } // Alternative: Let caller specify which slot they want public EquippableItemInstance GenerateWeapon(WeaponType weaponType, EquipmentType weaponSlot, ItemTier tier = ItemTier.Common, int playerLevel = 1) { if (weaponSlot != EquipmentType.Weapon1 && weaponSlot != EquipmentType.Weapon2) weaponSlot = EquipmentType.Weapon1; // Default fallback EquippableItemInstance item = new EquippableItemInstance(); item.EquipmentType = weaponSlot; item.WeaponType = weaponType; item.ItemName = GenerateWeaponName(weaponType, tier); item.Icon = GetWeaponIcon(weaponType, item); GenerateStatsForItem(item, tier, playerLevel); return item; } private void GenerateStatsForItem(EquippableItemInstance item, ItemTier tier, int playerLevel) { // Determine number of stats based on tier int statCount = GetStatCountForTier(tier); float levelMultiplier = 1f + (playerLevel - 1) * 0.1f; // 10% increase per level float tierMultiplier = GetTierMultiplier(tier); // Get appropriate stat weights StatWeights weights = item.IsWeapon ? weaponWeights : armorWeights; // Roll stats HashSet rolledStats = new HashSet(); for (int i = 0; i < statCount; i++) { RollRandomStat(item, weights, rolledStats, levelMultiplier * tierMultiplier); } } private int GetStatCountForTier(ItemTier tier) { return tier switch { ItemTier.Common => Random.Range(1, 3), ItemTier.Uncommon => Random.Range(2, 4), ItemTier.Rare => Random.Range(3, 5), ItemTier.Epic => Random.Range(4, 6), ItemTier.Legendary => Random.Range(5, 7), _ => 2 }; } private float GetTierMultiplier(ItemTier tier) { return tier switch { ItemTier.Common => 1f, ItemTier.Uncommon => 1.3f, ItemTier.Rare => 1.7f, ItemTier.Epic => 2.2f, ItemTier.Legendary => 3f, _ => 1f }; } private void RollRandomStat(EquippableItemInstance item, StatWeights weights, HashSet rolledStats, float multiplier) { // Create weighted list of available stats List<(string stat, float weight)> availableStats = new List<(string, float)>(); // Add damage stats if not already rolled if (!rolledStats.Contains("AttackDamage")) availableStats.Add(("AttackDamage", weights.attackDamage)); if (!rolledStats.Contains("SpellDamage")) availableStats.Add(("SpellDamage", weights.spellDamage)); if (!rolledStats.Contains("CritChance")) availableStats.Add(("CritChance", weights.critChance)); if (!rolledStats.Contains("CritDamage")) availableStats.Add(("CritDamage", weights.critDamage)); // Add defensive stats if (!rolledStats.Contains("MaxHealth")) availableStats.Add(("MaxHealth", weights.maxHealth)); if (!rolledStats.Contains("Armor")) availableStats.Add(("Armor", weights.armor)); if (!rolledStats.Contains("MagicResistance")) availableStats.Add(("MagicResistance", weights.magicResistance)); if (!rolledStats.Contains("DodgeChance")) availableStats.Add(("DodgeChance", weights.dodgeChance)); if (!rolledStats.Contains("BlockChance")) availableStats.Add(("BlockChance", weights.blockChance)); if (!rolledStats.Contains("BlockEffectiveness")) availableStats.Add(("BlockEffectiveness", weights.blockEffectiveness)); // Add resource stats if (!rolledStats.Contains("HealthRegen")) availableStats.Add(("HealthRegen", weights.healthRegen)); if (!rolledStats.Contains("MaxMana")) availableStats.Add(("MaxMana", weights.maxMana)); if (!rolledStats.Contains("ManaRegen")) availableStats.Add(("ManaRegen", weights.manaRegen)); // Add utility stats if (!rolledStats.Contains("AttackSpeed")) availableStats.Add(("AttackSpeed", weights.attackSpeed)); if (!rolledStats.Contains("AreaEffectiveness")) availableStats.Add(("AreaEffectiveness", weights.areaEffectiveness)); if (!rolledStats.Contains("CooldownReduction")) availableStats.Add(("CooldownReduction", weights.cooldownReduction)); if (!rolledStats.Contains("MovementSpeed")) availableStats.Add(("MovementSpeed", weights.movementSpeed)); if (!rolledStats.Contains("ReputationGain")) availableStats.Add(("ReputationGain", weights.reputationGain)); if (!rolledStats.Contains("GoldCostReduction")) availableStats.Add(("GoldCostReduction", weights.goldCostReduction)); if (availableStats.Count == 0) return; // Weighted random selection string selectedStat = SelectWeightedRandom(availableStats); rolledStats.Add(selectedStat); // Apply the stat ApplyStatToItem(item, selectedStat, multiplier); } private string SelectWeightedRandom(List<(string stat, float weight)> weightedStats) { float totalWeight = 0f; foreach (var stat in weightedStats) totalWeight += stat.weight; float randomValue = Random.Range(0f, totalWeight); float currentWeight = 0f; foreach (var stat in weightedStats) { currentWeight += stat.weight; if (randomValue <= currentWeight) return stat.stat; } return weightedStats[0].stat; // Fallback } private void ApplyStatToItem(EquippableItemInstance item, string statName, float multiplier) { // Decide between flat or percent bonus (roughly 60% flat, 40% percent) bool usePercent = Random.value < 0.4f; switch (statName) { case "AttackDamage": if (usePercent) item.AttackDamagePercentBonus = GeneratePercentStat(multiplier); else item.AttackDamageBonus = GenerateFlatStat(multiplier); break; case "SpellDamage": if (usePercent) item.SpellDamagePercentBonus = GeneratePercentStat(multiplier); else item.SpellDamageBonus = GenerateFlatStat(multiplier); break; case "CritChance": if (usePercent) item.CritChancePercentBonus = GeneratePercentStat(multiplier * 0.3f); // Lower values for crit else item.CritChanceBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 0.5f)); break; case "CritDamage": if (usePercent) item.CritDamagePercentBonus = GeneratePercentStat(multiplier * 0.5f); else item.CritDamageBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 0.8f)); break; case "MaxHealth": if (usePercent) item.MaxHealthPercentBonus = GeneratePercentStat(multiplier); else item.MaxHealthBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 5f)); // Health gets higher flat values break; case "Armor": if (usePercent) item.ArmorPercentBonus = GeneratePercentStat(multiplier); else item.ArmorBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier)); break; case "MagicResistance": if (usePercent) item.MagicResistancePercentBonus = GeneratePercentStat(multiplier); else item.MagicResistanceBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier)); break; case "DodgeChance": item.DodgeChancePercentBonus = GeneratePercentStat(multiplier * 0.4f); // Always percent break; case "BlockChance": item.BlockChancePercentBonus = GeneratePercentStat(multiplier * 0.4f); // Always percent break; case "BlockEffectiveness": item.BlockEffectivenessPercentBonus = GeneratePercentStat(multiplier * 0.6f); // Always percent break; case "AttackSpeed": item.AttackSpeedPercentBonus = GeneratePercentStat(multiplier * 0.6f); // Always percent break; case "HealthRegen": if (usePercent) item.HealthRegenPercentBonus = GeneratePercentStat(multiplier); else item.HealthRegenBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 2f)); break; case "MaxMana": if (usePercent) item.MaxManaPercentBonus = GeneratePercentStat(multiplier); else item.MaxManaBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 3f)); break; case "ManaRegen": if (usePercent) item.ManaRegenPercentBonus = GeneratePercentStat(multiplier); else item.ManaRegenBonus = Mathf.RoundToInt(GenerateFlatStat(multiplier * 2f)); break; case "AreaEffectiveness": item.AreaEffectivenessPercentBonus = GeneratePercentStat(multiplier * 0.5f); // Always percent break; case "CooldownReduction": item.CooldownReductionPercentBonus = GeneratePercentStat(multiplier * 0.4f); // Always percent break; case "MovementSpeed": item.MovementSpeedPercentBonus = GeneratePercentStat(multiplier * 0.3f); // Always percent break; case "ReputationGain": item.ReputationGainIncreasePercentBonus = GeneratePercentStat(multiplier * 0.6f); // Always percent break; case "GoldCostReduction": item.GoldCostReductionPercentBonus = GeneratePercentStat(multiplier * 0.5f); // Always percent break; } } private int GenerateFlatStat(float multiplier) { float baseValue = baseStatValue * multiplier; float variance = baseValue * statVariance; float finalValue = Random.Range(baseValue - variance, baseValue + variance); return Mathf.Max(1, Mathf.RoundToInt(finalValue)); } private float GeneratePercentStat(float multiplier) { float baseValue = percentStatBaseValue * multiplier; float variance = baseValue * statVariance; float finalValue = Random.Range(baseValue - variance, baseValue + variance); return Mathf.Max(0.01f, Mathf.Round(finalValue * 1000f) / 1000f); // Round to 3 decimal places } private string GenerateItemName(EquipmentType equipmentType, ItemTier tier) { string[] tierPrefixes = tier switch { ItemTier.Common => new[] { "", "Simple", "Basic" }, ItemTier.Uncommon => new[] { "Fine", "Quality", "Enhanced" }, ItemTier.Rare => new[] { "Superior", "Masterwork", "Refined" }, ItemTier.Epic => new[] { "Exceptional", "Legendary", "Mythic" }, ItemTier.Legendary => new[] { "Divine", "Ancient", "Celestial" }, _ => new[] { "" } }; string prefix = tierPrefixes[Random.Range(0, tierPrefixes.Length)]; string baseName = equipmentType.ToString(); return string.IsNullOrEmpty(prefix) ? baseName : $"{prefix} {baseName}"; } private string GenerateWeaponName(WeaponType weaponType, ItemTier tier) { string[] tierPrefixes = tier switch { ItemTier.Common => new[] { "", "Simple", "Basic" }, ItemTier.Uncommon => new[] { "Fine", "Quality", "Enhanced" }, ItemTier.Rare => new[] { "Superior", "Masterwork", "Refined" }, ItemTier.Epic => new[] { "Exceptional", "Legendary", "Mythic" }, ItemTier.Legendary => new[] { "Divine", "Ancient", "Celestial" }, _ => new[] { "" } }; string prefix = tierPrefixes[Random.Range(0, tierPrefixes.Length)]; string baseName = weaponType.ToString(); return string.IsNullOrEmpty(prefix) ? baseName : $"{prefix} {baseName}"; } // Update your icon selection methods to store the path private Sprite GetRandomIcon(EquipmentType equipmentType, EquippableItemInstance item) { List iconList = equipmentType switch { EquipmentType.Helmet => HelmetIcons, EquipmentType.Shoulder => ShoulderIcons, EquipmentType.Chest => ChestIcons, EquipmentType.Belt => BeltIcons, EquipmentType.Legs => LegsIcons, EquipmentType.Bracers => BracersIcons, EquipmentType.Gloves => GlovesIcons, EquipmentType.Boots => BootsIcons, EquipmentType.Weapon1 => null, // Will be handled by weapon type EquipmentType.Weapon2 => null, // Will be handled by weapon type _ => null }; if (iconList != null && iconList.Count > 0) { Sprite selectedSprite = iconList[Random.Range(0, iconList.Count)]; // Store the path in the item if (spritePathMap.TryGetValue(selectedSprite, out string path)) { item.IconPath = path; } return selectedSprite; } return null; } private Sprite GetWeaponIcon(WeaponType weaponType, EquippableItemInstance item) { List iconList = weaponType switch { WeaponType.Staff => StaffIcons, WeaponType.Spear => SpearIcons, WeaponType.Scythe => ScytheIcons, WeaponType.Hammer => HammerIcons, WeaponType.Bow => BowIcons, WeaponType.Crossbow => CrossbowIcons, WeaponType.Axe => AxeIcons, WeaponType.Sword => SwordIcons, WeaponType.Shield => ShieldIcons, WeaponType.Dagger => DaggerIcons, WeaponType.Book => BookIcons, _ => SwordIcons }; if (iconList != null && iconList.Count > 0) { Sprite selectedSprite = iconList[Random.Range(0, iconList.Count)]; // Store the path in the item if (spritePathMap.TryGetValue(selectedSprite, out string path)) { item.IconPath = path; } return selectedSprite; } return null; } private WeaponType GetRandomWeaponType() { // Return any weapon type System.Array allTypes = System.Enum.GetValues(typeof(WeaponType)); return (WeaponType)allTypes.GetValue(Random.Range(0, allTypes.Length)); } private void GenerateHelmet(EquippableItemInstance item) { } private void RollDamageStats(EquippableItemInstance item) { int addedDamageStats = 0; } private void RollOffensiveStats(EquippableItemInstance item) { int addedOffensiveStats = 0; } private void RollDefensiveStats(EquippableItemInstance item) { int addedDefensiveStats = 0; } private void RollResourceStats(EquippableItemInstance item) { int addedResourceStats = 0; } private void RollControlStats(EquippableItemInstance item) { int addedControlStats = 0; } }