private async Task<bool> LoadHeroItems(Hero hero) { string size = "large"; Dictionary<string, Item> temp = new Dictionary<string, Item>(); foreach (KeyValuePair<string, Item> item in hero.Items) { temp[item.Key] = await _d3Client.GetItemAsync(item.Value.TooltipParams); temp[item.Key].DisplayIcon = _d3Client.GetItemIcon(size, item.Value.Icon); temp[item.Key].BackgroundImage = GetItemBackgroundImage(item.Value.DisplayColor); } hero.Items = temp; // Clone original hero items to compare items to start off. hero.CompareItems = (from x in temp select x).ToDictionary(x => x.Key, x => x.Value.DeepCopyForCompare()); hero.CalculatedStats = Domain.CalculateStats.CalculateStatsFromHero(hero, hero.Items); return true; }
private void LoadHeroSkills(Hero hero) { for (int i = 0; i < hero.Skills.Active.Count; i++) { int x = 22 * (i % 2); int y = 0; if (i == 2 || i == 3) y = 22; if (i == 4 || i == 5) y = 44; if (hero.Skills.Active[i].Skill == null) { hero.Skills.Active[i].Skill = new Skill(); //hero.Skills.Active[i].Skill.DisplayIcon = new Windows.UI.Xaml.Media.Imaging.BitmapImage(new Uri(this.BaseUri, "Assets/skill-overlays.png")); //hero.Skills.Active[i].Skill.DisplayIconViewRect = String.Format("{0},{1},42,42", new object[] { x, y }); //hero.Skills.Active[i].Skill.DisplayIconMargin = String.Format("{0},{1},0,0", new object[] { x * -1, y * -1 }); } hero.Skills.Active[i].Skill.OverlayViewRect = String.Format("{0},{1},22,22", new object[] { x, y }); hero.Skills.Active[i].Skill.OverlayMargin = String.Format("{0},{1},0,0", new object[] { x * -1, y * -1 }); hero.Skills.Active[i].Skill.DisplayIcon = _d3Client.GetSkillIcon("42", hero.Skills.Active[i].Skill.Icon); } for (int i = 0; i < hero.Skills.Passive.Count; i++) { if (hero.Skills.Passive[i].Skill == null) { hero.Skills.Passive[i].Skill = new Skill(); } hero.Skills.Passive[i].Skill.DisplayIcon = _d3Client.GetSkillIcon("42", hero.Skills.Passive[i].Skill.Icon); } }
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; }