Генерация предметов

Есть инвентарь сундука, в который нужно сгенерировать несколько предметов по особым правилам. Предметы типа Weapon и Ability генерируются в зависимости от уровня, каждый уровень со своей вероятностью и тут первая проблема, на данный момент все генерируется по такой схеме, есть массив с уровнями, где каждому уровню присвоено число чем больше число, тем выше шанс генерации. Я просто складываю все числа в массиве и генерирую рандомное от 0 до суммы, в какой промежуток выпало тот уровень и выпадает. Например, у нас есть 3 уровня: 1 - 100, 2 - 50, 3 - 30, сумма выходит 180, мы генерируем число от 0 до 180 если выпадает меньше 100, то первый уровень если выпадает больше 100, но меньше 150 то второй и т.д. Вот код:

    protected int GetArraySum(int[] array, int id1, int id2)
    {
        var sum = 0;
        for (int i = id1; i < id2+1; i++)
        {
            sum+=array[i];
        }
        return sum;
    }
    protected int RandomRules(int[] chanceArray) // Возвращает уровень предмета, chanceArray это массив уровней вроде: 1 - 100, 2 - 50, 3 - 30
    {
        var rand = Random.Range(0, chanceArray.Sum());
        if (0 <= rand && rand < GetArraySum(chanceArray, 0, 0))
        {
            return 0;
        }
        for (int i = 1; i < chanceArray.Length; i++)
        {
            if (GetArraySum(chanceArray, 0, (i-1)) <= rand && rand < GetArraySum(chanceArray, 0, i))
            {
                return i;
            }
        }
        return 0;        
    }

    

Ниже генерация предметов, где нужно обратить внимание на Weapons and abilities, там уже видно проблемы, не придумал ничего лучше, чем просто бесконечно генерировать в цикле пока не выпадет предмет нужного уровня. В конце проверка на то есть ли уже этот предмет у игрока, предмет можно поднять только 1 раз и навсегда, а значит рано или поздно предметы определенного уровня закончатся и начнется бесконечный цикл, как это решить кроме как городить кучу if и вести подсчет предметов по уровням, я не придумал поэтому тут нет решения. Код:

    [Header("Prefabs")]
    [SerializeField] private GameObject itemPrefab;

    [Header("Chance LVL Settings")]
    [SerializeField] public int[] LvlProgression;

    public Item Make(int _itemID = -1, string _rulesType = "Corpse")
    {
        InfoItem infoItem;
        if (_itemID == -1) infoItem = MakeInfo(_rulesType);
        else infoItem = Game.Data.ItemList[_itemID];

        return spawn(infoItem);
    }

    public InfoItem MakeInfo(string _rulesType)
    {
        InfoItem item;
        var rand = Random.Range(0, 100);
        switch (_rulesType)
        {
            case "Corpse":
                {
                    if (rand < 60) // MONEY
                    {
                        item = Game.Data.ItemList[0];
                        item.cost = Random.Range(1, 16);
                    }
                    else if (rand < 90) // HALF HEAL
                    {
                        if (Random.Range(0, 3) <= 2)
                        {
                            item = Game.Data.ItemList[2];
                        }
                        else item = Game.Data.ItemList[4];
                    }
                    else if (rand < 95) // FULL HEAL
                    {
                        if (Random.Range(0, 3) <= 2)
                        {
                            item = Game.Data.ItemList[1];
                        }
                        else item = Game.Data.ItemList[3];
                    }
                    else// Weapons and abilities
                    {
                        var itemLvl = RandomRules(LvlProgression);
                        item = Game.Data.ItemList[Random.Range(5, 10)];
                        bool find = false;
                        while (!find)
                        {
                            item = Game.Data.ItemList[Random.Range(5, 10)];
                            if (item.lvl == itemLvl) 
                            {
                                find = true; 
                            }
                            if (Game.singletone.Player.InventoryEquipment.Count.ContainsKey(item.id)) find = false; // проверка на то есть ли предмет у игрока если есть то генеририруем еще раз
                        }
                    }
                    return item;
                }
            default:
                {
                    item = Game.Data.ItemList[0];
                    return item;
                }
        }
    }

Ну и самое главное предмет можно поднять только один раз, после чего он появятся у игрока навсегда, а значит нельзя генерировать одинаковые предметы типа Weapon и Ability в одном сундуке написал вот так вот, по мимо того что это выглядит ужасно так предметы определенного уровня могут и закончится а миллион циклов в цикле это просто гг, учитывая что при каждой генерации происходит все то что я описал выше.

    public void GenerateItems()
    {
        Game.UIManager.UILoot.UpdateInventory("Clear", UiName: Info.title);
        var count = Random.Range(1, 4); // генерируем количесетво предметов в сундуке
        for (int slot = 0; slot < count; slot++) // slot  - слот который будем заполнять
        {
            Item item = Game.FactoryItem.Make(); // slot  - слот который будем заполнять
            if (item.Info.type == "Weapon" || item.Info.type == "Ability") // если предмет оружие или способность
            {
                bool find = false;
                if (slot == 0) find = true; //Если первый предмет в сундуке просто генерируем его
                while (!find) //Проверяем все предметы на совпадение если совпало то просто гененируем еще раз
                {
                    for (int i2 = 0; i2 < slot; i2++)
                    {
                        if (Inventory.Items[i2].Info.id == item.Info.id)
                        {
                            find = false; break;
                        }
                        else
                        {
                            find = true;
                        }
                    }
                    item = Game.FactoryItem.Make();
                }
            }
            item.gameObject.transform.SetParent(gameObject.transform);
            item.Slot = slot;
            Inventory.Add(item, slot);
            Game.UIManager.UILoot.UpdateInventory("Add", slot, item);
        }
    }

Если кто-то сталкивался с подобным или есть предложения по улучшению и исправлению проблем буду раз услышать. По итогу 3 проблемы, что делать с тем, что куча циклов в цикле, что делать с тем, что предметы определенного уровня закончатся, и есть ли способ лучше генерировать не одинаковые предметы типа Weapon и Ability в сундуке.


Ответы (0 шт):