Advertisement
Krythic

GameItemGenerator 1_21_2024

Jan 21st, 2024
1,018
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 14.63 KB | None | 0 0
  1. using Assets.Resources.Scripts;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using UnityEngine;
  6.  
  7. /// <summary>
  8. /// The Order of these enums determines property order
  9. /// for display purposes. IE: The properties located at
  10. /// the top of the enumeration are sorted to the top
  11. /// of item descriptions
  12. /// </summary>
  13. public enum MagicPropertyType
  14. {
  15.     None,
  16.     Stat_Strength_Mod,
  17.     Stat_Defense_Mod,
  18.     Stat_Vitality_Mod,
  19.     Stat_Intellect_Mod,
  20.     Stat_Wisdom_Mod,
  21.     Stat_Spirit_Mod,
  22.     DamageVs_Aberrations,
  23.     DamageVs_Beasts,
  24.     DamageVs_Demons,
  25.     DamageVs_Undead,
  26.     ElementalMastery_Arcane,
  27.     ElementalMastery_Cold,
  28.     ElementalMastery_Fire,
  29.     ElementalMastery_Holy,
  30.     ElementalMastery_Poison,
  31.     ElementalMastery_Shadow,
  32.     ElementalMastery_Shock,
  33.     EnhancedBlockChance_Mod,
  34.     EnhancedWeaponDamage_Mult,
  35.     ExtraDamage_Arcane,
  36.     ExtraDamage_Cold,
  37.     ExtraDamage_Fire,
  38.     ExtraDamage_Holy,
  39.     ExtraDamage_Poison,
  40.     ExtraDamage_Shadow,
  41.     ExtraDamage_Shock,
  42.     Resist_All,
  43.     Resist_Arcane,
  44.     Resist_Cold,
  45.     Resist_Fire,
  46.     Resist_Holy,
  47.     Resist_Poison,
  48.     Resist_Shadow,
  49.     Resist_Shock,
  50.     WeaponMastery_Axes,
  51.     WeaponMastery_Bows,
  52.     WeaponMastery_Daggers,
  53.     WeaponMastery_Knuckles,
  54.     WeaponMastery_Maces,
  55.     WeaponMastery_Staves,
  56.     WeaponMastery_Swords,
  57.     WeaponMastery_Wands,
  58. }
  59.  
  60. public class MagicPropertyTemplate
  61. {
  62.     public MagicPropertyType property;
  63.     public VoidwalkerRange levelBracket;
  64.     public AffixType affixType;
  65.     public VoidwalkerRange valueRange;
  66.     public GameItemType[] constraints;
  67.     public int weight;
  68.  
  69.     public MagicPropertyTemplate()
  70.     {
  71.  
  72.     }
  73. }
  74.  
  75. public enum GameItemCraftmanship
  76. {
  77.     None,
  78.     Normal, // Iron 0-25
  79.     Exceptional, // Titanite 26-50
  80.     Exquisite, // Mythrite 51-75
  81.     Masterwork // Eternium 76-100
  82. }
  83.  
  84. public enum AffixType
  85. {
  86.     Any,
  87.     Prefix,
  88.     Suffix,
  89. }
  90.  
  91. public class GameItemGenerator
  92. {
  93.     private GameItemNameGenerator _nameGenerator;
  94.     private VoidwalkerRandom _random;
  95.     private List<MagicPropertyTemplate> _magicPropertyTemplates;
  96.     private Dictionary<string, MagicPropertyType> _magicPropertyTypeConverter;
  97.     private Dictionary<string, GameItemType> _gameItemTypeConverter;
  98.  
  99.     public GameItemGenerator()
  100.     {
  101.         _nameGenerator = new GameItemNameGenerator();
  102.         _random = new VoidwalkerRandom();
  103.         InitializeMagicProperties();
  104.     }
  105.  
  106.     private void InitializeMagicProperties()
  107.     {
  108.         _magicPropertyTypeConverter = new Dictionary<string, MagicPropertyType>
  109.         {
  110.             { "DamageVs_Aberrations", MagicPropertyType.DamageVs_Aberrations },
  111.             { "DamageVs_Beasts", MagicPropertyType.DamageVs_Beasts },
  112.             { "DamageVs_Demons", MagicPropertyType.DamageVs_Demons },
  113.             { "DamageVs_Undead", MagicPropertyType.DamageVs_Undead },
  114.             { "ElementalMastery_Arcane", MagicPropertyType.ElementalMastery_Arcane },
  115.             { "ElementalMastery_Cold", MagicPropertyType.ElementalMastery_Cold },
  116.             { "ElementalMastery_Fire", MagicPropertyType.ElementalMastery_Fire },
  117.             { "ElementalMastery_Holy", MagicPropertyType.ElementalMastery_Holy },
  118.             { "ElementalMastery_Poison", MagicPropertyType.ElementalMastery_Poison },
  119.             { "ElementalMastery_Shadow", MagicPropertyType.ElementalMastery_Shadow },
  120.             { "ElementalMastery_Shock", MagicPropertyType.ElementalMastery_Shock },
  121.             { "EnhancedBlockChance", MagicPropertyType.EnhancedBlockChance_Mod },
  122.             { "EnhancedWeaponDamage", MagicPropertyType.EnhancedWeaponDamage_Mult },
  123.             { "ExtraDamage_Arcane", MagicPropertyType.ExtraDamage_Arcane },
  124.             { "ExtraDamage_Cold", MagicPropertyType.ExtraDamage_Cold },
  125.             { "ExtraDamage_Fire", MagicPropertyType.ExtraDamage_Fire },
  126.             { "ExtraDamage_Holy", MagicPropertyType.ExtraDamage_Holy },
  127.             { "ExtraDamage_Poison", MagicPropertyType.ExtraDamage_Poison },
  128.             { "ExtraDamage_Shadow", MagicPropertyType.ExtraDamage_Shadow },
  129.             { "ExtraDamage_Shock", MagicPropertyType.ExtraDamage_Shock },
  130.             { "Resist_All", MagicPropertyType.Resist_All },
  131.             { "Resist_Arcane", MagicPropertyType.Resist_Arcane },
  132.             { "Resist_Cold", MagicPropertyType.Resist_Cold },
  133.             { "Resist_Fire", MagicPropertyType.Resist_Fire },
  134.             { "Resist_Holy", MagicPropertyType.Resist_Holy },
  135.             { "Resist_Poison", MagicPropertyType.Resist_Poison },
  136.             { "Resist_Shadow", MagicPropertyType.Resist_Shadow },
  137.             { "Resist_Shock", MagicPropertyType.Resist_Shock },
  138.             { "Stat_Defense_Mod", MagicPropertyType.Stat_Defense_Mod },
  139.             { "Stat_Intellect_Mod", MagicPropertyType.Stat_Intellect_Mod },
  140.             { "Stat_Strength_Mod", MagicPropertyType.Stat_Strength_Mod },
  141.             { "Stat_Vitality_Mod", MagicPropertyType.Stat_Vitality_Mod },
  142.             { "Stat_Wisdom_Mod", MagicPropertyType.Stat_Wisdom_Mod },
  143.             { "Stat_Spirit_Mod", MagicPropertyType.Stat_Spirit_Mod },
  144.             { "WeaponMastery_Axes", MagicPropertyType.WeaponMastery_Axes },
  145.             { "WeaponMastery_Bows", MagicPropertyType.WeaponMastery_Bows },
  146.             { "WeaponMastery_Daggers", MagicPropertyType.WeaponMastery_Daggers },
  147.             { "WeaponMastery_Knuckles", MagicPropertyType.WeaponMastery_Knuckles },
  148.             { "WeaponMastery_Maces", MagicPropertyType.WeaponMastery_Maces },
  149.             { "WeaponMastery_Staves", MagicPropertyType.WeaponMastery_Staves },
  150.             { "WeaponMastery_Swords", MagicPropertyType.WeaponMastery_Swords },
  151.             { "WeaponMastery_Wands", MagicPropertyType.WeaponMastery_Wands },
  152.         };
  153.  
  154.  
  155.         _gameItemTypeConverter = new Dictionary<string, GameItemType>
  156.         {
  157.             { "Daggers", GameItemType.Weapon_Dagger },
  158.             { "Bows", GameItemType.Weapon_Bow },
  159.             { "Knuckles", GameItemType.Weapon_Knuckle },
  160.             { "Staves", GameItemType.Weapon_Staff },
  161.             { "Wands", GameItemType.Weapon_Wand },
  162.             { "Swords", GameItemType.Weapon_Sword },
  163.             { "GreatSwords", GameItemType.Weapon_Greatsword },
  164.             { "Axes", GameItemType.Weapon_Axe },
  165.             { "GreatAxes", GameItemType.Weapon_Greataxe },
  166.             { "Maces", GameItemType.Weapon_Mace },
  167.             { "GreatMaces", GameItemType.Weapon_GreatMace },
  168.             { "Shields", GameItemType.Shield },
  169.             { "Headwear", GameItemType.Headwear },
  170.             { "Chestwear", GameItemType.Chestwear },
  171.             { "Handwear", GameItemType.Handwear },
  172.             { "Footwear", GameItemType.Footwear },
  173.             { "Amulets", GameItemType.Jewelry_Amulet },
  174.             { "Rings", GameItemType.Jewelry_Ring },
  175.             { "Charms", GameItemType.Jewelry_Charm }
  176.         };
  177.  
  178.  
  179.         /**
  180.          * Load MagicProperties.txt
  181.          */
  182.         this._magicPropertyTemplates = new List<MagicPropertyTemplate>();
  183.         TextAsset mytxtData = Resources.Load<TextAsset>("Data/MagicProperties");
  184.         string[] magicPropertyData = mytxtData.text.Split("\n");
  185.         foreach (string line in magicPropertyData)
  186.         {
  187.             string[] lineData = line.Split("\t");
  188.             string[] constraints = RemoveFormatting(lineData[5]).Split(",");
  189.             MagicPropertyTemplate template = new MagicPropertyTemplate()
  190.             {
  191.                 property = ParseMagicPropertyType(lineData[0]),
  192.                 levelBracket = VoidwalkerRange.Parse(lineData[1]),
  193.                 affixType = ParseAffixType(lineData[2]),
  194.                 valueRange = VoidwalkerRange.Parse(lineData[3]),
  195.                 weight = Int32.Parse(lineData[4]),
  196.                 constraints = ParseGameItemConstraints(constraints)
  197.             };
  198.             this._magicPropertyTemplates.Add(template);
  199.         }
  200.     }
  201.  
  202.     private AffixType ParseAffixType(string affixType)
  203.     {
  204.         switch (affixType)
  205.         {
  206.             case "Prefix":
  207.                 return AffixType.Prefix;
  208.             case "Suffix":
  209.                 return AffixType.Suffix;
  210.             default:
  211.                 return AffixType.Any; // Should probably default to a null state?
  212.         }
  213.     }
  214.  
  215.     public static string RemoveFormatting(string pString)
  216.     {
  217.         return pString.Replace("\n", "").Replace("\r", "");
  218.     }
  219.  
  220.     private MagicPropertyType ParseMagicPropertyType(string property)
  221.     {
  222.         return _magicPropertyTypeConverter[property];
  223.     }
  224.  
  225.     private GameItemType[] ParseGameItemConstraints(string[] properties)
  226.     {
  227.         List<GameItemType> propertyTypes = new List<GameItemType>();
  228.         foreach (string propertyType in properties)
  229.         {
  230.             propertyTypes.Add(ParseGameItemConstraint(propertyType));
  231.         }
  232.         return propertyTypes.ToArray();
  233.     }
  234.  
  235.     private GameItemType ParseGameItemConstraint(string constraint)
  236.     {
  237.         return _gameItemTypeConverter[constraint];
  238.     }
  239.  
  240.     /// <summary>
  241.     /// TODO: Finish adding this functionality.
  242.     /// </summary>
  243.     /// <param name="level"></param>
  244.     /// <returns></returns>
  245.     public GameItemTemplate Generate(int level)
  246.     {
  247.         return null;
  248.     }
  249.  
  250.     /// <summary>
  251.     /// TODO: Tie this into the dynamic Generate function directly above
  252.     /// this declaration. This will be used to generate a random item quality
  253.     /// without the need to manually feed one into the generator.
  254.     /// </summary>
  255.     /// <param name="level"></param>
  256.     /// <returns></returns>
  257.     private ItemQuality NextRandomQuality(int level)
  258.     {
  259.         return ItemQuality.None;
  260.     }
  261.  
  262.     public GameItemTemplate Generate(GameItemType itemType, int level, ItemQuality quality)
  263.     {
  264.         GameItemTemplate template = ScriptableObject.CreateInstance<GameItemTemplate>();
  265.         template.baseItemQuality = quality;
  266.         template.itemType = itemType;
  267.         template.itemLevel = level;
  268.         template.identifier = "ProcGen_" + level + "_" + itemType;
  269.         template.name = _nameGenerator.Generate(quality, itemType);
  270.         if (quality == ItemQuality.Uncommon || quality == ItemQuality.Rare)
  271.         {
  272.             GenerateAffixCount(quality, out int prefixCount, out int suffixCount);
  273.             List<MagicProperty> properties = new List<MagicProperty>();
  274.             List<MagicPropertyTemplate> generatedTemplates = new List<MagicPropertyTemplate>();
  275.             generatedTemplates.AddRange(GenerateMagicPropertyTemplates(itemType, level, prefixCount, AffixType.Prefix, false));
  276.             generatedTemplates.AddRange(GenerateMagicPropertyTemplates(itemType, level, suffixCount, AffixType.Suffix, false));
  277.             foreach (MagicPropertyTemplate magicPropertyTemplate in generatedTemplates)
  278.             {
  279.                 MagicProperty property = new MagicProperty()
  280.                 {
  281.                     propertyType = magicPropertyTemplate.property,
  282.                     value = _random.NextRange(magicPropertyTemplate.valueRange)
  283.                 };
  284.                 properties.Add(property);
  285.             }
  286.             properties = properties.OrderBy(property => property.propertyType).ToList();
  287.             template.magicProperties = new MagicProperties();
  288.             template.magicProperties.properties = properties;
  289.         }
  290.         return template;
  291.     }
  292.  
  293.     /// <summary>
  294.     ///
  295.     /// </summary>
  296.     /// <param name="constraint"></param>
  297.     /// <param name="level"></param>
  298.     /// <param name="count"></param>
  299.     /// <param name="allowDuplicates"></param>
  300.     /// <returns></returns>
  301.     private List<MagicPropertyTemplate> GenerateMagicPropertyTemplates(GameItemType constraint, int level, int count,
  302.         AffixType affixType = AffixType.Any, bool allowDuplicates = false)
  303.     {
  304.         List<MagicPropertyTemplate> results = new List<MagicPropertyTemplate>();
  305.         if (count == 0)
  306.         {
  307.             return results;
  308.         }
  309.         int totalFitness = 0;
  310.         List<MagicPropertyTemplate> filteredTemplates = new List<MagicPropertyTemplate>();
  311.         foreach (MagicPropertyTemplate candidate in this._magicPropertyTemplates)
  312.         {
  313.             if (candidate.affixType == affixType || affixType == AffixType.Any)
  314.             {
  315.                 if (candidate.constraints.Contains(constraint))
  316.                 {
  317.                     if (candidate.levelBracket.Contains(level))
  318.                     {
  319.                         filteredTemplates.Add(candidate);
  320.                         totalFitness += candidate.weight;
  321.                     }
  322.                 }
  323.             }
  324.         }
  325.         if (filteredTemplates.Count < count)
  326.         {
  327.             count = filteredTemplates.Count;
  328.             if (count == 0)
  329.             {
  330.                 return results;
  331.             }
  332.         }
  333.         filteredTemplates.OrderBy(enchantment => enchantment.weight).Reverse().ToList();
  334.         int enchantmentsGenerated = 0;
  335.         bool isSearching = true;
  336.         int attempts = 0;
  337.         const int maximumAttempts = 32; // Prevent Infinite Loops
  338.         while (isSearching)
  339.         {
  340.             MagicPropertyTemplate selectedEnchantment = null;
  341.             int randomSample = _random.NextInteger(totalFitness);
  342.             foreach (MagicPropertyTemplate attempt in filteredTemplates)
  343.             {
  344.                 if (randomSample < attempt.weight)
  345.                 {
  346.                     selectedEnchantment = attempt;
  347.                     break;
  348.                 }
  349.                 randomSample -= attempt.weight;
  350.             }
  351.             if (allowDuplicates ||
  352.                 !results.Any(e => e == selectedEnchantment) &&
  353.                 !results.Any(e => e.property.Equals(selectedEnchantment.property)))
  354.             {
  355.                 attempts = 0;
  356.                 results.Add(selectedEnchantment);
  357.                 enchantmentsGenerated++;
  358.             }
  359.             attempts++;
  360.             if (enchantmentsGenerated == count || attempts >= maximumAttempts)
  361.             {
  362.                 isSearching = false;
  363.             }
  364.         }
  365.         return results;
  366.     }
  367.  
  368.     private void GenerateAffixCount(ItemQuality quality, out int prefixCount, out int suffixCount)
  369.     {
  370.         switch (quality)
  371.         {
  372.             case ItemQuality.Uncommon:
  373.                 prefixCount = _random.NextRange(1, 3);
  374.                 suffixCount = _random.NextRange(0, 1);
  375.                 return;
  376.             case ItemQuality.Rare:
  377.                 prefixCount = _random.NextRange(3, 4);
  378.                 suffixCount = _random.NextRange(1, 2);
  379.                 return;
  380.             default:
  381.                 prefixCount = 0;
  382.                 suffixCount = 0;
  383.                 return;
  384.         }
  385.     }
  386. }
  387.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement