Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using VoidwalkerEngine.Framework.Collections;
- using VoidwalkerEngine.Framework.DataTypes;
- using VoidwalkerEngine.Framework.Logic;
- using VoidwalkerEngine.Framework.Maths;
- using VoidwalkerEngine.Framework.Systems.Items;
- using VoidwalkerEngine.Framework.Systems.Items.Base;
- using VoidwalkerEngine.Framework.Systems.Items.Templates;
- using VoidwalkerEngine.Framework.Utilities;
- namespace VoidwalkerEngine.Framework.Algorithms
- {
- public partial class LootGenerator
- {
- private VoidwalkerRandom _random;
- private Dictionary<ItemConstraint, List<LegendaryTemplate>> _legendaryItems;
- static LootGenerator()
- {
- InitializeMagicalAffixIndices();
- InitializeRareNameSuffixes();
- }
- public LootGenerator(Dictionary<ItemConstraint, List<LegendaryTemplate>> legendaryItems)
- {
- this._legendaryItems = legendaryItems;
- _random = new VoidwalkerRandom();
- }
- /// <summary>
- /// Generates a new Item, using a given base item as a foundation.
- /// </summary>
- /// <typeparam name="T"></typeparam>
- /// <param name="baseItem"></param>
- /// <param name="lootParams"></param>
- /// <param name="level"></param>
- /// <param name="totalMagicFind"></param>
- /// <returns></returns>
- public T Generate<T>(T baseItem, LootQualityParams lootParams, int level, double totalMagicFind)
- where T : GameItem
- {
- switch (baseItem)
- {
- case Weapon baseWeapon:
- Weapon weaponResult = new Weapon();
- weaponResult.Copy(baseWeapon);
- GenerateItem(
- baseWeapon.Category.ToItemConstraint(),
- baseWeapon.Name,
- lootParams,
- level,
- totalMagicFind,
- out QualityType weaponQuality,
- out string weaponHeader,
- out string weaponFlavorText,
- out ItemModifiers weaponModifiers);
- weaponResult.Header = weaponHeader;
- weaponResult.Quality = weaponQuality;
- weaponResult.FlavorText = weaponFlavorText;
- weaponResult.Modifiers.Add(weaponModifiers);
- return (T)((object)weaponResult);
- case Armor baseArmor:
- Armor armorResult = new Armor();
- armorResult.Copy(baseItem);
- GenerateItem(
- baseArmor.Category.ToItemConstraint(baseArmor.Weight),
- baseItem.Name,
- lootParams,
- level,
- totalMagicFind,
- out QualityType quality,
- out string header,
- out string flavorText,
- out ItemModifiers modifiers);
- armorResult.Header = header;
- armorResult.Quality = quality;
- armorResult.FlavorText = flavorText;
- armorResult.Modifiers.Add(modifiers);
- return (T)((object)armorResult);
- case Jewelry baseJewelry:
- Jewelry jewelryResult = new Jewelry();
- jewelryResult.Copy(baseItem);
- GenerateItem(
- baseJewelry.Category.ToItemConstraint(),
- baseItem.Name,
- lootParams,
- level,
- totalMagicFind,
- out QualityType jewelryQuality,
- out string jewelryHeader,
- out string jewelryFlavorText,
- out ItemModifiers jewelryModifiers);
- jewelryResult.Header = jewelryHeader;
- jewelryResult.Quality = jewelryQuality;
- jewelryResult.FlavorText = jewelryFlavorText;
- jewelryResult.Modifiers.Add(jewelryModifiers);
- return (T)((object)jewelryResult);
- case Shield baseShield:
- Shield shieldResult = new Shield();
- shieldResult.Copy(baseShield);
- GenerateItem(
- shieldResult.Category.ToItemConstraint(),
- baseItem.Name,
- lootParams,
- level,
- totalMagicFind,
- out QualityType shieldQuality,
- out string shieldHeader,
- out string shieldFlavorText,
- out ItemModifiers shieldModifiers);
- shieldResult.Header = shieldHeader;
- shieldResult.Quality = shieldQuality;
- shieldResult.FlavorText = shieldFlavorText;
- shieldResult.Modifiers.Add(shieldModifiers);
- return (T)((object)shieldResult);
- default:
- throw new Exception("Illegal Generator Type: " + baseItem.GetType());
- }
- }
- private void GenerateItem(ItemConstraint itemConstraint, string baseItemName, LootQualityParams lootQualityParams, int level, double totalMagicFind,
- out QualityType quality, out string header, out string flavorText, out ItemModifiers modifiers)
- {
- bool isEthereal = TryForEthereal();
- modifiers = new ItemModifiers();
- if (isEthereal)
- {
- modifiers.StaticModifiers.Add(new ItemModifier(ItemModifierTrait.Ethereal));
- }
- quality = GenerateItemQuality(lootQualityParams, totalMagicFind);
- switch (quality)
- {
- case QualityType.Uncommon:
- GenerateUncommonItem(
- itemConstraint,
- isEthereal,
- level,
- baseItemName,
- out string uncommonHeader,
- out ItemModifiers uncommonModifiers);
- header = uncommonHeader;
- modifiers.Add(uncommonModifiers);
- flavorText = "";
- return;
- case QualityType.Rare:
- GenerateRareItem(
- itemConstraint,
- isEthereal,
- level,
- baseItemName,
- out string rareHeader,
- out ItemModifiers rareModifiers);
- header = rareHeader;
- modifiers.Add(rareModifiers);
- flavorText = "";
- return;
- case QualityType.Legendary:
- GenerateLegendaryItem(
- itemConstraint,
- level,
- out string legendaryHeader,
- out ItemModifiers legendaryModifiers,
- out string legendaryFlavorText,
- out bool isGeneratorFailure);
- if (!isGeneratorFailure)
- {
- header = legendaryHeader;
- modifiers.Add(legendaryModifiers);
- flavorText = legendaryFlavorText;
- return;
- }
- else
- {
- /**
- * No Legendary item exists for the given parameters.
- * As such, we will instead default to giving the player
- * a guaranteed Rare item.
- */
- quality = QualityType.Rare;
- goto case QualityType.Rare;
- }
- default:
- /**
- * The Item Generator didnt create anything. We will return a copy
- * of the base item instead.
- */
- header = "";
- flavorText = "";
- return;
- }
- }
- /// <summary>
- /// Generates and Uncommon Item
- /// </summary>
- /// <param name="itemConstraint"></param>
- /// <param name="isEthereal"></param>
- /// <param name="level"></param>
- /// <param name="baseItemName"></param>
- /// <param name="uncommonHeader"></param>
- /// <param name="modifiers"></param>
- public void GenerateUncommonItem(ItemConstraint itemConstraint, bool isEthereal, int level, string baseItemName,
- out string uncommonHeader, out ItemModifiers modifiers)
- {
- int affixQuantity = _random.NextRange(0, 4);
- List<Affix> affixes = new List<Affix>();
- switch (affixQuantity)
- {
- case 0: // Both Prefix and Suffix
- affixes.Add(NextRawAffix(AffixType.Prefix, itemConstraint, level));
- affixes.Add(NextRawAffix(AffixType.Suffix, itemConstraint, level));
- break;
- case 1: // Prefix Only
- case 2: // Prefix Only
- affixes.Add(NextRawAffix(AffixType.Prefix, itemConstraint, level));
- break;
- case 3: // Suffix Only
- affixes.Add(NextRawAffix(AffixType.Suffix, itemConstraint, level));
- break;
- }
- // Generate the Uncommon Name
- string outputHeader = baseItemName;
- for (int i = 0; i < affixes.Count; i++)
- {
- Affix affix = affixes[i];
- switch (affix.AffixType)
- {
- case AffixType.Prefix:
- outputHeader = affix.Name + outputHeader;
- break;
- default: // Counts as Suffix
- outputHeader += affix.Name;
- break;
- }
- }
- uncommonHeader = outputHeader;
- modifiers = ConvertAffixesToModifiers(affixes, isEthereal);
- }
- /// <summary>
- /// Generates a Rare Item
- /// </summary>
- /// <param name="itemConstraint"></param>
- /// <param name="isEthereal"></param>
- /// <param name="level"></param>
- /// <param name="baseItemName"></param>
- /// <param name="rareHeader"></param>
- /// <param name="modifiers"></param>
- public void GenerateRareItem(ItemConstraint itemConstraint, bool isEthereal, int level, string baseItemName,
- out string rareHeader, out ItemModifiers modifiers)
- {
- rareHeader = GenerateRareName(itemConstraint);
- int probability = 100;
- bool isSearching = true;
- int affixesFound = 0;
- // Find Prefixes
- List<Affix> affixes = new List<Affix>();
- while (isSearching)
- {
- Affix affix = NextRawAffix(AffixType.Prefix, itemConstraint, level);
- if (!affixes.Any(a => a.Name.Equals(affix.Name)))
- {
- affixesFound++;
- if (_random.NextProbability(probability))
- {
- affixes.Add(affix);
- }
- if (affixesFound >= 2)
- {
- probability = 25;
- }
- if (affixesFound >= 3)
- {
- isSearching = false;
- }
- }
- }
- // Find Suffixes
- probability = 100;
- affixesFound = 0;
- isSearching = true;
- while (isSearching)
- {
- Affix affix = NextRawAffix(AffixType.Suffix, itemConstraint, level);
- if (!affixes.Any(a => a.Name.Equals(affix.Name)))
- {
- affixesFound++;
- if (_random.NextProbability(probability))
- {
- affixes.Add(affix);
- }
- if (affixesFound >= 1)
- {
- probability = 40;
- }
- if (affixesFound >= 3)
- {
- isSearching = false;
- }
- }
- }
- modifiers = ConvertAffixesToModifiers(affixes, isEthereal);
- }
- /// <summary>
- /// Generates a Legendary Item
- /// </summary>
- /// <param name="itemConstraint"></param>
- /// <param name="level"></param>
- /// <param name="legendaryHeader"></param>
- /// <param name="modifiers"></param>
- /// <param name="flavorText"></param>
- /// <param name="isGeneratorFailure"></param>
- public void GenerateLegendaryItem(ItemConstraint itemConstraint, int level,
- out string legendaryHeader, out ItemModifiers modifiers, out string flavorText, out bool isGeneratorFailure)
- {
- isGeneratorFailure = false;
- if (_legendaryItems.ContainsKey(itemConstraint))
- {
- List<LegendaryTemplate> eligibleLegendaries = new List<LegendaryTemplate>();
- foreach (LegendaryTemplate legendary in _legendaryItems[itemConstraint])
- {
- if (legendary.Level.Contains(level))
- {
- eligibleLegendaries.Add(legendary);
- }
- }
- modifiers = new ItemModifiers();
- if (eligibleLegendaries.Count > 0)
- {
- LegendaryTemplate rolledLegendary = _random.Choose(eligibleLegendaries);
- legendaryHeader = rolledLegendary.Name;
- flavorText = rolledLegendary.FlavorText;
- foreach (ItemModifier property in rolledLegendary.Modifiers.DynamicModifiers)
- {
- modifiers.DynamicModifiers.Add(new ItemModifier(property));
- }
- return;
- }
- }
- legendaryHeader = null;
- flavorText = null;
- isGeneratorFailure = true;
- modifiers = null;
- }
- /// <summary>
- /// Generates a QualityType
- /// </summary>
- /// <param name="lootParams"></param>
- /// <param name="totalMagicFind"></param>
- /// <returns></returns>
- private QualityType GenerateItemQuality(LootQualityParams lootParams, double totalMagicFind)
- {
- int uncommonChance = lootParams.UncommonChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
- int rareChance = lootParams.RareChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
- int legendaryChance = lootParams.LegendaryChance * (int)Math.Floor(1 + (totalMagicFind / 100D));
- uncommonChance = VoidwalkerMath.Clamp(uncommonChance, 0, 100);
- rareChance = VoidwalkerMath.Clamp(rareChance, 0, 100);
- legendaryChance = VoidwalkerMath.Clamp(legendaryChance, 0, 100);
- if (_random.NextProbability(legendaryChance))
- {
- return QualityType.Legendary;
- }
- if (_random.NextProbability(rareChance))
- {
- return QualityType.Rare;
- }
- if (_random.NextProbability(uncommonChance))
- {
- return QualityType.Uncommon;
- }
- return QualityType.Common;
- }
- /// <summary>
- /// Attempts to generate the flag for an item being Ethereal
- /// The current odds of rolling an Ethereal item is 1 in 1024 (0.0009765625%)
- /// </summary>
- /// <param name="baseItem"></param>
- public bool TryForEthereal()
- {
- return _random.NextOdds(1, 1024);
- }
- /// <summary>
- /// Converts a List of raw affixes to ItemModifiers
- /// </summary>
- /// <param name="affixes"></param>
- /// <param name="isEthereal"></param>
- /// <returns></returns>
- private ItemModifiers ConvertAffixesToModifiers(List<Affix> affixes, bool isEthereal)
- {
- ItemModifiers modifiers = new ItemModifiers();
- foreach (Affix affix in affixes)
- {
- if (affix != null)
- {
- int value;
- if (affix.Property.IsRange())
- {
- modifiers.DynamicModifiers.Add(new ItemModifier(affix.Property, affix.Minimum, affix.Maximum));
- }
- else
- {
- value = isEthereal ? affix.Maximum : _random.NextRange(affix.Minimum, affix.Maximum);
- modifiers.DynamicModifiers.Add(new ItemModifier(affix.Property, value));
- }
- }
- }
- return modifiers;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement