示例#1
0
        private void ReplaceTreasures(IEnumerable <Item> items)
        {
            var treasures = new TreasureData(rom);

            treasures.LoadTable();

            var pool1 = GetLegendaryPool();
            var pool2 = ItemLists.RareWeaponTier.Concat(ItemLists.RareArmorTier).Where(i => !pool1.Contains(i)).ToList();
            var pool3 = ItemLists.CommonArmorTier.Concat(ItemLists.CommonWeaponTier).ToList();

            var hqPool = new HashSet <Item>(pool1.Concat(pool2));

            items = items.Where(i => hqPool.Contains(i)).ToArray();

            foreach (var i in items)
            {
                var indices = treasures.Data.Select((item, idx) => (item, idx)).Where(e => e.item == i).ToList();
                if (indices.Count > 0)
                {
                    var idx = indices.PickRandom(rng).idx;
                    treasures[idx] = ExtConsumables.ExtConsumableStartingEquipmentFix(pool3.PickRandom(rng), flags);
                }
            }

            treasures.StoreTable();
        }
示例#2
0
        public void SetStartingEquipment()
        {
            var items = GetEquipment();

            ExtConsumables.ExtConsumableStartingEquipmentFix(items.Weapons, flags);

            if (flags.StartingEquipmentRemoveFromPool)
            {
                ReplaceTreasures(items.Weapons.Concat(items.Armor));
            }

            for (int i = 0; i < 16; i++)
            {
                if (items.Weapons[i] > 0)
                {
                    items.Weapons[i] -= Item.Soft;
                }
                if (items.Armor[i] > 0)
                {
                    items.Armor[i] -= Item.Masamune;
                }
            }

            for (int i = 0; i < 4; i++)
            {
                byte[] buffer1 = new byte[4];
                Buffer.BlockCopy(items.Weapons, 4 * i, buffer1, 0, 4);

                byte[] buffer2 = new byte[4];
                Buffer.BlockCopy(items.Armor, 4 * i, buffer2, 0, 4);

                rom.PutInBank(0x1B, 0x8520 + 0x08 * i, buffer1);
                rom.PutInBank(0x1B, 0x8524 + 0x08 * i, buffer2);
            }

            rom.PutInBank(0x1B, 0x8540, Blob.FromHex("A200A000205785A040205785A080205785A0C020578560BD2085991861E8C898290FC908D0F160"));
        }
        // Scale is the geometric scale factor used with RNG.  Multiplier is where we make everything cheaper
        // instead of enemies giving more gold, so we don't overflow.
        public void ScalePrices(IScaleFlags flags, MT19337 rng, bool increaseOnly, ItemShopSlot shopItemLocation, bool FreeClinic = false)
        {
            IEnumerable <Item> tmpExcludedItems = Array.Empty <Item>();

            if (flags.ExcludeGoldFromScaling ?? false)
            {
                tmpExcludedItems = tmpExcludedItems.Concat(ItemLists.AllGoldTreasure);
            }
            if ((flags.ExcludeGoldFromScaling ?? false) && flags.CheapVendorItem)
            {
                tmpExcludedItems = tmpExcludedItems.Concat(ItemLists.AllQuestItems);
            }

            HashSet <Item> excludedItems = new HashSet <Item>(tmpExcludedItems);
            HashSet <Item> questItems    = new HashSet <Item>(ItemLists.AllQuestItems);

            int rawScaleLow  = increaseOnly ? 100 : flags.PriceScaleFactorLow;
            int rawScaleHigh = increaseOnly ? Math.Max(100, flags.PriceScaleFactorHigh) : flags.PriceScaleFactorHigh;

            double scaleLow  = (double)rawScaleLow / 100.0;
            double scaleHigh = (double)rawScaleHigh / 100.0;

            var multiplier = flags.ExcludeGoldFromScaling ?? false ? 1.0 : flags.ExpMultiplier;
            var prices     = Get(PriceOffset, PriceSize * PriceCount).ToUShorts();

            for (int i = 0; i < prices.Length; i++)
            {
                if (excludedItems.Contains((Item)i))
                {
                    var price = (int)prices[i];

                    if (flags.CheapVendorItem && questItems.Contains((Item)i))
                    {
                        price = 20000;
                    }

                    var newPrice = price + rng.Between(-price / 10, price / 10);
                    prices[i] = (ushort)Math.Min(Math.Max(newPrice, 1), 65535);
                }
                else
                {
                    var price    = ExtConsumables.ExtConsumablePriceFix((Item)i, prices[i], flags);
                    var newPrice = RangeScaleWithZero(price / multiplier, scaleLow, scaleHigh, 1e-5 * multiplier, 1, rng);
                    prices[i] = (ushort)Min(newPrice, 0xFFFF);
                }
            }
            var questItemPrice = prices[(int)Item.Bottle];

            // If we don't do this before checking for the item shop location factor, Ribbons and Shirts will end up being really cheap
            // This realistically doesn't matter without Shop Wares shuffle on because nobody wants to sell Ribbons/Shirts, but if it is...
            prices[(int)Item.WhiteShirt] = (ushort)(questItemPrice / 2);
            prices[(int)Item.BlackShirt] = (ushort)(questItemPrice / 2);
            prices[(int)Item.Ribbon]     = questItemPrice;
            var itemShopFactor = new Dictionary <MapLocation, int>()
            {
                { MapLocation.Coneria, 8 },
                { MapLocation.Pravoka, 2 }
            };

            if (itemShopFactor.TryGetValue(shopItemLocation.MapLocation, out int divisor))
            {
                questItemPrice = (ushort)(prices[(int)Item.Bottle] / divisor);
            }
            for (var i = 0; i < (int)Item.Tent; i++)
            {
                prices[i] = questItemPrice;
            }
            Put(PriceOffset, Blob.FromUShorts(prices));

            for (int i = GoldItemOffset; i < GoldItemOffset + GoldItemCount; i++)
            {
                ItemsText[i] = prices[i].ToString() + " G";
            }

            var pointers = Get(ShopPointerOffset, ShopPointerCount * ShopPointerSize).ToUShorts();

            RepackShops(pointers);

            for (int i = (int)ShopType.Clinic; i < (int)ShopType.Inn + ShopSectionSize; i++)
            {
                if (pointers[i] != ShopNullPointer)
                {
                    var priceBytes = Get(ShopPointerBase + pointers[i], 2);
                    var priceValue = BitConverter.ToUInt16(priceBytes, 0);

                    priceValue = (ushort)RangeScale(priceValue / multiplier, scaleLow, scaleHigh, 1, rng);
                    if (FreeClinic && i < (int)ShopType.Clinic + ShopSectionSize)
                    {
                        priceValue = 0;
                    }
                    priceBytes = BitConverter.GetBytes(priceValue);
                    Put(ShopPointerBase + pointers[i], priceBytes);
                }
            }

            List <(StartingGold, ushort)> startingGold = new()
            {
                (StartingGold.None, 0),
                (StartingGold.Gp100, 100),
                (StartingGold.Gp200, 200),
                (StartingGold.Gp400, 400),
                (StartingGold.Gp800, 800),
                (StartingGold.Gp2500, 2500),
                (StartingGold.Gp9999, 9999),
                (StartingGold.Gp65535, 65535),
                (StartingGold.RandomLow, (ushort)rng.Between(0, 800)),
                (StartingGold.RandomHigh, (ushort)rng.Between(0, 65535)),
            };

            Put(StartingGoldOffset, BitConverter.GetBytes(startingGold[(int)flags.StartingGold].Item2));
        }