public ItemGenerator(List <Item> seedPool, WorldWealthMode wealth) { // Make a copy var treasurePool = seedPool.ToList(); // Make sure we copy all the input lists so we don't modify anything static. List <List <Item> > tiers = new List <List <Item> > { ItemLists.UberTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.LegendaryWeaponTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.LegendaryArmorTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.RareWeaponTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.RareArmorTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.CommonWeaponTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.CommonArmorTier.Where(item => treasurePool.Remove(item)).ToList(), ItemLists.AllConsumables.Where(item => treasurePool.Remove(item)).ToList(), treasurePool.Where(x => x >= Item.Gold10 && x <= Item.Gold65000).ToList(), }; List <int> ratios = Ratios[(int)wealth]; System.Diagnostics.Debug.Assert(tiers.Count == ratios.Count); System.Diagnostics.Debug.Assert(Enum.GetValues(typeof(WorldWealthMode)).Length == Ratios.Length); // Now populate the comined pool with a weighted average of all those above lists. _pool = new List <List <Item> >(); for (int i = 0; i < ratios.Count(); ++i) { for (int j = 0; j < ratios[i]; ++j) { if (tiers[i].Any()) { _pool.Add(tiers[i]); } } } }
public ItemShopSlot ShuffleShops(MT19337 rng, bool earlyAilments, bool randomizeWeaponsAndArmor, IEnumerable <Item> excludeItemsFromRandomShops, WorldWealthMode wealth, int coneriaEntranceShopIndex) { var pointers = Get(ShopPointerOffset, ShopPointerCount * ShopPointerSize).ToUShorts(); RepackShops(pointers); ShuffleShopType(ShopType.Weapon, pointers, rng, randomizeWeaponsAndArmor, excludeItemsFromRandomShops, wealth); ShuffleShopType(ShopType.Armor, pointers, rng, randomizeWeaponsAndArmor, excludeItemsFromRandomShops, wealth); ItemShopSlot result = null; do { result = ShuffleShopType(ShopType.Item, pointers, rng); } while (earlyAilments && !AilmentsCovered(pointers, coneriaEntranceShopIndex)); if (result == null) { throw new InvalidOperationException("Shop Location for Bottle was not set"); } Put(ShopPointerOffset, Blob.FromUShorts(pointers)); return(result); }
private ItemShopSlot ShuffleShopType(ShopType shopType, ushort[] pointers, MT19337 rng, bool randomize = false, IEnumerable <Item> excludeItemsFromRandomShops = null, WorldWealthMode wealth = WorldWealthMode.Normal) { var shops = GetShops(shopType, pointers); bool shopsBlocked; List <byte>[] newShops; do { shopsBlocked = false; newShops = new List <byte> [ShopSectionSize]; var allEntries = shops.SelectMany(list => list).ToList(); allEntries.Shuffle(rng); int entry = 0; for (int i = 0; i < ShopSectionSize; i++) { newShops[i] = new List <byte>(); if (pointers[(int)shopType + i] != ShopNullPointer) { newShops[i].Add(allEntries[entry++]); } } while (entry < allEntries.Count) { var eligibleShops = new List <int>(); for (int i = 0; i < newShops.Length; i++) { if (newShops[i].Count > 0 && newShops[i].Count < 5 && !newShops[i].Contains(allEntries[entry])) { eligibleShops.Add(i); } } // We might be unable to place an item in any shop because they're all full, or they already have that item. Start over. if (eligibleShops.Count == 0) { shopsBlocked = true; break; } int shopIndex = eligibleShops[rng.Between(0, eligibleShops.Count - 1)]; newShops[shopIndex].Add(allEntries[entry++]); } } while (shopsBlocked); if (randomize) { if (shopType == ShopType.Weapon || shopType == ShopType.Armor) { // Shuffle up a byte array of random weapons or armor and assign them in place of the existing items. var baseIndex = shopType == ShopType.Armor ? Item.Cloth : Item.WoodenNunchucks; var indeces = Enumerable.Range((int)baseIndex, 40).Select(i => (Item)i).ToList(); foreach (var exclusion in excludeItemsFromRandomShops ?? new List <Item>()) { indeces.Remove(exclusion); } ItemGenerator generator = new ItemGenerator(indeces, wealth); for (int i = 0; i < newShops.Length; i++) { newShops[i] = newShops[i].Select(x => (byte)generator.SpliceItem(rng)).ToList(); } } } // Zero-terminate the new shops. foreach (var newShop in newShops) { newShop.Add(0); } ItemShopSlot result = null; var pointer = pointers[(int)shopType]; for (int i = 0; i < ShopSectionSize; i++) { if (newShops[i].Count > 1) { var bottle = newShops[i] .Select((item, index) => new { item, index }) .FirstOrDefault(x => ((Item)x.item) == Item.Bottle); if (bottle != null) { var location = ShopMapLocationsByIndex[i]; result = new ItemShopSlot(ShopPointerBase + pointer + bottle.index, $"{Enum.GetName(typeof(MapLocation), location)}Shop{bottle.index + 1}", location, Item.Bottle); } Put(ShopPointerBase + pointer, newShops[i].ToArray()); pointers[(int)shopType + i] = pointer; pointer += (ushort)newShops[i].Count; } } return(result); }
public ItemGenerator(List <Item> seedPool, List <int> unusedGoldItems, List <Item> removedItems, WorldWealthMode wealth) { // Make a copy var treasurePool = seedPool.ToList(); // Make sure we copy all the input lists so we don't modify anything static. List <List <Item> > tiers = new List <List <Item> > { ItemLists.UberTier.Where(x => !removedItems.Contains(x)).ToList(), ItemLists.LegendaryWeaponTier.Where(x => !removedItems.Contains(x)).ToList(), ItemLists.LegendaryArmorTier.ToList(), ItemLists.RareWeaponTier.ToList(), ItemLists.RareArmorTier.ToList(), ItemLists.CommonWeaponTier.ToList(), ItemLists.CommonArmorTier.ToList(), ItemLists.AllConsumables.ToList(), ItemLists.AllGoldTreasure.Where(x => !unusedGoldItems.Contains((int)x)).ToList(), }; List <int> ratios = RelativeRatios[(int)wealth].ToList(); System.Diagnostics.Debug.Assert(tiers.Count == ratios.Count); ratios[0] += treasurePool.Where(x => ItemLists.UberTier.Contains(x)).Count(); ratios[1] += treasurePool.Where(x => ItemLists.LegendaryWeaponTier.Contains(x)).Count(); ratios[2] += treasurePool.Where(x => ItemLists.LegendaryArmorTier.Contains(x)).Count(); ratios[3] += treasurePool.Where(x => ItemLists.RareWeaponTier.Contains(x)).Count(); ratios[4] += treasurePool.Where(x => ItemLists.RareArmorTier.Contains(x)).Count(); ratios[5] += treasurePool.Where(x => ItemLists.CommonWeaponTier.Contains(x)).Count(); ratios[6] += treasurePool.Where(x => ItemLists.CommonArmorTier.Contains(x)).Count(); ratios[7] += treasurePool.Where(x => ItemLists.AllConsumables.Contains(x)).Count(); ratios[8] += treasurePool.Where(x => ItemLists.AllGoldTreasure.Contains(x)).Count(); if (!tiers[0].Any()) { ratios[1] += ratios[0]; ratios[0] = 0; } for (int i = 0; i < ratios.Count - 1; i++) { if (ratios[i] < 0) { ratios[8] += ratios[i]; ratios[i] = 0; } } // Now populate the combined pool with a weighted average of all those above lists. _pool = new List <List <Item> >(); for (int i = 0; i < ratios.Count(); ++i) { for (int j = 0; j < ratios[i]; ++j) { if (tiers[i].Any()) { _pool.Add(tiers[i]); } } } System.Diagnostics.Debug.Assert(treasurePool.Count == _pool.Count); }