Advertisement
Krythic

Untitled

Dec 14th, 2019
314
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 17.39 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using VoidwalkerEngine.Framework.Collections;
  5. using VoidwalkerEngine.Framework.DataTypes;
  6. using VoidwalkerEngine.Framework.Logic;
  7. using VoidwalkerEngine.Framework.Maths;
  8. using VoidwalkerEngine.Framework.Systems.Items;
  9. using VoidwalkerEngine.Framework.Systems.Items.Base;
  10. using VoidwalkerEngine.Framework.Systems.Items.Templates;
  11. using VoidwalkerEngine.Framework.Utilities;
  12.  
  13. namespace VoidwalkerEngine.Framework.Algorithms
  14. {
  15.     public partial class LootGenerator
  16.     {
  17.         private VoidwalkerRandom _random;
  18.         private Dictionary<ItemConstraint, List<LegendaryTemplate>> _legendaryItems;
  19.  
  20.         static LootGenerator()
  21.         {
  22.             InitializeMagicalAffixIndices();
  23.             InitializeRareNameSuffixes();
  24.         }
  25.  
  26.         public LootGenerator(Dictionary<ItemConstraint, List<LegendaryTemplate>> legendaryItems)
  27.         {
  28.             this._legendaryItems = legendaryItems;
  29.             _random = new VoidwalkerRandom();
  30.         }
  31.  
  32.         /// <summary>
  33.         /// Generates a new Item, using a given base item as a foundation.
  34.         /// </summary>
  35.         /// <typeparam name="T"></typeparam>
  36.         /// <param name="baseItem"></param>
  37.         /// <param name="lootParams"></param>
  38.         /// <param name="level"></param>
  39.         /// <param name="totalMagicFind"></param>
  40.         /// <returns></returns>
  41.         public T Generate<T>(T baseItem, LootQualityParams lootParams, int level, double totalMagicFind)
  42.             where T : GameItem
  43.         {
  44.             switch (baseItem)
  45.             {
  46.                 case Weapon baseWeapon:
  47.                     Weapon weaponResult = new Weapon();
  48.                     weaponResult.Copy(baseWeapon);
  49.                     GenerateItem(
  50.                         baseWeapon.Category.ToItemConstraint(),
  51.                         baseWeapon.Name,
  52.                         lootParams,
  53.                         level,
  54.                         totalMagicFind,
  55.                         out QualityType weaponQuality,
  56.                         out string weaponHeader,
  57.                         out string weaponFlavorText,
  58.                         out ItemModifiers weaponModifiers);
  59.                     weaponResult.Header = weaponHeader;
  60.                     weaponResult.Quality = weaponQuality;
  61.                     weaponResult.FlavorText = weaponFlavorText;
  62.                     weaponResult.Modifiers.Add(weaponModifiers);
  63.                     return (T)((object)weaponResult);
  64.                 case Armor baseArmor:
  65.                     Armor armorResult = new Armor();
  66.                     armorResult.Copy(baseItem);
  67.                     GenerateItem(
  68.                         baseArmor.Category.ToItemConstraint(baseArmor.Weight),
  69.                         baseItem.Name,
  70.                         lootParams,
  71.                         level,
  72.                         totalMagicFind,
  73.                         out QualityType quality,
  74.                         out string header,
  75.                         out string flavorText,
  76.                         out ItemModifiers modifiers);
  77.                     armorResult.Header = header;
  78.                     armorResult.Quality = quality;
  79.                     armorResult.FlavorText = flavorText;
  80.                     armorResult.Modifiers.Add(modifiers);
  81.                     return (T)((object)armorResult);
  82.                 case Jewelry baseJewelry:
  83.                     Jewelry jewelryResult = new Jewelry();
  84.                     jewelryResult.Copy(baseItem);
  85.                     GenerateItem(
  86.                         baseJewelry.Category.ToItemConstraint(),
  87.                         baseItem.Name,
  88.                         lootParams,
  89.                         level,
  90.                         totalMagicFind,
  91.                         out QualityType jewelryQuality,
  92.                         out string jewelryHeader,
  93.                         out string jewelryFlavorText,
  94.                         out ItemModifiers jewelryModifiers);
  95.                     jewelryResult.Header = jewelryHeader;
  96.                     jewelryResult.Quality = jewelryQuality;
  97.                     jewelryResult.FlavorText = jewelryFlavorText;
  98.                     jewelryResult.Modifiers.Add(jewelryModifiers);
  99.                     return (T)((object)jewelryResult);
  100.                 case Shield baseShield:
  101.                     Shield shieldResult = new Shield();
  102.                     shieldResult.Copy(baseShield);
  103.                     GenerateItem(
  104.                         shieldResult.Category.ToItemConstraint(),
  105.                         baseItem.Name,
  106.                         lootParams,
  107.                         level,
  108.                         totalMagicFind,
  109.                         out QualityType shieldQuality,
  110.                         out string shieldHeader,
  111.                         out string shieldFlavorText,
  112.                         out ItemModifiers shieldModifiers);
  113.                     shieldResult.Header = shieldHeader;
  114.                     shieldResult.Quality = shieldQuality;
  115.                     shieldResult.FlavorText = shieldFlavorText;
  116.                     shieldResult.Modifiers.Add(shieldModifiers);
  117.                     return (T)((object)shieldResult);
  118.                 default:
  119.                     throw new Exception("Illegal Generator Type: " + baseItem.GetType());
  120.             }
  121.         }
  122.  
  123.         private void GenerateItem(ItemConstraint itemConstraint, string baseItemName, LootQualityParams lootQualityParams, int level, double totalMagicFind,
  124.             out QualityType quality, out string header, out string flavorText, out ItemModifiers modifiers)
  125.         {
  126.             bool isEthereal = TryForEthereal();
  127.             modifiers = new ItemModifiers();
  128.             if (isEthereal)
  129.             {
  130.                 modifiers.StaticModifiers.Add(new ItemModifier(ItemModifierTrait.Ethereal));
  131.             }
  132.             quality = GenerateItemQuality(lootQualityParams, totalMagicFind);
  133.             switch (quality)
  134.             {
  135.                 case QualityType.Uncommon:
  136.                     GenerateUncommonItem(
  137.                         itemConstraint,
  138.                         isEthereal,
  139.                         level,
  140.                         baseItemName,
  141.                         out string uncommonHeader,
  142.                         out ItemModifiers uncommonModifiers);
  143.                     header = uncommonHeader;
  144.                     modifiers.Add(uncommonModifiers);
  145.                     flavorText = "";
  146.                     return;
  147.                 case QualityType.Rare:
  148.                     GenerateRareItem(
  149.                         itemConstraint,
  150.                         isEthereal,
  151.                         level,
  152.                         baseItemName,
  153.                         out string rareHeader,
  154.                         out ItemModifiers rareModifiers);
  155.                     header = rareHeader;
  156.                     modifiers.Add(rareModifiers);
  157.                     flavorText = "";
  158.                     return;
  159.                 case QualityType.Legendary:
  160.                     GenerateLegendaryItem(
  161.                         itemConstraint,
  162.                         level,
  163.                         out string legendaryHeader,
  164.                         out ItemModifiers legendaryModifiers,
  165.                         out string legendaryFlavorText,
  166.                         out bool isGeneratorFailure);
  167.                     if (!isGeneratorFailure)
  168.                     {
  169.                         header = legendaryHeader;
  170.                         modifiers.Add(legendaryModifiers);
  171.                         flavorText = legendaryFlavorText;
  172.                         return;
  173.                     }
  174.                     else
  175.                     {
  176.                         /**
  177.                          * No Legendary item exists for the given parameters.
  178.                          * As such, we will instead default to giving the player
  179.                          * a guaranteed Rare item.
  180.                          */
  181.                         quality = QualityType.Rare;
  182.                         goto case QualityType.Rare;
  183.                     }
  184.                 default:
  185.                     /**
  186.                      * The Item Generator didnt create anything. We will return a copy
  187.                      * of the base item instead.
  188.                      */
  189.                     header = "";
  190.                     flavorText = "";
  191.                     return;
  192.             }
  193.         }
  194.  
  195.         /// <summary>
  196.         /// Generates and Uncommon Item
  197.         /// </summary>
  198.         /// <param name="itemConstraint"></param>
  199.         /// <param name="isEthereal"></param>
  200.         /// <param name="level"></param>
  201.         /// <param name="baseItemName"></param>
  202.         /// <param name="uncommonHeader"></param>
  203.         /// <param name="modifiers"></param>
  204.         public void GenerateUncommonItem(ItemConstraint itemConstraint, bool isEthereal, int level, string baseItemName,
  205.             out string uncommonHeader, out ItemModifiers modifiers)
  206.         {
  207.             int affixQuantity = _random.NextRange(0, 4);
  208.             List<Affix> affixes = new List<Affix>();
  209.             switch (affixQuantity)
  210.             {
  211.                 case 0: // Both Prefix and Suffix
  212.                     affixes.Add(NextRawAffix(AffixType.Prefix, itemConstraint, level));
  213.                     affixes.Add(NextRawAffix(AffixType.Suffix, itemConstraint, level));
  214.                     break;
  215.                 case 1: // Prefix Only
  216.                 case 2: // Prefix Only
  217.                     affixes.Add(NextRawAffix(AffixType.Prefix, itemConstraint, level));
  218.                     break;
  219.                 case 3: // Suffix Only
  220.                     affixes.Add(NextRawAffix(AffixType.Suffix, itemConstraint, level));
  221.                     break;
  222.             }
  223.             // Generate the Uncommon Name
  224.             string outputHeader = baseItemName;
  225.             for (int i = 0; i < affixes.Count; i++)
  226.             {
  227.                 Affix affix = affixes[i];
  228.                 switch (affix.AffixType)
  229.                 {
  230.                     case AffixType.Prefix:
  231.                         outputHeader = affix.Name + outputHeader;
  232.                         break;
  233.                     default: // Counts as Suffix
  234.                         outputHeader += affix.Name;
  235.                         break;
  236.                 }
  237.             }
  238.             uncommonHeader = outputHeader;
  239.             modifiers = ConvertAffixesToModifiers(affixes, isEthereal);
  240.         }
  241.  
  242.         /// <summary>
  243.         /// Generates a Rare Item
  244.         /// </summary>
  245.         /// <param name="itemConstraint"></param>
  246.         /// <param name="isEthereal"></param>
  247.         /// <param name="level"></param>
  248.         /// <param name="baseItemName"></param>
  249.         /// <param name="rareHeader"></param>
  250.         /// <param name="modifiers"></param>
  251.         public void GenerateRareItem(ItemConstraint itemConstraint, bool isEthereal, int level, string baseItemName,
  252.             out string rareHeader, out ItemModifiers modifiers)
  253.         {
  254.             rareHeader = GenerateRareName(itemConstraint);
  255.             int probability = 100;
  256.             bool isSearching = true;
  257.             int affixesFound = 0;
  258.             // Find Prefixes
  259.             List<Affix> affixes = new List<Affix>();
  260.             while (isSearching)
  261.             {
  262.                 Affix affix = NextRawAffix(AffixType.Prefix, itemConstraint, level);
  263.                 if (!affixes.Any(a => a.Name.Equals(affix.Name)))
  264.                 {
  265.                     affixesFound++;
  266.                     if (_random.NextProbability(probability))
  267.                     {
  268.                         affixes.Add(affix);
  269.                     }
  270.                     if (affixesFound >= 2)
  271.                     {
  272.                         probability = 25;
  273.                     }
  274.                     if (affixesFound >= 3)
  275.                     {
  276.                         isSearching = false;
  277.                     }
  278.                 }
  279.             }
  280.             // Find Suffixes
  281.             probability = 100;
  282.             affixesFound = 0;
  283.             isSearching = true;
  284.             while (isSearching)
  285.             {
  286.                 Affix affix = NextRawAffix(AffixType.Suffix, itemConstraint, level);
  287.                 if (!affixes.Any(a => a.Name.Equals(affix.Name)))
  288.                 {
  289.                     affixesFound++;
  290.                     if (_random.NextProbability(probability))
  291.                     {
  292.                         affixes.Add(affix);
  293.                     }
  294.                     if (affixesFound >= 1)
  295.                     {
  296.                         probability = 40;
  297.                     }
  298.                     if (affixesFound >= 3)
  299.                     {
  300.                         isSearching = false;
  301.                     }
  302.                 }
  303.             }
  304.             modifiers = ConvertAffixesToModifiers(affixes, isEthereal);
  305.         }
  306.  
  307.         /// <summary>
  308.         /// Generates a Legendary Item
  309.         /// </summary>
  310.         /// <param name="itemConstraint"></param>
  311.         /// <param name="level"></param>
  312.         /// <param name="legendaryHeader"></param>
  313.         /// <param name="modifiers"></param>
  314.         /// <param name="flavorText"></param>
  315.         /// <param name="isGeneratorFailure"></param>
  316.         public void GenerateLegendaryItem(ItemConstraint itemConstraint, int level,
  317.             out string legendaryHeader, out ItemModifiers modifiers, out string flavorText, out bool isGeneratorFailure)
  318.         {
  319.             isGeneratorFailure = false;
  320.             if (_legendaryItems.ContainsKey(itemConstraint))
  321.             {
  322.                 List<LegendaryTemplate> eligibleLegendaries = new List<LegendaryTemplate>();
  323.                 foreach (LegendaryTemplate legendary in _legendaryItems[itemConstraint])
  324.                 {
  325.                     if (legendary.Level.Contains(level))
  326.                     {
  327.                         eligibleLegendaries.Add(legendary);
  328.                     }
  329.                 }
  330.                 modifiers = new ItemModifiers();
  331.                 if (eligibleLegendaries.Count > 0)
  332.                 {
  333.                     LegendaryTemplate rolledLegendary = _random.Choose(eligibleLegendaries);
  334.                     legendaryHeader = rolledLegendary.Name;
  335.                     flavorText = rolledLegendary.FlavorText;
  336.                     foreach (ItemModifier property in rolledLegendary.Modifiers.DynamicModifiers)
  337.                     {
  338.                         modifiers.DynamicModifiers.Add(new ItemModifier(property));
  339.                     }
  340.                     return;
  341.                 }
  342.             }
  343.             legendaryHeader = null;
  344.             flavorText = null;
  345.             isGeneratorFailure = true;
  346.             modifiers = null;
  347.         }
  348.  
  349.         /// <summary>
  350.         /// Generates a QualityType
  351.         /// </summary>
  352.         /// <param name="lootParams"></param>
  353.         /// <param name="totalMagicFind"></param>
  354.         /// <returns></returns>
  355.         private QualityType GenerateItemQuality(LootQualityParams lootParams, double totalMagicFind)
  356.         {
  357.             int uncommonChance = lootParams.UncommonChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
  358.             int rareChance = lootParams.RareChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
  359.             int legendaryChance = lootParams.LegendaryChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
  360.             uncommonChance = VoidwalkerMath.Clamp(uncommonChance, 0, 100);
  361.             rareChance = VoidwalkerMath.Clamp(rareChance, 0, 100);
  362.             legendaryChance = VoidwalkerMath.Clamp(legendaryChance, 0, 100);
  363.             if (_random.NextProbability(legendaryChance))
  364.             {
  365.                 return QualityType.Legendary;
  366.             }
  367.             if (_random.NextProbability(rareChance))
  368.             {
  369.                 return QualityType.Rare;
  370.             }
  371.             if (_random.NextProbability(uncommonChance))
  372.             {
  373.                 return QualityType.Uncommon;
  374.             }
  375.             return QualityType.Common;
  376.         }
  377.  
  378.         /// <summary>
  379.         /// Attempts to generate the flag for an item being Ethereal
  380.         /// The current odds of rolling an Ethereal item is 1 in 1024 (‭‭0.0009765625‬%)
  381.         /// </summary>
  382.         /// <param name="baseItem"></param>
  383.         public bool TryForEthereal()
  384.         {
  385.             return _random.NextOdds(1, 1024);
  386.         }
  387.  
  388.         /// <summary>
  389.         /// Converts a List of raw affixes to ItemModifiers
  390.         /// </summary>
  391.         /// <param name="affixes"></param>
  392.         /// <param name="isEthereal"></param>
  393.         /// <returns></returns>
  394.         private ItemModifiers ConvertAffixesToModifiers(List<Affix> affixes, bool isEthereal)
  395.         {
  396.             ItemModifiers modifiers = new ItemModifiers();
  397.             foreach (Affix affix in affixes)
  398.             {
  399.                 if (affix != null)
  400.                 {
  401.                     int value;
  402.                     if (affix.Property.IsRange())
  403.                     {
  404.                         modifiers.DynamicModifiers.Add(new ItemModifier(affix.Property, affix.Minimum, affix.Maximum));
  405.                     }
  406.                     else
  407.                     {
  408.                         value = isEthereal ? affix.Maximum : _random.NextRange(affix.Minimum, affix.Maximum);
  409.                         modifiers.DynamicModifiers.Add(new ItemModifier(affix.Property, value));
  410.                     }
  411.                 }
  412.             }
  413.             return modifiers;
  414.         }
  415.     }
  416. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement