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.Systems.Enchanting;
- using VoidwalkerEngine.Framework.Systems.Items.Base;
- using VoidwalkerEngine.Framework.Systems.Items.Templates;
- using VoidwalkerEngine.Framework.Systems.Loot;
- using VoidwalkerEngine.Framework.Utilities;
- namespace VoidwalkerEngine.Framework.Algorithms
- {
- public partial class LootGenerator
- {
- private VoidwalkerRandom _random;
- private List<LegendaryTemplate> _legendaries { get; set; }
- private List<Enchantment> _enchantments { get; set; }
- static LootGenerator()
- {
- InitializeRareNameSuffixes();
- }
- public LootGenerator()
- {
- _enchantments = new List<Enchantment>();
- _random = new VoidwalkerRandom();
- if (GameDatabase.Enchantments != null)
- {
- foreach (Enchantment enchantment in GameDatabase.Enchantments)
- {
- if (enchantment.IsSpawnable)
- {
- this._enchantments.Add(enchantment);
- }
- }
- this._legendaries = GameDatabase.Legendaries;
- }
- }
- public List<GameItem> Process(int level, List<LootTableDrop> items)
- {
- if (items == null || items.Count == 0)
- {
- return null;
- }
- List<GameItem> results = new List<GameItem>();
- foreach (LootTableDrop drop in items)
- {
- int quantity = _random.NextRange(drop.Quantity);
- if (quantity > 0)
- {
- if (drop.Item.IsEnchantable)
- {
- /**
- * Roll Enchantments for each item in quantity.
- * This allows for multiple items to have different
- * enchantments, and qualities.
- */
- for (int i = 0; i < quantity; i++)
- {
- GameItem item = Generate(drop.Item, drop.LootArgs, level);
- results.Add(item);
- }
- }
- else
- {
- List<GameItem> existingStacks = new List<GameItem>();
- foreach (GameItem item in results)
- {
- if (item.IsStackableWith(drop.Item))
- {
- existingStacks.Add(item);
- }
- }
- if (existingStacks.Count == 0)
- {
- existingStacks.Add(drop.Item.MakeCopy());
- }
- int currentStackIndex = 0;
- for (int i = 1; i < quantity; i++)
- {
- int totalQuantity = existingStacks[currentStackIndex].Quantity + 1;
- if (totalQuantity <= 20)
- {
- existingStacks[currentStackIndex].Quantity++;
- }
- else
- {
- currentStackIndex++;
- existingStacks.Add(drop.Item.MakeCopy());
- }
- }
- results.RemoveAll(p => p.Identifier.Equals(drop.Item.Identifier));
- results.AddRange(existingStacks);
- }
- }
- }
- return results;
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="template"></param>
- /// <param name="lootParams"></param>
- /// <param name="level"></param>
- /// <param name="totalMagicFind"></param>
- /// <returns></returns>
- public GameItem Generate(GameItem template, LootDropArgs lootParams, int level)
- {
- GameItem result = template.MakeCopy();
- if (result.IsSpawnable)
- {
- result.Quality = GenerateItemQuality(lootParams);
- result.IsEthereal = GenerateEthereal();
- ItemType itemConstraint = result.Category;
- result.Enchantments = new List<Enchantment>();
- int maximumEnchantments = result.Quality.GetMaximumEnchantmentSlots();
- if (result.Quality == QualityType.Legendary)
- {
- maximumEnchantments -= 1;
- }
- int enchantmentCount =
- result.IsEthereal ?
- maximumEnchantments :
- GenerateEnchantmentCount(result.Quality);
- // Generate enchantments based upon quality
- switch (result.Quality)
- {
- case QualityType.Uncommon:
- result.Enchantments = GenerateEnchantments(itemConstraint, level, enchantmentCount);
- break;
- case QualityType.Rare:
- result.Enchantments = GenerateEnchantments(itemConstraint, level, enchantmentCount);
- result.Header = GenerateRareName(itemConstraint);
- break;
- case QualityType.Epic:
- result.Enchantments = GenerateEnchantments(itemConstraint, level, enchantmentCount);
- result.Header = GenerateEpicName();
- break;
- case QualityType.Legendary:
- if (this._legendaries != null)
- {
- List<LegendaryTemplate> candidates = new List<LegendaryTemplate>();
- foreach (LegendaryTemplate candidate in this._legendaries)
- {
- if (candidate.Constraints.Contains(itemConstraint))
- {
- if (candidate.LevelBracket.Contains(level))
- {
- candidates.Add(candidate);
- }
- }
- }
- if (candidates.Count > 0)
- {
- LegendaryTemplate legendary = _random.Choose(candidates);
- Enchantment legendaryEnchantment = GameDatabase.GetEnchantment(legendary.Enchantment);
- if (legendaryEnchantment != null)
- {
- result.Enchantments.Add(legendaryEnchantment);
- }
- // generate enchantments
- result.Enchantments = GenerateEnchantments(itemConstraint, level, enchantmentCount);
- result.Header = legendary.Header;
- result.FlavorText = legendary.FlavorText;
- break;
- }
- }
- /**
- * The player rolled a legendary, however the routine failed. This may mean
- * that no legendary exists for their level bracket, or the item type has no
- * corresponding legendary. We will default to giving them a guaranteed epic.
- */
- result.Quality = QualityType.Epic;
- goto case QualityType.Epic;
- }
- result.Repair();
- return result;
- }
- else
- {
- return result;
- }
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="dropArgs"></param>
- /// <returns></returns>
- public QualityType GenerateItemQuality(LootDropArgs dropArgs)
- {
- /**
- * This needs to handle probabilities as doubles instead.
- */
- if (_random.NextProbability(dropArgs.LegendaryChance))
- {
- return QualityType.Legendary;
- }
- if (_random.NextProbability(dropArgs.EpicChance))
- {
- return QualityType.Epic;
- }
- if (_random.NextProbability(dropArgs.RareChance))
- {
- return QualityType.Rare;
- }
- if (_random.NextProbability(dropArgs.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>
- public bool GenerateEthereal()
- {
- return _random.NextOdds(1, 1024);
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="constraint"></param>
- /// <param name="level"></param>
- /// <returns></returns>
- public Enchantment GenerateEnchantment(ItemType constraint, int level)
- {
- if (this._enchantments == null || this._enchantments.Count == 0)
- {
- return null;
- }
- return GenerateEnchantments(constraint, level, 1)[0];
- }
- /// <summary>
- ///
- /// </summary>
- /// <param name="constraint"></param>
- /// <param name="level"></param>
- /// <param name="count"></param>
- /// <param name="allowDuplicates"></param>
- /// <returns></returns>
- private List<Enchantment> GenerateEnchantments(ItemType constraint, int level, int count, bool allowDuplicates = false)
- {
- List<Enchantment> results = new List<Enchantment>();
- if (count == 0)
- {
- return results;
- }
- int totalFitness = 0;
- List<Enchantment> filteredEnchantments = new List<Enchantment>();
- foreach (Enchantment candidate in this._enchantments)
- {
- if (candidate.Constraints.Contains(constraint))
- {
- if (candidate.LevelBracket.Contains(level))
- {
- filteredEnchantments.Add(candidate);
- totalFitness += candidate.Frequency;
- }
- }
- }
- if (filteredEnchantments.Count < count)
- {
- count = filteredEnchantments.Count;
- if (count == 0)
- {
- return results;
- }
- }
- filteredEnchantments.OrderBy(enchantment => enchantment.Frequency).Reverse().ToList();
- int enchantmentsGenerated = 0;
- bool isSearching = true;
- int attempts = 0;
- const int maximumAttempts = 32; // Prevent Infinite Loops
- while (isSearching)
- {
- Enchantment selectedEnchantment = null;
- int randomSample = _random.NextInteger(totalFitness);
- foreach (Enchantment attempt in filteredEnchantments)
- {
- if (randomSample < attempt.Frequency)
- {
- selectedEnchantment = attempt;
- break;
- }
- randomSample -= attempt.Frequency;
- }
- if (allowDuplicates ||
- !results.Any(e => e == selectedEnchantment) &&
- !results.Any(e => e.Family.Equals(selectedEnchantment.Family)))
- {
- attempts = 0;
- results.Add(selectedEnchantment);
- enchantmentsGenerated++;
- }
- attempts++;
- if (enchantmentsGenerated == count || attempts >= maximumAttempts)
- {
- isSearching = false;
- }
- }
- return results;
- }
- private int GenerateEnchantmentCount(QualityType quality)
- {
- int result = 0;
- switch (quality)
- {
- case QualityType.Uncommon:
- if (_random.NextProbability(75))
- {
- return 1;
- }
- break;
- case QualityType.Rare:
- if (_random.NextProbability(75))
- {
- result += 1;
- }
- if (_random.NextProbability(40))
- {
- result += 1;
- }
- break;
- case QualityType.Epic:
- if (_random.NextProbability(75))
- {
- result += 1;
- }
- for (int i = 0; i < 2; i++)
- {
- if (_random.NextProbability(40))
- {
- result += 1;
- }
- }
- break;
- case QualityType.Legendary:
- if (_random.NextProbability(75))
- {
- result += 1;
- }
- if (_random.NextProbability(75))
- {
- result += 1;
- }
- if (_random.NextProbability(40))
- {
- result += 1;
- }
- break;
- }
- return result;
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement