예제 #1
0
    /// <summary>
    /// Generates the loot within all specified parameters, depending on level & difficulty.
    /// </summary>
    /// <returns>The loot.</returns>
    /// <param name="map">Map to get the levelNumber and difficulty from. If unspecified uses set values. </param>
    public GameItem[] GenerateLoot(Map map = null)
    {
        if (map != null)
        {
            SetLevelAndDifficulty(map);
        }
        //Set loot parameters depending on level & difficulty
        int maxDifficulty = Enum.GetValues(typeof(Settings.Difficulty)).Length - 1;

        int minItems_base         = Mathf.RoundToInt(minItemsBase_hardest + minItemsBase_modifier * (maxDifficulty - difficulty));
        int maxItems_base         = Mathf.RoundToInt(maxItemsBase_hardest + maxItemsBase_modifier * (maxDifficulty - difficulty));
        int levelsTillMinItemGain = Mathf.RoundToInt(levelsTillMinItemGain_easiest * Mathf.Pow(levelsTillMinItemGain_multiplier, difficulty));
        int levelsTillMaxItemGain = Mathf.RoundToInt(levelsTillMaxItemGain_easiest * Mathf.Pow(levelsTillMaxItemGain_multiplier, difficulty));
        int minItems_gain         = (int)levelNumber / levelsTillMinItemGain;
        int maxItems_gain         = (int)levelNumber / levelsTillMaxItemGain;
        int minItems = Mathf.Min(minItems_base + minItems_gain, minLootCap);
        int maxItems = Mathf.Min(maxItems_base + maxItems_gain, maxLootCap);

        if (minItems > maxItems)
        {
            minItems = maxItems;
        }

        //Rarity
        int minRarityBase           = Mathf.RoundToInt((int)minRarityBase_hardest + minRarityBase_modifier * (maxDifficulty - difficulty));
        int levelsTillMinRarityGain = Mathf.RoundToInt(levelsTillMinRarityGain_easiest * Mathf.Pow(levelsTillMinRarityGain_multiplier, difficulty));
        int minRarity_gain          = (int)levelNumber / levelsTillMinRarityGain;

        GameItem.ItemRarity minRarity = (GameItem.ItemRarity)Mathf.Min(minRarityBase + minRarity_gain, (int)minRarityCap);

        //Generate loot in secret room
        return(ItemSpawner.GenerateLootBag((int)Time.time, levelNumber, minItems, maxItems, minRarity, false, healthPotionChance));
    }
예제 #2
0
    /// <summary>
    /// Generates a health potion.
    /// </summary>
    /// <returns>The health potion.</returns>
    /// <param name="seed">Seed.</param>
    /// <param name="quality">Quality.</param>
    /// <param name="rarity">Rarity.</param>
    /// <param name="useSeed">If set to <c>true</c> use seed.</param>
    public static UsableItem GenerateHealthPotion(int seed, int quality, GameItem.ItemRarity rarity, bool useSeed = false)
    {
        //TODO: incorporate quality more by allowing custom healing amounts
        //Allow 1 more potential potion every 5 levels, up to the max stack of course.
        Random     random         = GetRandom(seed, useSeed);
        int        potionMaxStack = 5;
        int        maxAmount      = UnityEngine.Mathf.Min((int)(quality / 5) + 1, potionMaxStack);
        int        quantity       = random.Next(1, maxAmount + 1);
        UsableItem healthPotion   = new UsableItem(null, null, "Health Potion", "A health potion.", 1, rarity, quantity, potionMaxStack, 100, "HealthPotionAction");

        SetItemSprites(seed, "Health Potion", healthPotion, useSeed);
        return(healthPotion);
    }
예제 #3
0
    /// <summary>
    /// Generation function designed to build a weapon item of some sort. Can be a melee or ranged weapon.
    /// </summary>
    /// <param name="seed">Seed to use for generation, useful for testing. Set this to system time during playtime.</param>
    /// <param name="quality">Quality modifier for items. Essentially represents how deep in the dungeon the player is. Pass this from the map class ideally.</param>
    /// <param name="rarity">Minimum item rarity, defaults to common. Higher rarity items have better stats implicitly.</param>
    /// <returns>A weapon item, with name and description pre-set based on the item spec.</returns>
    public static WeaponItem GenerateWeapon(int seed, int quality, GameItem.ItemRarity rarity = GameItem.ItemRarity.COMMON, bool useSeed = true)
    {
        // Some constants to use for calculations:
        int meleeWeight  = 1;   // Weighted likelyhood to pick this over the other.
        int rangedWeight = 0;   // Weighted likelyhood to pick this over the other.

        // Note we are using the system's random, and not Unity's in order to use a seed.
        Random random = GetRandom(seed, useSeed);

        // Choose what type of thing to generate, Ranged? Melee?
        int val = random.Next(1, meleeWeight + rangedWeight);

        // Generate basic stats, these apply to all weapons
        int rareVal = (int)rarity;

        double[] damageScale = { 1, 10, 25, 60, 135, 250 }; // Damage range dependent on rarity, For rarity i, minimum is damageScale[i]
        double[] rofMin      = { 1, 2, 3, 4, 5 };           // TODO: PLEASE BALANCE THIS
        double[] rofMax      = { 2, 4, 6, 8, 10 };
        double   rangeMin    = 1;
        double   rangeMax    = 5; // Ranged weapon range is x10 this.

        // Get Damage Value; utilizes quality and rarity to help it scale.
        double damage = random.NextDouble() * (damageScale[rareVal + 1] - damageScale[rareVal]) + damageScale[rareVal];

        damage = damage + damage * (quality / floorRarityBoostThreshold);

        // Get Range Value; depdenent on nothing.
        double range = random.NextDouble() * (rangeMax - rangeMin) + rangeMin;

        // Get Rate Of Fire; higher rarities increase this value.
        double rof = random.NextDouble() * (rofMax[rareVal] - rofMin[rareVal]) + rofMin[rareVal];

        // Call other generation functions based on this.
        if (val >= rangedWeight)
        {
            return(GenerateMeleeWeapon(seed, quality, damage, range, rof, (int)rarity, useSeed));
        }
        else
        {
            return(GenerateRangedWeapon(seed, quality, damage, range * 10, rof, (int)rarity, useSeed));
        }
    }
예제 #4
0
    /// <summary>
    /// Generation function designed to build an either a weapon or armor.
    /// </summary>
    /// <param name="seed">Seed to use for generation, useful for testing. Set this to system time during playtime.</param>
    /// <param name="quality">Quality modifier for items. Essentially represents how deep in the dungeon the player is. Pass this from the map class ideally.</param>
    /// <param name="rarity">Minimum item rarity, defaults to common. Higher rarity items have better stats implicitly.</param>
    /// <returns>An item, with name and description pre-set based on the item spec.</returns>
    public static GameItem GenerateItem(int seed, int quality, GameItem.ItemRarity rarity = GameItem.ItemRarity.COMMON, bool useSeed = true)
    {
        // Some constants to use for calculations:
        int armorWeight  = 2;   // Weighted likelyhood to pick this over the other.
        int weaponWeight = 1;   // Weighted likelyhood to pick this over the other.

        // Note we are using the system's random, and not Unity's in order to use a seed.
        Random random = GetRandom(seed, useSeed);

        // Choose what type of thing to generate, armor, or a weapon?
        int val = random.Next(1, armorWeight + weaponWeight + 1);

        // Call other generation functions based on this.
        if (val >= weaponWeight)
        {
            return(GenerateWeapon(seed, quality, rarity, useSeed));
        }
        else
        {
            return(GenerateArmor(seed, quality, rarity, useSeed));
        }
    }
예제 #5
0
    /// <summary>
    /// Generation function designed to build an armor item for spawning. Can fit any slot.
    /// </summary>
    /// <param name="seed">Seed to use for generation, useful for testing. Set this to system time during playtime.</param>
    /// <param name="rarity">Minimum item rarity, defaults to common. Higher rarity items have better stats implicitly.</param>
    /// <returns>A weapon item, with name and description pre-set based on the item spec.</returns>
    public static ArmorItem GenerateArmor(int seed, int quality, GameItem.ItemRarity rarity = GameItem.ItemRarity.COMMON, bool useSeed = true)
    {
        // Some constants to use for calculations:
        double[] minArmorRarityRatings = { 1, 2, 3, 4, 5 };           // Scaling factor for minimum based on rarity. Min * RarityRating = Absolute Minimum
        double[] minArmorRatings       = { 5, 10, 15, 5, 1, 1 };      // Minimum rating per armor slot, in enum order.
        double[] maxArmorRatings       = { 20, 50, 100, 10, 5, 5 };   // Maximum rating per armor slot, in enum order.

        double[] minSpeedRarityRatings = { 1, 1.25, 1.5, 1.75, 2 };   // Scaling factor for minimum based on rarity.
        double[] minSpeedRatings       = { 0, 1, 0, 0, 1, 1 };        // Minimum rating per armor slot, in enum order.
        double[] maxSpeedRatings       = { 2, 5, 2, 1, 5, 5 };        // Maximum rating per armor slot, in enum order.

        double[] minDamageRarityRatings = { 1, 1.25, 1.5, 1.75, 2 };  // Scaling factor for minimum based on rarity.
        double[] minDamageRatings       = { 0, 0, 0, 1, 1, 1 };       // Minimum rating per armor slot, in enum order.
        double[] maxDamageRatings       = { 2, 2, 2, 5, 5, 5 };       // Maximum rating per armor slot, in enum order.

        // For reference, ENUM Order: HEAD, LEGS, CHEST, GLOVES, RING, NECK.

        // Note we are using the system's random, and not Unity's in order to use a seed.
        Random random = GetRandom(seed, useSeed);

        // Select rarity first; this determines effectiveness.
        int totalWeight = 0;

        for (int i = 0; i < rarityWeights.Length; i++)
        {
            totalWeight += rarityWeights[i];
        }

        int randRarity = random.Next(totalWeight);
        int trueRarity = -1;

        totalWeight = rarityWeights[0];
        for (int i = 1; i < rarityWeights.Length && trueRarity == -1; i++)
        {
            if (randRarity < totalWeight)
            {
                trueRarity = i - 1;
            }

            totalWeight += rarityWeights[i];
        }

        // Rarity is guaurnteed to increase for every X floors of depth.
        trueRarity += (quality / floorRarityBoostThreshold);
        if (trueRarity > 4)
        {
            trueRarity = 4;
        }

        // Determine slot for armor.
        int trueSlot = random.Next(Enum.GetNames(typeof(EquipmentManager.EquipSlot)).Length);

        // Determine sprite info (somehow). TODO (I'm not sure how to do this)

        // Calculate the armor's values.
        double weightedMinArmor = minArmorRatings[trueSlot] * minArmorRarityRatings[trueRarity];

        if (weightedMinArmor > maxArmorRatings[trueSlot])
        {
            weightedMinArmor = maxArmorRatings[trueSlot];
        }

        double weightedMinSpeed = minSpeedRatings[trueSlot] * minSpeedRarityRatings[trueRarity];

        if (weightedMinArmor > maxSpeedRatings[trueSlot])
        {
            weightedMinArmor = maxSpeedRatings[trueSlot];
        }

        double weightedMinDamage = minDamageRatings[trueSlot] * minDamageRarityRatings[trueRarity];

        if (weightedMinArmor > maxDamageRatings[trueSlot])
        {
            weightedMinArmor = maxDamageRatings[trueSlot];
        }

        double armor  = random.NextDouble() * (maxArmorRatings[trueSlot] - weightedMinArmor) + weightedMinArmor;
        double speed  = random.NextDouble() * (maxSpeedRatings[trueSlot] - weightedMinSpeed) + weightedMinSpeed;
        double damage = random.NextDouble() * (maxDamageRatings[trueSlot] - weightedMinDamage) + weightedMinDamage;


        // Determine, based on rarity, if armor is allowed to have speed or damage.
        if (trueRarity < 1)
        {
            speed  = 0;
            damage = 0;
        }
        else if (trueRarity < 2)
        {
            if (speed > damage)
            {
                damage = 0;
            }
            else
            {
                speed = 0;
            }
        }

        // Build the armor item.
        ArmorItem newItem = new ArmorItem((EquipmentManager.EquipSlot)trueSlot, armor, speed, damage)
        {
            Rarity = (GameItem.ItemRarity)trueRarity
        };

        // Generate a name.
        newItem.Name = GenerateArmorName(seed, newItem, minArmorRatings, maxArmorRatings, minSpeedRatings, maxSpeedRatings, minDamageRatings, maxDamageRatings, useSeed);

        // Generate a description.
        newItem.Description = GenerateArmorDesc(seed, newItem, useSeed);

        // Pick a value rating. (Should probably be another utility method).
        newItem.Value = GenerateItemValue(newItem);

        // Generate a unique ID (this might require some internal memory somewhere to keep track of what IDs have already been assigned, probably another utility function).
        newItem.ItemID = GenerateItemID();

        // Return the finished item.
        return(newItem);
    }
예제 #6
0
    /// <summary>
    /// Generation function designed to build an array of game items, can be potions, equipment, or just misc stuff.
    /// Function is primarily used for spawning more than one thing in a treasure room.
    /// </summary>
    /// <param name="seed">Seed to use for generation, useful for testing. Set this to system time during playtime.</param>
    /// <param name="quality">Quality modifier for items. Essentially represents how deep in the dungeon the player is. Pass this from the map class ideally.</param>
    /// <param name="min">Minimum amount of items that are allowed to spawn, inclusive.</param>
    /// <param name="max">Maximum amount of items that are allowed to spawn, inclusive.</param>
    /// <param name="rarity">Minimum item rarity, defaults to common. Higher rarity items have better stats implicitly.</param>
    /// <param name="healthPotionChance"> % chance from [0, 1] inclusive that any item dropped will be a health potion.</param></param>
    /// <returns>An equippable item, with name and description pre-set based on the item spec.</returns>
    public static GameItem[] GenerateLootBag(int seed, int quality, int min = 1, int max = 5, GameItem.ItemRarity rarity = GameItem.ItemRarity.COMMON, bool useSeed = true, double healthPotionChance = 0.0)
    {
        // Random generation seed is set before doing anyhting else, neat.
        Random random = GetRandom(seed, useSeed);

        // Size up the situation.
        int size = random.Next(min, max + 1);

        GameItem[] lootBag = new GameItem[size];

        // Generate and fill the bag.
        for (int i = 0; i < size; i++)
        {
            if (random.NextDouble() <= healthPotionChance)
            {
                lootBag[i] = GenerateHealthPotion(seed, quality, rarity, useSeed);
            }
            else
            {
                lootBag[i] = GenerateItem(seed, quality, rarity, useSeed);
            }
        }

        return(lootBag);
    }
예제 #7
0
    public void ItemValue(GameItem.ItemRarity rarity, double value)
    {
        GameItem valueTestItem = new GameItem(null, null, "Generic Item", "I am an Item.", 10, rarity, 5, 10, 2);

        Assert.AreEqual(value, ItemSpawner.GenerateItemValue(valueTestItem));
    }
예제 #8
0
    public void TestArmorNameByRarity(EquipmentManager.EquipSlot slot, int armorRatingPosition, GameItem.ItemRarity rarity, string description)
    {
        ArmorItem armor = new ArmorItem(rarity, slot);

        double[] minArmor = new double[6];
        double[] maxArmor = new double[6];
        minArmor[armorRatingPosition] = 1;
        maxArmor[armorRatingPosition] = 5;

        double[] minSpeed = new double[6];
        double[] maxSpeed = new double[6];
        minSpeed[armorRatingPosition] = 1;
        maxSpeed[armorRatingPosition] = 5;

        double[] minDamage = new double[6];
        double[] maxDamage = new double[6];
        minDamage[armorRatingPosition] = 1;
        maxDamage[armorRatingPosition] = 5;

        string name = ItemSpawner.GenerateArmorName(5, armor, minArmor, maxArmor, minSpeed, maxSpeed, minDamage, maxDamage);

        string[] ssize = name.Split(null);
        Assert.AreEqual(ssize[0], description);
    }