Advertisement
Krythic

Generator

May 15th, 2025
296
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 15.55 KB | None | 0 0
  1.  
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6. using VoidwalkerEngine.Framework.Algorithms;
  7.  
  8.  
  9. public class RarityEventArgs
  10. {
  11.     public int uncommonChance;
  12.     public int rareChance;
  13.     public int epicChance;
  14.     public int uniqueChance;
  15.  
  16.     public int superiorChance;
  17.     public int commonChance;
  18.     public int lowQualityChance;
  19.  
  20.     public RarityEventArgs(int uncommonChance, int rareChance, int epicChance, int uniqueChance)
  21.     {
  22.         this.uncommonChance = uncommonChance;
  23.         this.rareChance = rareChance;
  24.         this.epicChance = epicChance;
  25.         this.uniqueChance = uniqueChance;
  26.  
  27.     }
  28.  
  29.     public RarityEventArgs()
  30.     {
  31.  
  32.     }
  33. }
  34.  
  35. public class GameItemEnchanter
  36. {
  37.     private List<EnchantmentTemplate> _enchantmentTemplates;
  38.     private GameItemNameGenerator _gameItemNameGenerator;
  39.  
  40.     private static readonly List<EnchantmentTemplate> _superiorTemplate = new List<EnchantmentTemplate>() {
  41.         new EnchantmentTemplate(EnchantmentProperty.ItemMod_EnhancedDamage, new Range(10, 15)),
  42.         new EnchantmentTemplate(EnchantmentProperty.ItemMod_EnhancedDurability, new Range(10, 15)),
  43.         new EnchantmentTemplate(EnchantmentProperty.ItemMod_EnhancedArmorRating, new Range(10, 15)),
  44.     };
  45.  
  46.     public GameItemEnchanter()
  47.     {
  48.         Initialize();
  49.     }
  50.  
  51.     private void Initialize()
  52.     {
  53.         LoadEnchantmentTemplates();
  54.         _gameItemNameGenerator = new GameItemNameGenerator();
  55.     }
  56.  
  57.     public static float CalculateEffectiveMagicFind(float totalMagicFind, GameItemRarity rarity)
  58.     {
  59.         float rarityFactor = rarity.ToRarityMagicFindFactor();
  60.         return (totalMagicFind * rarityFactor) / (totalMagicFind + rarityFactor);
  61.     }
  62.  
  63.     public GameItemTemplate Enchant(GameItemTemplate baseItemTemplate, int itemLevel, int magicFind, RarityEventArgs rarityTemplate)
  64.     {
  65.         Dictionary<GameItemRarity, float> rarityChances = new Dictionary<GameItemRarity, float>
  66.         {
  67.             { GameItemRarity.Unique, rarityTemplate.uniqueChance / 100f },
  68.             { GameItemRarity.Epic, rarityTemplate.epicChance / 100f },
  69.             { GameItemRarity.Rare, rarityTemplate.rareChance / 100f },
  70.             { GameItemRarity.Uncommon, rarityTemplate.uncommonChance / 100f }
  71.         };
  72.         GameItemRarity[] rarities = new GameItemRarity[] { GameItemRarity.Unique, GameItemRarity.Epic, GameItemRarity.Rare, GameItemRarity.Uncommon };
  73.         foreach (GameItemRarity rarity in rarities)
  74.         {
  75.             float effectiveChance = Mathf.Clamp(
  76.                 rarityChances[rarity] * CalculateEffectiveMagicFind(magicFind, rarity),
  77.                 0f,
  78.                 1f
  79.             );
  80.  
  81.             if (UnityEngine.Random.Range(0f, 1f) <= effectiveChance)
  82.             {
  83.                 return Enchant(baseItemTemplate, rarity, itemLevel);
  84.             }
  85.         }
  86.  
  87.         return Enchant(baseItemTemplate, GameItemRarity.Common, itemLevel);
  88.     }
  89.  
  90.     public GameItemTemplate Enchant(GameItemTemplate baseItemTemplate, GameItemRarity rarity, int itemLevel)
  91.     {
  92.         GameItemTemplate gameItemTemplate = ScriptableObject.CreateInstance<GameItemTemplate>();
  93.         gameItemTemplate.itemType = baseItemTemplate.itemType;
  94.         gameItemTemplate.itemRarity = rarity;
  95.         gameItemTemplate.itemName = "LGI_001";
  96.         gameItemTemplate.itemIcon = baseItemTemplate.itemIcon;
  97.         gameItemTemplate.weaponDamageMin = baseItemTemplate.weaponDamageMin;
  98.         gameItemTemplate.weaponDamageMax = baseItemTemplate.weaponDamageMax;
  99.         gameItemTemplate.itemLevel = itemLevel;
  100.         int enchantmentCount = NextEnchantmentCount(rarity);
  101.         Debug.Log("Enchantment Count: " + enchantmentCount);
  102.         Enchantment[] generatedAffixes = GenerateRandomEnchantments(baseItemTemplate.itemType, itemLevel, enchantmentCount, out EnchantmentTemplate[] generatedTemplates);
  103.         Debug.Log("Generated Affixes: " + generatedAffixes.Length);
  104.         gameItemTemplate.enchantments = generatedAffixes;
  105.         gameItemTemplate.isGenerated = true;
  106.         switch (rarity)
  107.         {
  108.             case GameItemRarity.Common:
  109.                 gameItemTemplate.itemName = "Null Common";
  110.                 break;
  111.             case GameItemRarity.Uncommon:
  112.                 gameItemTemplate.itemName = _gameItemNameGenerator.GenerateUncommonName(gameItemTemplate.itemType, gameItemTemplate.itemLevel, generatedTemplates);
  113.                 break;
  114.             case GameItemRarity.Rare:
  115.                 gameItemTemplate.itemName = _gameItemNameGenerator.GenerateRareName(gameItemTemplate.itemType);
  116.                 break;
  117.             case GameItemRarity.Epic:
  118.                 gameItemTemplate.itemName = _gameItemNameGenerator.GenerateEpicName(gameItemTemplate.itemType);
  119.                 break;
  120.             case GameItemRarity.Unique:
  121.                 gameItemTemplate.itemName = "Null Legendary";
  122.                 break;
  123.             default:
  124.                 gameItemTemplate.itemName = "Error";
  125.                 break;
  126.         }
  127.         gameItemTemplate.isEthereal = GenerateEthereal();
  128.         return gameItemTemplate;
  129.     }
  130.  
  131.     private EnchantmentTemplate[] GetValidEnchantmentTemplates(GameItemType itemType, int itemLevel)
  132.     {
  133.         List<EnchantmentTemplate> validEnchantments = new List<EnchantmentTemplate>();
  134.         foreach (EnchantmentTemplate template in _enchantmentTemplates)
  135.         {
  136.             if (template.levelBracketRange.Contains(itemLevel))
  137.             {
  138.                 foreach (GameItemType constraint in template.itemConstraints)
  139.                 {
  140.                     if (constraint == itemType)
  141.                     {
  142.                         validEnchantments.Add(template);
  143.                         break;
  144.                     }
  145.                 }
  146.             }
  147.         }
  148.         return validEnchantments.ToArray();
  149.     }
  150.  
  151.     public Enchantment[] GenerateRandomEnchantments(GameItemType itemType, int itemLevel, int affixCount, out EnchantmentTemplate[] generatedEnchantmentTemplateResults)
  152.     {
  153.         EnchantmentTemplate[] validTemplates = GetValidEnchantmentTemplates(itemType, itemLevel);
  154.         List<Enchantment> generatedEnchantments = new List<Enchantment>();
  155.         List<EnchantmentTemplate> selectedTemplates = new List<EnchantmentTemplate>();
  156.  
  157.         if (validTemplates.Length == 0)
  158.         {
  159.             generatedEnchantmentTemplateResults = null;
  160.             return generatedEnchantments.ToArray();
  161.         }
  162.  
  163.         List<EnchantmentTemplate> templatesPool = new List<EnchantmentTemplate>(validTemplates);
  164.         int totalWeight = templatesPool.Sum(t => t.weight);
  165.  
  166.         for (int i = 0; i < affixCount && templatesPool.Count > 0; i++)
  167.         {
  168.             int randomWeight = UnityEngine.Random.Range(0, totalWeight);
  169.             int cumulativeWeight = 0;
  170.  
  171.             foreach (EnchantmentTemplate template in templatesPool)
  172.             {
  173.                 cumulativeWeight += template.weight;
  174.                 if (randomWeight < cumulativeWeight)
  175.                 {
  176.                     Enchantment newMagicAffix = new Enchantment
  177.                     {
  178.                         property = template.property,
  179.                         parameter = UnityEngine.Random.Range(template.staticParamRange.min, template.staticParamRange.max),
  180.                         minParam = UnityEngine.Random.Range(template.minDynamicParamRange.min, template.minDynamicParamRange.max),
  181.                         maxParam = UnityEngine.Random.Range(template.maxDynamicParamRange.min, template.maxDynamicParamRange.max),
  182.                         priceModifier = template.priceModifier,
  183.                     };
  184.  
  185.                     generatedEnchantments.Add(newMagicAffix);
  186.                     selectedTemplates.Add(template);
  187.                     totalWeight -= template.weight;
  188.                     templatesPool.Remove(template);
  189.                     break;
  190.                 }
  191.             }
  192.         }
  193.  
  194.         generatedEnchantmentTemplateResults = selectedTemplates.ToArray();
  195.         return generatedEnchantments.ToArray();
  196.     }
  197.  
  198.     public int NextEnchantmentCount(GameItemRarity rarity)
  199.     {
  200.         switch (rarity)
  201.         {
  202.             case GameItemRarity.Uncommon:
  203.                 return UnityEngine.Random.Range(1, 2);
  204.             case GameItemRarity.Rare:
  205.                 return UnityEngine.Random.Range(2, 6);
  206.             default:
  207.                 return 0;
  208.         }
  209.     }
  210.  
  211.     public static Enchantment[] CombineDuplicateEnchantments(Enchantment[] enchantments)
  212.     {
  213.         if (enchantments == null || enchantments.Length == 0)
  214.         {
  215.             return Array.Empty<Enchantment>();
  216.         }
  217.         // Preallocate with capacity if input is large to avoid resizing
  218.         Dictionary<EnchantmentProperty, Enchantment> combined = new Dictionary<EnchantmentProperty, Enchantment>(enchantments.Length);
  219.         for (int i = 0; i < enchantments.Length; i++)
  220.         {
  221.             Enchantment enchantment = enchantments[i];
  222.             if (combined.TryGetValue(enchantment.property, out var existing))
  223.             {
  224.                 // Accumulate into existing
  225.                 existing.parameter += enchantment.parameter;
  226.                 existing.minParam += enchantment.minParam;
  227.                 existing.maxParam += enchantment.maxParam;
  228.                 existing.priceModifier = enchantment.priceModifier;
  229.             }
  230.             else
  231.             {
  232.                 // Clone only when needed to avoid unnecessary allocations
  233.                 combined[enchantment.property] = new Enchantment
  234.                 {
  235.                     property = enchantment.property,
  236.                     parameter = enchantment.parameter,
  237.                     minParam = enchantment.minParam,
  238.                     maxParam = enchantment.maxParam,
  239.                     priceModifier = enchantment.priceModifier
  240.                 };
  241.             }
  242.         }
  243.         // Use collection copy to minimize LINQ overhead
  244.         Enchantment[] result = new Enchantment[combined.Count];
  245.         combined.Values.CopyTo(result, 0);
  246.         return result;
  247.     }
  248.  
  249.     public bool GenerateEthereal()
  250.     {
  251.         return UnityEngine.Random.Range(0, 10) < 5;
  252.     }
  253.  
  254.     public void LoadEnchantmentTemplates()
  255.     {
  256.         List<EnchantmentTemplate> templates = new List<EnchantmentTemplate>();
  257.         string fileName = "EnchantmentTemplates";
  258.  
  259.         try
  260.         {
  261.             TextAsset textAsset = Resources.Load<TextAsset>("Prefabs/Data/" + fileName);
  262.             if (textAsset == null)
  263.             {
  264.                 Debug.LogError($"[LoadEnchantmentTemplates] File not found: Resources/Prefabs/Data/{fileName}");
  265.                 return;
  266.             }
  267.  
  268.             string[] lines = textAsset.text.Split(new[] { '\n' }, System.StringSplitOptions.RemoveEmptyEntries);
  269.             Debug.Log($"[LoadEnchantmentTemplates] Loaded {lines.Length} lines from {fileName}.");
  270.             if (lines.Length <= 1)
  271.             {
  272.                 Debug.LogWarning("[LoadEnchantmentTemplates] Enchantment template file is empty or missing data.");
  273.                 return;
  274.             }
  275.  
  276.             for (int i = 0; i < lines.Length; i++)
  277.             {
  278.                 string[] fields = lines[i].Split(new[] { '\t' }, System.StringSplitOptions.None);
  279.                 if (fields.Length < 8)
  280.                 {
  281.                     Debug.LogWarning($"[LoadEnchantmentTemplates] Skipping line {i + 1}: Not enough fields.");
  282.                     continue;
  283.                 }
  284.  
  285.                 try
  286.                 {
  287.                     EnchantmentTemplate enchantmentTemplate = new EnchantmentTemplate();
  288.  
  289.                     if (!Enchantment.TryParseEnchantmentProperty(fields[0], out EnchantmentProperty property))
  290.                     {
  291.                         Debug.LogWarning($"[LoadEnchantmentTemplates] Line {i + 1}: Could not parse property '{fields[0]}'.");
  292.                         continue;
  293.                     }
  294.  
  295.                     enchantmentTemplate.property = property;
  296.                     enchantmentTemplate.prefix = fields[1];
  297.                     enchantmentTemplate.suffix = fields[2];
  298.                     enchantmentTemplate.levelBracketRange = Range.Parse(fields[3]);
  299.                     enchantmentTemplate.staticParamRange = Range.Parse(fields[4]);
  300.                     enchantmentTemplate.minDynamicParamRange = Range.Parse(fields[5]);
  301.                     enchantmentTemplate.maxDynamicParamRange = Range.Parse(fields[6]);
  302.                     enchantmentTemplate.weight = int.Parse(fields[7]);
  303.                     enchantmentTemplate.itemConstraints = ParseGameItemConstraintsField(fields[8]);
  304.  
  305.                     templates.Add(enchantmentTemplate);
  306.                 }
  307.                 catch (FormatException fe)
  308.                 {
  309.                     Debug.LogWarning($"[LoadEnchantmentTemplates] Line {i + 1}: Format exception - {fe.Message}");
  310.                 }
  311.                 catch (System.Exception ex)
  312.                 {
  313.                     Debug.LogWarning($"[LoadEnchantmentTemplates] Line {i + 1}: Unexpected error - {ex.Message}");
  314.                 }
  315.             }
  316.         }
  317.         catch (System.Exception ex)
  318.         {
  319.             Debug.LogError($"[LoadEnchantmentTemplates] Failed to load templates: {ex.Message}");
  320.             return;
  321.         }
  322.  
  323.         this._enchantmentTemplates = templates;
  324.         Debug.Log($"[LoadEnchantmentTemplates] Successfully loaded {templates.Count} enchantment templates.");
  325.     }
  326.  
  327.     private static GameItemType[] ParseGameItemConstraintsField(string constraints)
  328.     {
  329.         if (string.IsNullOrWhiteSpace(constraints))
  330.         {
  331.             return new GameItemType[0];
  332.         }
  333.         string[] constraintParts = constraints.Split(",", System.StringSplitOptions.RemoveEmptyEntries);
  334.         List<GameItemType> results = new List<GameItemType>();
  335.         foreach (string constraint in constraintParts)
  336.         {
  337.             string trimmedConstraint = constraint.Trim();
  338.             GameItemType parsedConstraint = ParseGameItemTypeConstraint(trimmedConstraint);
  339.             if (!results.Contains(parsedConstraint))
  340.             {
  341.                 results.Add(parsedConstraint);
  342.             }
  343.         }
  344.         return results.ToArray();
  345.     }
  346.  
  347.     private static GameItemType ParseGameItemTypeConstraint(string constraints)
  348.     {
  349.         switch (constraints)
  350.         {
  351.             case "Dagger":
  352.                 return GameItemType.Dagger;
  353.             case "Sword":
  354.                 return GameItemType.Sword;
  355.             case "Greatsword":
  356.                 return GameItemType.GreatSword;
  357.             case "Axe":
  358.                 return GameItemType.Axe;
  359.             case "Greataxe":
  360.                 return GameItemType.GreatAxe;
  361.             case "Mace":
  362.                 return GameItemType.Mace;
  363.             case "Greatmace":
  364.                 return GameItemType.GreatMace;
  365.             case "Bow":
  366.                 return GameItemType.Bow;
  367.             case "Head":
  368.                 return GameItemType.Headwear;
  369.             case "Chest":
  370.                 return GameItemType.Chestwear;
  371.             case "Hand":
  372.                 return GameItemType.Handwear;
  373.             case "Foot":
  374.                 return GameItemType.Footwear;
  375.             case "Amulet":
  376.                 return GameItemType.Amulet;
  377.             case "Ring":
  378.                 return GameItemType.Ring;
  379.             case "Shield":
  380.                 return GameItemType.Shield;
  381.             case "Charm":
  382.                 return GameItemType.Charm;
  383.             default:
  384.                 throw new System.Exception("Could not parse GameItemConstraint: '" + constraints + "'!");
  385.         }
  386.     }
  387. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement