Ejemplo n.º 1
0
        private void CalculateCompareStat(CalculatedStats compareItemStats, CalculatedStat oldStat, CalculatedStat newStat)
        {
            //for (int j = 0; j < oldStat.Values.Length; j++)
            //{
            //    if (oldStat.Values[j] != newStat.Values[j])
            //    {
            //        double[] values = new double[oldStat.Values.Length];

            //        for (int k = 0; k < oldStat.Values.Length; k++)
            //        {
            //            values[k] = newStat.Values[k] - oldStat.Values[k];
            //        }

            //        object[] obj = new object[values.Length];
            //        for (int l = 0; l < values.Length; l++)
            //            obj[i] = values[l];

            //        double diffValue
            //    }
            //}

            if (oldStat.Value != newStat.Value)
            {
                double diffValue = newStat.Value - oldStat.Value;

                string diff = String.Format(oldStat.Format, new object[] { diffValue });
                string color = diffValue < 0 ? "Red" : "Green";
                _compareStats.Add(new CompareStat() { Name = oldStat.Name, Before = oldStat.DisplayValue, After = newStat.DisplayValue, Difference = diff.ToString(), DifferenceColor = color });
            }
        }
Ejemplo n.º 2
0
        public static CalculatedStats CalculateStatsFromHero(Hero hero, Dictionary<string, Item> items)
        {
            CalculatedStats calcStats = new CalculatedStats();
            Dictionary<string, Set> charSets = new Dictionary<string, Set>();

            double totalArmor = 0;
            double armFromItems = 0;

            double allResFromItems = 0;
            Dictionary<string, double> resFromItems = new Dictionary<string, double>();
            resFromItems.Add("Fire", 0);
            resFromItems.Add("Lightning", 0);
            resFromItems.Add("Poison", 0);
            resFromItems.Add("Physical", 0);
            resFromItems.Add("Arcane", 0);
            resFromItems.Add("Cold", 0);
            double totalAllRes = 0;

            double baseDR = 0;
            double armDR = 0;
            double resDR = 0;

            double totalStr = 0;
            double strFromChar = 0;
            double strFromItems = 0;
            double baseStr = 8;
            double strPerLvl = 1;

            double totalDex = 0;
            double dexFromChar = 0;
            double dexFromItems = 0;
            double baseDex = 8;
            double dexPerLvl = 1;

            double totalInt = 0;
            double intFromChar = 0;
            double intFromItems = 0;
            double baseInt = 8;
            double intPerLvl = 1;

            double totalVit = 0;
            double vitFromChar = 0;
            double vitFromItems = 0;
            double baseVit = 9;
            double vitPerLvl = 2;

            double lifePctFromItems = 0;
            int healthVitMult = hero.Level < 35 ? 10 : hero.Level - 25;

            double critDamage = 0.5;
            double critChance = 0.05;
            double ias = 0;
            double aps = 1;

            double eleDmg = 0;
            double loh = 0;
            double minDmg = 0;
            double maxDmg = 0;

            double skillDmg = 0;

            double eliteBonus = 0;
            double demonBonus = 0;

            double ls = 0;
            double lifeRegen = 0;

            double blockChance = 0;
            double blockMin = 0;
            double blockMax = 0;

            // Class bonuses.
            switch (hero.Class)
            {
                case D3Client.Barbarian:
                    baseStr = 10;
                    strPerLvl = 3;
                    baseDR = .3;
                    break;
                case D3Client.Monk:
                    baseDex = 10;
                    dexPerLvl = 3;
                    baseDR = .3;
                    break;
                case D3Client.DemonHunter:
                    baseDex = 10;
                    dexPerLvl = 3;
                    break;
                default: // Wizard or Witch-Doctor
                    baseInt = 10;
                    intPerLvl = 3;
                    break;
            }

            // Initialize hands
            Item mainHand = null;
            if (items.ContainsKey("mainHand"))
                mainHand = items["mainHand"];

            Item offHand = null;
            if (items.ContainsKey("offHand"))
                offHand = items["offHand"];

            foreach (KeyValuePair<string, Item> item in items)
            {
                bool isWeapon = (item.Key == "offHand" && items[item.Key].AttacksPerSecond != null) || item.Key == "mainHand";
                // Get stats from item
                CalculateStatsFromRawAttributes(items[item.Key].AttributesRaw, isWeapon, ref allResFromItems, ref strFromItems,
                            ref dexFromItems, ref intFromItems, ref vitFromItems, ref lifePctFromItems, ref armFromItems,
                            ref critDamage, ref critChance, ref ias, ref aps, ref resFromItems,
                            ref eleDmg, ref loh, ref minDmg, ref maxDmg,
                            ref eliteBonus, ref demonBonus, ref ls, ref lifeRegen,
                            ref blockChance, ref blockMin, ref blockMax);

                // Get stats from gems
                if (items[item.Key].Gems != null)
                    foreach (SocketedGem gem in items[item.Key].Gems)
                    {
                        CalculateStatsFromRawAttributes(gem.AttributesRaw, false, ref allResFromItems, ref strFromItems,
                                ref dexFromItems, ref intFromItems, ref vitFromItems, ref lifePctFromItems, ref armFromItems,
                                ref critDamage, ref critChance, ref ias, ref aps, ref resFromItems,
                                ref eleDmg, ref loh, ref minDmg, ref maxDmg,
                                ref eliteBonus, ref demonBonus, ref ls, ref lifeRegen,
                                ref blockChance, ref blockMin, ref blockMax);
                    }

                // Monitor sets
                if (items[item.Key].Set != null)
                {
                    Set tempSet = new Set();
                    // If set is already monitored, increment the count.
                    if (charSets.ContainsKey(items[item.Key].Set.Slug))
                    {
                        tempSet = charSets[items[item.Key].Set.Slug];
                        tempSet.CharCount++;
                    }
                    else // Else create a new monitor
                    {
                        tempSet = items[item.Key].Set;
                        tempSet.CharCount = 1;
                    }

                    charSets[items[item.Key].Set.Slug] = tempSet;
                }
            }

            // Incorporate Sets
            foreach (KeyValuePair<string, Set> set in charSets)
            {
                foreach (Rank rank in set.Value.Ranks)
                {
                    if (set.Value.CharCount >= rank.Required)
                    {
                        Dictionary<string, MinMax> attributesRaw = D3Client.ParseAttributesRawFromAttributes(rank.Attributes);

                        // Get stats from Set Bonuses
                        CalculateStatsFromRawAttributes(attributesRaw, false, ref allResFromItems, ref strFromItems,
                            ref dexFromItems, ref intFromItems, ref vitFromItems, ref lifePctFromItems, ref armFromItems,
                            ref critDamage, ref critChance, ref ias, ref aps, ref resFromItems,
                            ref eleDmg, ref loh, ref minDmg, ref maxDmg,
                            ref eliteBonus, ref demonBonus, ref ls, ref lifeRegen,
                            ref blockChance, ref blockMin, ref blockMax);
                    }
                }
            }

            // Calculate Strength
            strFromChar = baseStr + (strPerLvl * (hero.Level - 1)) + (strPerLvl * hero.ParagonLevel);
            totalStr = strFromChar + strFromItems;

            // Calculate Dexterity
            dexFromChar = baseDex + (dexPerLvl * (hero.Level - 1)) + (dexPerLvl * hero.ParagonLevel);
            totalDex = dexFromChar + dexFromItems;

            // Calculate Intelligence
            intFromChar = baseInt + (intPerLvl * (hero.Level - 1)) + (intPerLvl * hero.ParagonLevel);
            totalInt = intFromChar + intFromItems;

            // Calculate Vitality
            vitFromChar = baseVit + (vitPerLvl * (hero.Level - 1)) + (vitPerLvl * hero.ParagonLevel);
            totalVit = vitFromChar + vitFromItems;

            // Calculate Armor
            totalArmor = armFromItems + totalStr;

            // Calculate All Res
            totalAllRes = allResFromItems + (totalInt / 10);

            // Class Mainstat.
            double mainStat;
            string mainStatName;
            GetMainStatFromClass(hero.Class, totalStr, totalDex, totalInt,
                out mainStat, out mainStatName);

            // Calculate Dodge Chance
            double dodgeChance = CalculateDodgeChance(totalDex);

            // Class passive skills
            foreach (SkillRune passive in hero.Skills.Passive)
            {
                switch (passive.Skill.Slug)
                {
                    case "ruthless":
                        critChance += 0.05;
                        critDamage += 0.5;
                        break;
                    case "bloodthirst":
                        ls += 0.03;
                        break;
                    case "nerves-of-steel":
                        totalArmor += totalVit;
                        break;
                    case "tough-as-nails":
                        totalArmor += totalArmor * 0.25;
                        break;
                    case "archery":
                    case "weapons-master":
                        switch (mainHand.Type.Id)
                        {
                            case "Mace":
                            case "Axe":
                            case "Mace2H":
                            case "Axe2H":
                            case "HandXBow":
                                critChance += 0.1;
                                break;
                            case "Crossbow":
                                critDamage += .5;
                                break;
                            case "Polearm":
                            case "Spear":
                                ias += .1;
                                break;
                            case "Bow":
                            case "Sword":
                            case "Sword2H":
                            case "Dagger":
                                skillDmg += 0.15;
                                break;
                        }
                        break;
                    case "perfectionist":
                        lifePctFromItems += 0.1;
                        totalArmor += totalArmor * 0.1;
                        totalAllRes += totalAllRes * 0.1;
                        break;
                    case "one-with-everything":
                        double highRes = 0;
                        foreach (KeyValuePair<string, double> res in resFromItems)
                            if (res.Value > highRes)
                                highRes = res.Value;
                        totalAllRes += highRes;
                        break;
                    case "seize-the-initiative":
                        totalArmor += totalDex * 0.5;
                        break;
                    case "sixth-sense":
                        dodgeChance += critChance * 0.3;
                        break;
                    case "pierce-the-veil":
                        skillDmg += 0.2;
                        break;
                    case "glass-cannon":
                        skillDmg += 0.15;
                        totalArmor -= totalArmor * 0.1;
                        totalAllRes -= totalAllRes * 0.1;
                        break;
                }
            }

            armDR = totalArmor / ((50 * 63) + totalArmor);
            resDR = totalAllRes / ((5 * 63) + totalAllRes);

            double multDR = ((1 - armDR) * (1 - resDR) * (1 - baseDR));

            double dr = 1 - multDR;
            double hp = (36 + (4 * hero.Level) + (healthVitMult * totalVit)) * (1 + lifePctFromItems);
            double ehp = hp / multDR;

            calcStats.EHP = ehp;

            calcStats.DPS = CalculateDPS(mainStat, critChance, critDamage,
                    mainHand, offHand, ias, minDmg, maxDmg, eleDmg, skillDmg);

            // Base stats
            calcStats.BaseStats.Add(new CalculatedStat("Strength", new double[] { totalStr }, "{0:N0}"));
            calcStats.BaseStats.Add(new CalculatedStat("Dexterity", new double[] { totalDex }, "{0:N0}"));
            calcStats.BaseStats.Add(new CalculatedStat("Intelligence", new double[] { totalInt }, "{0:N0}"));
            calcStats.BaseStats.Add(new CalculatedStat("Vitality", new double[] { totalVit }, "{0:N0}"));
            calcStats.BaseStats.Add(new CalculatedStat("Armor", new double[] { totalArmor }, "{0:N0}"));

            // Offense
            calcStats.DamageStats.Add(new CalculatedStat("Damage Increased by " + mainStatName, new double[] { mainStat / 100 }, "{0:P}"));
            calcStats.DamageStats.Add(new CalculatedStat("Damage Increased by Skills", new double[] { skillDmg }, "{0:P}"));
            aps = CalculateR(mainHand, offHand, ias);
            calcStats.DamageStats.Add(new CalculatedStat("Attacks per Second", new double[] { aps }, "{0:N}"));
            calcStats.DamageStats.Add(new CalculatedStat("+% Attack Speed", new double[] { ias }, "{0:P}"));
            calcStats.DamageStats.Add(new CalculatedStat("Critical Hit Chance", new double[] { critChance }, "{0:P}"));
            calcStats.DamageStats.Add(new CalculatedStat("Critical Hit Damage", new double[] { critDamage }, "{0:P}"));

            // Defense
            calcStats.DefenseStats.Add(new CalculatedStat("Block Amount", new double[] { blockMin, blockMax }, "{0:N0} - {1:N0}"));
            calcStats.DefenseStats.Add(new CalculatedStat("Block Chance", new double[] { blockChance }, "{0:P}"));
            calcStats.DefenseStats.Add(new CalculatedStat("Dodge Chance", new double[] { dodgeChance }, "{0:P}"));
            calcStats.DefenseStats.Add(new CalculatedStat("Armor Damage Reduction", new double[] { armDR }, "{0:P}"));
            calcStats.DefenseStats.Add(new CalculatedStat("Resist Damage Reduction", new double[] { resDR }, "{0:P}"));
            calcStats.DefenseStats.Add(new CalculatedStat("Damage Reduction", new double[] { dr }, "{0:P}"));
            calcStats.DefenseStats.Add(new CalculatedStat("All Resist", new double[] { totalAllRes }, "{0:N0}"));

            // Life
            calcStats.LifeStats.Add(new CalculatedStat("Maximum Life", new double[] { hp }, "{0:N0}"));
            calcStats.LifeStats.Add(new CalculatedStat("Total Life Bonus", new double[] { lifePctFromItems }, "{0:P0}"));
            calcStats.LifeStats.Add(new CalculatedStat("Life per Second", new double[] { lifeRegen }, "{0:N}"));
            calcStats.LifeStats.Add(new CalculatedStat("Life Steal", new double[] { ls }, "{0:P}"));
            //calcStats.LifeStats.Add(new CalculatedStat("Life per Kill", lifePctFromItems, "{0:N}"));
            calcStats.LifeStats.Add(new CalculatedStat("Life per Hit", new double[] { loh }, "{0:N}"));
            //calcStats.LifeStats.Add(new CalculatedStat("Health Globe Healing Bonus", lifePctFromItems, "{0:N}"));
            //calcStats.LifeStats.Add(new CalculatedStat("Bonus to Gold/Globe radius", lifePctFromItems, "{0:N}"));

            return calcStats;
        }