Advertisement
Krythic

GameItemGenerator 5_24_2024

May 24th, 2024
516
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 16.07 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. public enum MagicPropertyType
  8. {
  9.     None,
  10.     ExtraDamage_Fire,
  11.     ExtraDamage_Cold,
  12.     ExtraDamage_Shock,
  13.     ExtraDamage_Poison,
  14.     ExtraDamage_Arcane,
  15.     ExtraDamage_Shadow,
  16.  
  17.     Resist_All,
  18.     Resist_Fire,
  19.     Resist_Cold,
  20.     Resist_Shock,
  21.     Resist_Poison,
  22.     Resist_Arcane,
  23.     Resist_Shadow,
  24.  
  25.     CriticalRate,
  26.     CarryWeight,
  27.  
  28.     DamageVs_Humans,
  29.     DamageVs_Undead,
  30.     DamageVs_Demons,
  31.     DamageVs_Beasts,
  32.  
  33.     Steal_Mana,
  34.     Steal_Stamina,
  35.     Steal_Life,
  36.  
  37.     StatMod_Strength, // Damage with melee weapons
  38.     StatMod_Dexterity, // Damage with ranged weapons
  39.     StatMod_Endurance, // Carry Weight, Stamina Regen
  40.     StatMod_Vitality, // Health
  41.     StatMod_Intellect, // Damage with spells
  42.     StatMod_Wisdom, // Mana Regen
  43.     StatMod_Spirit, // Void Timer, all stats in small way.
  44.  
  45.  
  46. }
  47.  
  48. public class LootGeneratorArgs
  49. {
  50.     public BasicRange commonChance;
  51.     public BasicRange uncommonChance;
  52.     public BasicRange rareChance;
  53.     public BasicRange epicChance;
  54.     public BasicRange legendaryChance;
  55.     public GameItemType[] targets;
  56.  
  57.     public LootGeneratorArgs()
  58.     {
  59.  
  60.     }
  61.  
  62.     public LootGeneratorArgs(BasicRange commonChance, BasicRange uncommonChance, BasicRange rareChance,
  63.         BasicRange epicChance, BasicRange legendaryChance, GameItemType[] targets)
  64.     {
  65.         this.commonChance = commonChance;
  66.         this.uncommonChance = uncommonChance;
  67.         this.rareChance = rareChance;
  68.         this.epicChance = epicChance;
  69.         this.legendaryChance = legendaryChance;
  70.         this.targets = targets;
  71.     }
  72. }
  73.  
  74. public class GameItemGenerator
  75. {
  76.     private GameItemNameGenerator _nameGenerator;
  77.     private VoidwalkerRandom _random;
  78.     private List<Enchantment> _enchantments;
  79.     private Dictionary<string, MagicPropertyType> _magicPropertyTypeConverter;
  80.     private Dictionary<string, GameItemType> _gameItemTypeConverter;
  81.     //public Dictionary<GameItemType, Sprite[]> _gameItemSprites;
  82.  
  83.     public GameItemGenerator()
  84.     {
  85.         _nameGenerator = new GameItemNameGenerator();
  86.         _random = new VoidwalkerRandom();
  87.         InitializeMagicProperties();
  88.         //InitializeGameItemSprites();
  89.     }
  90.  
  91.     //private void InitializeGameItemSprites()
  92.     //{
  93.     //    object[] swordSprites = Resources.LoadAll("Graphics/UI/GameItems/Weapons/Swords", typeof(Sprite));
  94.  
  95.     //    _gameItemSprites = new Dictionary<GameItemType, Sprite[]>
  96.     //    {
  97.     //        { GameItemType.Weapon_Sword, ConvertResourceToSpriteArray(swordSprites) }
  98.     //    };
  99.     //}
  100.  
  101.     private Sprite[] ConvertResourceToSpriteArray(object[] resource)
  102.     {
  103.         List<Sprite> sprites = new List<Sprite>();
  104.         foreach (object item in resource)
  105.         {
  106.             sprites.Add((Sprite)item);
  107.         }
  108.         return sprites.ToArray();
  109.     }
  110.  
  111.     private void InitializeMagicProperties()
  112.     {
  113.         _magicPropertyTypeConverter = new Dictionary<string, MagicPropertyType>
  114.         {
  115.             {"ExtraDamage_Fire",MagicPropertyType.ExtraDamage_Fire },
  116.             {"ExtraDamage_Cold",MagicPropertyType.ExtraDamage_Cold },
  117.             {"ExtraDamage_Shock",MagicPropertyType.ExtraDamage_Shock },
  118.             {"ExtraDamage_Poison",MagicPropertyType.ExtraDamage_Poison },
  119.             {"ExtraDamage_Arcane",MagicPropertyType.ExtraDamage_Arcane },
  120.             {"ExtraDamage_Shadow",MagicPropertyType.ExtraDamage_Shadow },
  121.             {"Resist_All",MagicPropertyType.Resist_All },
  122.             {"Resist_Fire",MagicPropertyType.Resist_Fire },
  123.             {"Resist_Cold",MagicPropertyType.Resist_Cold },
  124.             {"Resist_Shock",MagicPropertyType.Resist_Shock },
  125.             {"Resist_Poison",MagicPropertyType.Resist_Poison },
  126.             {"Resist_Arcane",MagicPropertyType.Resist_Arcane },
  127.             {"Resist_Shadow",MagicPropertyType.Resist_Shadow },
  128.             {"CriticalRate",MagicPropertyType.CriticalRate },
  129.             {"CarryWeight",MagicPropertyType.CarryWeight },
  130.             {"DamageVs_Humans",MagicPropertyType.DamageVs_Humans },
  131.             {"DamageVs_Undead",MagicPropertyType.DamageVs_Undead },
  132.             {"DamageVs_Demons",MagicPropertyType.DamageVs_Demons },
  133.             {"DamageVs_Beasts",MagicPropertyType.DamageVs_Beasts },
  134.             {"Steal_Mana",MagicPropertyType.Steal_Mana },
  135.             {"Steal_Stamina",MagicPropertyType.Steal_Stamina },
  136.             {"Steal_Health",MagicPropertyType.Steal_Life },
  137.  
  138.             {"StatMod_Strength",MagicPropertyType.StatMod_Strength },
  139.             {"StatMod_Dexterity",MagicPropertyType.StatMod_Strength },
  140.             {"StatMod_Endurance",MagicPropertyType.StatMod_Strength },
  141.             {"StatMod_Vitality",MagicPropertyType.StatMod_Strength },
  142.             {"StatMod_Intellect",MagicPropertyType.StatMod_Strength },
  143.             {"StatMod_Wisdom",MagicPropertyType.StatMod_Strength },
  144.             {"StatMod_Spirit",MagicPropertyType.StatMod_Strength },
  145.         };
  146.  
  147.  
  148.         _gameItemTypeConverter = new Dictionary<string, GameItemType>
  149.         {
  150.             { "Daggers", GameItemType.Weapon_Dagger },
  151.             { "Bows", GameItemType.Weapon_Bow },
  152.             { "Knuckles", GameItemType.Weapon_Knuckle },
  153.             { "Staves", GameItemType.Weapon_Staff },
  154.             { "Wands", GameItemType.Weapon_Wand },
  155.             { "Swords", GameItemType.Weapon_Sword },
  156.             { "Greatswords", GameItemType.Weapon_Greatsword },
  157.             { "Axes", GameItemType.Weapon_Axe },
  158.             { "Greataxes", GameItemType.Weapon_Greataxe },
  159.             { "Maces", GameItemType.Weapon_Mace },
  160.             { "Greatmaces", GameItemType.Weapon_Greatmace },
  161.             { "Shields", GameItemType.Shield },
  162.  
  163.             { "Light_Headwear", GameItemType.Light_Headwear },
  164.             { "Light_Chestwear", GameItemType.Light_Chestwear },
  165.             { "Light_Handwear", GameItemType.Light_Handwear },
  166.             { "Light_Footwear", GameItemType.Light_Footwear },
  167.  
  168.             { "Medium_Headwear", GameItemType.Medium_Headwear },
  169.             { "Medium_Chestwear", GameItemType.Medium_Chestwear },
  170.             { "Medium_Handwear", GameItemType.Medium_Handwear },
  171.             { "Medium_Footwear", GameItemType.Medium_Footwear },
  172.  
  173.             { "Heavy_Headwear",  GameItemType.Heavy_Headwear },
  174.             { "Heavy_Chestwear", GameItemType.Heavy_Chestwear },
  175.             { "Heavy_Handwear",  GameItemType.Heavy_Handwear },
  176.             { "Heavy_Footwear",  GameItemType.Heavy_Footwear },
  177.  
  178.             { "Amulets", GameItemType.Jewelry_Amulet },
  179.             { "Rings", GameItemType.Jewelry_Ring },
  180.         };
  181.  
  182.  
  183.         /**
  184.          * Load Enchantments.txt
  185.          */
  186.         this._enchantments = new List<Enchantment>();
  187.         TextAsset mytxtData = Resources.Load<TextAsset>("Data/Enchantments");
  188.         string[] magicPropertyData = mytxtData.text.Split("\n");
  189.         foreach (string line in magicPropertyData)
  190.         {
  191.             string[] lineData = line.Split("\t");
  192.             string[] constraints = RemoveFormatting(lineData[7]).Split(",");
  193.             Enchantment template = new Enchantment()
  194.             {
  195.                 identifier = lineData[0],
  196.                 name = lineData[1],
  197.                 prefix = lineData[2],
  198.                 suffix = lineData[3],
  199.                 family = lineData[4],
  200.                 level = Int32.Parse(lineData[5]),
  201.                 weight = Int32.Parse(lineData[6]),
  202.                 constraints = ParseGameItemConstraints(constraints),
  203.                 description = lineData[8],
  204.             };
  205.             /**
  206.              * Load Magic Properties
  207.              */
  208.             List<EnchantmentProperty> effects = new List<EnchantmentProperty>();
  209.             string[] properties = RemoveFormatting(lineData[9]).Split(";"); // ; is the delimiter for multiple properties
  210.             foreach (string property in properties)
  211.             {
  212.                 EnchantmentProperty enchantmentProperty = new EnchantmentProperty();
  213.                 string[] fields = property.Split(",");
  214.                 enchantmentProperty.property = ParseMagicPropertyType(fields[0]);
  215.                 enchantmentProperty.chance = Int32.Parse(fields[1]);
  216.                 enchantmentProperty.value = Int32.Parse(fields[2]);
  217.                 effects.Add(enchantmentProperty);
  218.             }
  219.             template.effects = effects.ToArray();
  220.             this._enchantments.Add(template);
  221.         }
  222.     }
  223.  
  224.     public static string RemoveFormatting(string pString)
  225.     {
  226.         return pString.Replace("\n", "").Replace("\r", "");
  227.     }
  228.  
  229.     private MagicPropertyType ParseMagicPropertyType(string property)
  230.     {
  231.         return _magicPropertyTypeConverter[property];
  232.     }
  233.  
  234.     private GameItemType[] ParseGameItemConstraints(string[] properties)
  235.     {
  236.         List<GameItemType> propertyTypes = new List<GameItemType>();
  237.         foreach (string propertyType in properties)
  238.         {
  239.             propertyTypes.Add(ParseGameItemConstraint(propertyType));
  240.         }
  241.         return propertyTypes.ToArray();
  242.     }
  243.  
  244.     private GameItemType ParseGameItemConstraint(string constraint)
  245.     {
  246.         return _gameItemTypeConverter[constraint];
  247.     }
  248.  
  249.     /// <summary>
  250.     /// TODO: Finish adding this functionality.
  251.     /// </summary>
  252.     /// <param name="level"></param>
  253.     /// <returns></returns>
  254.     public GameItem Generate(int level, LootGeneratorArgs args)
  255.     {
  256.         if (args != null)
  257.         {
  258.             GameItemRarity rarity = GenerateItemRarity(args);
  259.             if (args.targets != null && args.targets.Length > 0)
  260.             {
  261.                 GameItemType target = _random.Choose(args.targets);
  262.                 if (target.IsLootGeneratorTarget())
  263.                 {
  264.                     GameItem template = Generate(target, level, rarity);
  265.                     return template;
  266.                 }
  267.             }
  268.         }
  269.         return null;
  270.     }
  271.  
  272.     public GameItemRarity GenerateItemRarity(LootGeneratorArgs args)
  273.     {
  274.         if (args != null)
  275.         {
  276.             if (_random.NextDouble() <= args.legendaryChance.ToRatio())
  277.             {
  278.                 return GameItemRarity.Legendary;
  279.             }
  280.             if (_random.NextDouble() <= args.epicChance.ToRatio())
  281.             {
  282.                 return GameItemRarity.Epic;
  283.             }
  284.             if (_random.NextDouble() <= args.rareChance.ToRatio())
  285.             {
  286.                 return GameItemRarity.Rare;
  287.             }
  288.             if (_random.NextDouble() <= args.uncommonChance.ToRatio())
  289.             {
  290.                 return GameItemRarity.Uncommon;
  291.             }
  292.             if (_random.NextDouble() <= args.commonChance.ToRatio())
  293.             {
  294.                 return GameItemRarity.Common;
  295.             }
  296.         }
  297.         return GameItemRarity.None;
  298.     }
  299.  
  300.     public GameItem Generate(GameItemType itemType, int level, GameItemRarity rarity)
  301.     {
  302.         GameItem template = new GameItem();
  303.         template.baseItemQuality = rarity;
  304.         template.itemType = itemType;
  305.         template.itemLevel = level;
  306.         //template.itemIcon = _random.Choose(_gameItemSprites[itemType]);
  307.         template.identifier = "ProcGen_" + level + "_" + itemType;
  308.         template.itemName = _nameGenerator.Generate(itemType, rarity);
  309.  
  310.         //if (rarity == GameItemRarity.Uncommon || rarity == GameItemRarity.Rare || rarity == GameItemRarity.Epic)
  311.         //{
  312.         //    int affixCount = GenerateAffixCount(rarity);
  313.         //    List<Enchantment> properties = new List<Enchantment>();
  314.         //    properties.AddRange(GenerateEnchantments(itemType, level, affixCount));
  315.         //    //properties = properties.OrderBy(property => property.propertyType).ToList();
  316.         //    template.enchantments = properties;
  317.         //}
  318.         return template;
  319.     }
  320.  
  321.     /// <summary>
  322.     ///
  323.     /// </summary>
  324.     /// <param name="constraint"></param>
  325.     /// <param name="level"></param>
  326.     /// <param name="count"></param>
  327.     /// <param name="allowDuplicates"></param>
  328.     /// <returns></returns>
  329.     //private List<Enchantment> GenerateEnchantments(GameItemType constraint, int level, int count)
  330.     //{
  331.     //    List<Enchantment> results = new List<Enchantment>();
  332.     //    if (count == 0)
  333.     //    {
  334.     //        return results;
  335.     //    }
  336.     //    int totalFitness = 0;
  337.     //    List<Enchantment> filteredTemplates = new List<Enchantment>();
  338.     //    foreach (Enchantment candidate in this._enchantments)
  339.     //    {
  340.     //        if (candidate.constraints.Contains(constraint))
  341.     //        {
  342.     //            if (candidate.level <= level)
  343.     //            {
  344.     //                filteredTemplates.Add(candidate);
  345.     //                totalFitness += candidate.weight;
  346.     //            }
  347.     //        }
  348.     //    }
  349.     //    if (filteredTemplates.Count < count)
  350.     //    {
  351.     //        count = filteredTemplates.Count;
  352.     //        if (count == 0)
  353.     //        {
  354.     //            return results;
  355.     //        }
  356.     //    }
  357.     //    filteredTemplates.OrderBy(enchantment => enchantment.weight).Reverse().ToList();
  358.     //    int templatesGenerated = 0;
  359.     //    bool isSearching = true;
  360.     //    int attempts = 0;
  361.     //    const int maximumAttempts = 32; // Prevent Infinite Loops
  362.     //    while (isSearching)
  363.     //    {
  364.     //        Enchantment selectedTemplate = null;
  365.     //        int randomSample = _random.NextInteger(totalFitness);
  366.     //        foreach (Enchantment attempt in filteredTemplates)
  367.     //        {
  368.     //            if (randomSample < attempt.weight)
  369.     //            {
  370.     //                selectedTemplate = attempt;
  371.     //                break;
  372.     //            }
  373.     //            randomSample -= attempt.weight;
  374.     //        }
  375.     //        if (results.Any(e => e.family == selectedTemplate.family) == false)
  376.     //        {
  377.     //            attempts = 0;
  378.     //            results.Add(selectedTemplate);
  379.     //            templatesGenerated++;
  380.     //        }
  381.     //        attempts++;
  382.     //        if (templatesGenerated == count || attempts >= maximumAttempts)
  383.     //        {
  384.     //            isSearching = false;
  385.     //        }
  386.     //    }
  387.  
  388.     //    return results;
  389.     //}
  390.  
  391.     private List<Enchantment> GenerateEnchantments(GameItemType constraint, int level, int count)
  392.     {
  393.         List<Enchantment> results = new List<Enchantment>();
  394.         if (count == 0)
  395.         {
  396.             return results;
  397.         }
  398.  
  399.         // Filtered templates directly
  400.         List<Enchantment> filteredTemplates = this._enchantments
  401.             .Where(candidate => candidate.constraints.Contains(constraint) && candidate.level <= level)
  402.             .OrderByDescending(candidate => candidate.weight)
  403.             .ToList();
  404.  
  405.         int totalFitness = filteredTemplates.Sum(candidate => candidate.weight);
  406.  
  407.         // Limit count if filtered templates count is less
  408.         count = Math.Min(count, filteredTemplates.Count);
  409.  
  410.         // Randomize selection
  411.         int templatesGenerated = 0;
  412.         while (templatesGenerated < count && results.Count < filteredTemplates.Count && filteredTemplates.Any())
  413.         {
  414.             int randomSample = _random.NextInteger(totalFitness);
  415.             foreach (Enchantment attempt in filteredTemplates.ToList())
  416.             {
  417.                 if (randomSample < attempt.weight && !results.Any(e => e.family == attempt.family))
  418.                 {
  419.                     results.Add(attempt);
  420.                     templatesGenerated++;
  421.                     filteredTemplates.Remove(attempt);
  422.                     break;
  423.                 }
  424.                 randomSample -= attempt.weight;
  425.             }
  426.         }
  427.  
  428.         return results;
  429.     }
  430.  
  431.  
  432.     private int GenerateAffixCount(GameItemRarity quality)
  433.     {
  434.         switch (quality)
  435.         {
  436.             case GameItemRarity.Uncommon:
  437.                 return 1;
  438.             case GameItemRarity.Rare:
  439.                 return _random.NextRange(1, 2);
  440.             case GameItemRarity.Epic:
  441.                 return _random.NextRange(2, 3);
  442.             default:
  443.                 return 0;
  444.         }
  445.     }
  446. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement