public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, bool referenceCalculation, bool significantChange, bool needsDisplayCalculations) { CalculationOptionsElemental calcOpts = character.CalculationOptions as CalculationOptionsElemental; if (calcOpts == null) { calcOpts = new CalculationOptionsElemental(); } BossOptions bossOpts = character.BossOptions; if (bossOpts == null) { bossOpts = new BossOptions(); } Stats stats = GetCharacterStats(character, additionalItem); CharacterCalculationsElemental calculatedStats = new CharacterCalculationsElemental(); calculatedStats.BasicStats = stats; calculatedStats.LocalCharacter = character; calcOpts.calculatedStats = calculatedStats; Rawr.Elemental.Estimation.solve(calculatedStats, calcOpts, bossOpts); return(calculatedStats); }
public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, bool referenceCalculation, bool significantChange, bool needsDisplayCalculations) { // First things first, we need to ensure that we aren't using bad data CharacterCalculationsElemental calc = new CharacterCalculationsElemental(); if (character == null) { return(calc); } CalculationOptionsElemental calcOpts = character.CalculationOptions as CalculationOptionsElemental; if (calcOpts == null) { return(calc); } // BossOptions bossOpts = character.BossOptions; Stats stats = GetCharacterStats(character, additionalItem); calc.BasicStats = stats; calc.LocalCharacter = character; Rawr.Elemental.Estimation.solve(calc, calcOpts, bossOpts); return(calc); }
public override ICalculationOptionBase DeserializeDataObject(string xml) { System.Xml.Serialization.XmlSerializer serializer = new System.Xml.Serialization.XmlSerializer(typeof(CalculationOptionsElemental)); System.IO.StringReader reader = new System.IO.StringReader(xml); CalculationOptionsElemental calcOpts = serializer.Deserialize(reader) as CalculationOptionsElemental; return(calcOpts); }
public void LoadCalculationOptions() { _loadingCalculationOptions = true; if (Character.CalculationOptions == null) Character.CalculationOptions = new CalculationOptionsElemental(); calcOpts = Character.CalculationOptions as CalculationOptionsElemental; // Model Specific Code // _loadingCalculationOptions = false; }
private void checkBox1_CheckedChanged(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; calcOpts.UseThunderstorm = cbThunderstorm.Checked; Character.OnCalculationsInvalidated(); }
private void cbFireEle_CheckedChanged(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; calcOpts.UseFireEle = cbFireEle.Checked; Character.OnCalculationsInvalidated(); }
public void LoadCalculationOptions() { _loadingCalculationOptions = true; if (Character.CalculationOptions == null) { Character.CalculationOptions = new CalculationOptionsElemental(); } calcOpts = Character.CalculationOptions as CalculationOptionsElemental; // Model Specific Code // _loadingCalculationOptions = false; }
private void trkTargets_Scroll(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; calcOpts.NumberOfTargets = trkTargets.Value; lbTargets.Text = "Number of Targets: " + trkTargets.Value; Character.OnCalculationsInvalidated(); }
/// <summary> /// Beware when updating: The spells from an earlier returned Rotation are references to the SpellBox from this Estimation. /// </summary> /// <param name="baseStats"></param> /// <param name="procStats"></param> /// <param name="talents"></param> /// <param name="calcOpts"></param> public void Update(Stats baseStats, Stats procStats, ShamanTalents talents, CalculationOptionsElemental calcOpts) { this.baseStats = baseStats; this.procStats = procStats; this.talents = talents; this.calcOpts = calcOpts; Stats addedStats = baseStats.Clone(); addedStats.Accumulate(procStats); CombatFactors combatFactors = new CombatFactors(talents, addedStats, Math.Max(calcOpts.NumberOfTargets - 1, 0), calcOpts.LatencyCast, calcOpts.LatencyGcd, calcOpts.UseFireNova, calcOpts.UseChainLightning, calcOpts.UseDpsTotem); spellbox.Update(combatFactors); }
/// <summary> /// Beware when updating: The spells from an earlier returned Rotation are references to the SpellBox from this Estimation. /// </summary> /// <param name="baseStats"></param> /// <param name="procStats"></param> /// <param name="talents"></param> /// <param name="calcOpts"></param> public void Update(Stats baseStats, Stats procStats, ShamanTalents talents, CalculationOptionsElemental calcOpts) { this.baseStats = baseStats; this.procStats = procStats; this.talents = talents; this.calcOpts = calcOpts; Stats addedStats = baseStats.Clone(); addedStats.Accumulate(procStats); CombatFactors combatFactors = new CombatFactors(talents, addedStats, Math.Max(calcOpts.NumberOfTargets - 1, 0), calcOpts.LatencyCast, calcOpts.LatencyGcd, calcOpts.UseFireNova, calcOpts.UseChainLightning, calcOpts.UseDpsTotem); spellbox.Update(combatFactors); }
private void trkFightLength_Scroll(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; calcOpts.FightDuration = trkFightLength.Value * 15; int m = trkFightLength.Value / 4; int s = calcOpts.FightDuration - 60 * m; lblFightLength.Text = "Fight duration: " + m + ":" + s; Character.OnCalculationsInvalidated(); }
private void tbBSRatio_Scroll(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; calcOpts.BSRatio = tbBSRatio.Value; int burst = 100 - tbBSRatio.Value; int sust = tbBSRatio.Value; lblBSRatio.Text = "Ratio: " + burst + "% Burst, " + sust + "% Sustained."; Character.OnCalculationsInvalidated(); }
private void textBoxGCDLatency_TextChanged(object sender, EventArgs e) { if (loading) { return; } CalculationOptionsElemental calcOpts = Character.CalculationOptions as CalculationOptionsElemental; float lag; if (!float.TryParse(textBoxGCDLatency.Text, System.Globalization.NumberStyles.Float, System.Globalization.CultureInfo.InvariantCulture, out lag)) { textBoxGCDLatency.Text = calcOpts.LatencyGcd.ToString(System.Globalization.CultureInfo.InvariantCulture); return; } calcOpts.LatencyGcd = lag; Character.OnCalculationsInvalidated(); }
protected override void LoadCalculationOptions() { loading = true; CalculationOptionsElemental calcOpts; if (Character.CalculationOptions == null) { calcOpts = new CalculationOptionsElemental(); Character.CalculationOptions = calcOpts; } else { calcOpts = (CalculationOptionsElemental)Character.CalculationOptions; } tbBSRatio.Value = calcOpts.BSRatio; int burst = 100 - tbBSRatio.Value; int sust = tbBSRatio.Value; lblBSRatio.Text = "Ratio: " + burst + "% Burst, " + sust + "% Sustained."; trkFightLength.Value = calcOpts.FightDuration / 15; int m = trkFightLength.Value / 4; int s = calcOpts.FightDuration - 60 * m; lblFightLength.Text = "Fight duration: " + m + ":" + s; trkTargets.Value = calcOpts.NumberOfTargets; lbTargets.Text = "Number of targets: " + calcOpts.NumberOfTargets; textBoxCastLatency.Text = calcOpts.LatencyCast.ToString(System.Globalization.CultureInfo.InvariantCulture); textBoxGCDLatency.Text = calcOpts.LatencyGcd.ToString(System.Globalization.CultureInfo.InvariantCulture); cbThunderstorm.Checked = calcOpts.UseThunderstorm; cbFireNova.Checked = calcOpts.UseFireNova; cbChainLightning.Checked = calcOpts.UseChainLightning; cbFireDpsTotem.Checked = calcOpts.UseDpsTotem; cbFireEle.Checked = calcOpts.UseFireEle; loading = false; }
public Stats GetBuffsStats(Character character, CalculationOptionsElemental calcOpts) { List <Buff> removedBuffs = new List <Buff>(); List <Buff> addedBuffs = new List <Buff>(); //float hasRelevantBuff; #region Passive Ability Auto-Fixing // Removes the Trueshot Aura Buff and it's equivalents Unleashed Rage and Abomination's Might if you are // maintaining it yourself. We are now calculating this internally for better accuracy and to provide // value to relevant talents /*{ * hasRelevantBuff = character.HunterTalents.TrueshotAura; * Buff a = Buff.GetBuffByName("Trueshot Aura"); * Buff b = Buff.GetBuffByName("Unleashed Rage"); * Buff c = Buff.GetBuffByName("Abomination's Might"); * if (hasRelevantBuff > 0) * { * if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); removedBuffs.Add(a); } * if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); removedBuffs.Add(b); } * if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); removedBuffs.Add(c); } * } * }*/ #endregion Stats statsBuffs = GetBuffsStats(character.ActiveBuffs, character.SetBonusCount); foreach (Buff b in removedBuffs) { character.ActiveBuffsAdd(b); } foreach (Buff b in addedBuffs) { character.ActiveBuffs.Remove(b); } return(statsBuffs); }
public static void solve(CharacterCalculationsElemental calculatedStats, CalculationOptionsElemental calcOpts, BossOptions bossOpts) { Stats stats = calculatedStats.BasicStats; Character character = calculatedStats.LocalCharacter; ShamanTalents talents = character.ShamanTalents; /* Effects: * Clearcasting (-40% mana cost next 2 spells) * Glyph of flame shock or not * Clearcasting (5/10% more total damage) * Elemental Mastery (+15% haste chance, 15 sec/3 min cd) * Trinkets * * Assume LvB used on CD and FS either after LvB, on dot drop or before LvB * Filler: LB * NYI Optional: use of CL */ Estimation e; Rotation rot; float damage; Stats procStats; #if RAWR3 || SILVERLIGHT float FightDuration = bossOpts.BerserkTimer; #else float FightDuration = calcOpts.FightDuration; #endif // WITHOUT PROCS e = new Estimation(stats, new Stats { }, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); // WITH PROCS int nPasses = 2, k; for (k = 0; k < nPasses; k++) { procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); e.Update(stats, procStats, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); } // Thunderstorm usage float thunderstormRegen = 0f; #region Thunderstorm if (calcOpts.UseThunderstorm) { float procsPerSecond = Thunderstorm.getProcsPerSecond(talents.GlyphofThunder, (int)FightDuration); thunderstormRegen += (talents.GlyphofThunderstorm ? .1f : .08f) * stats.Mana * procsPerSecond * 5; } #endregion /* Regen variables: (divide by 5 for regen per second) * While casting: ManaRegInFSR * During regen: ManaRegOutFSR */ #region Calculate Regen float spiRegen = 5 * StatConversion.GetSpiritRegenSec(stats.Spirit, stats.Intellect); float replenishRegen = 5 * stats.Mana * stats.ManaRestoreFromMaxManaPerSecond; float judgementRegen = 5 * rot.GetBaseCastTime() / rot.Duration * stats.ManaRestoreFromBaseManaPPM / 60f * BaseStats.GetBaseStats(character).Mana; float ManaRegInFSR = spiRegen * stats.SpellCombatManaRegeneration + stats.Mp5 + replenishRegen + judgementRegen + thunderstormRegen; float ManaRegOutFSR = spiRegen + stats.Mp5 + replenishRegen + thunderstormRegen; float ManaRegen = ManaRegInFSR; #endregion // TotalDamage, CastFraction, TimeUntilOOM #region Calculate total damage in the fight float TimeUntilOOM = 0; float effectiveMPS = rot.MPS - ManaRegen / 5f; if (effectiveMPS <= 0) { TimeUntilOOM = FightDuration; } else { TimeUntilOOM = (calculatedStats.BasicStats.Mana) / effectiveMPS; } if (TimeUntilOOM > FightDuration) { TimeUntilOOM = FightDuration; } #region SpecialEffects from procs etc. procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); //damage procs (Thunder Capacitor etc.) are effected by spellcrit and damage debuffs damage = procStats.ArcaneDamage * (1 + stats.BonusArcaneDamageMultiplier) + procStats.NatureDamage * (1 + stats.BonusNatureDamageMultiplier) + procStats.FireDamage * (1 + stats.BonusFireDamageMultiplier) + procStats.ShadowDamage * (1 + stats.BonusShadowDamageMultiplier); if (damage > 0) { damage *= (1 + stats.SpellCrit * .5f); // but only with the normal 50% dmg bonus rot.DPS += damage; } #endregion float TotalDamage = TimeUntilOOM * rot.DPS; float TimeToRegenFull = 5f * calculatedStats.BasicStats.Mana / ManaRegOutFSR; float TimeToBurnAll = calculatedStats.BasicStats.Mana / effectiveMPS; float CastFraction = 1f; if (ManaRegOutFSR > 0 && FightDuration > TimeUntilOOM) { float timeLeft = FightDuration - TimeUntilOOM; if (TimeToRegenFull + TimeToBurnAll == 0) { CastFraction = 0; } else { CastFraction = TimeToBurnAll / (TimeToRegenFull + TimeToBurnAll); } TotalDamage += timeLeft * rot.DPS * CastFraction; } #endregion float bsRatio = ((float)calcOpts.BSRatio) * 0.01f; calculatedStats.BurstPoints = (1f - bsRatio) * 2f * rot.DPS; calculatedStats.SustainedPoints = bsRatio * 2f * TotalDamage / FightDuration; calculatedStats.OverallPoints = calculatedStats.BurstPoints + calculatedStats.SustainedPoints; calculatedStats.CombatStats = stats.Clone(); calculatedStats.CombatStats.Accumulate(procStats); calculatedStats.ManaRegenInFSR = ManaRegInFSR; calculatedStats.ManaRegenOutFSR = ManaRegOutFSR; calculatedStats.ReplenishMP5 = replenishRegen; calculatedStats.LightningBolt = rot.LB; calculatedStats.ChainLightning = rot.CL; calculatedStats.FlameShock = rot.FS; calculatedStats.LavaBurst = rot.LvB; calculatedStats.EarthShock = rot.ES; calculatedStats.FrostShock = rot.FrS; calculatedStats.FireNova = rot.FN; calculatedStats.SearingTotem = rot.ST; calculatedStats.MagmaTotem = rot.MT; calculatedStats.TimeToOOM = TimeUntilOOM; calculatedStats.CastRegenFraction = CastFraction; calculatedStats.CastsPerSecond = rot.getCastsPerSecond(); calculatedStats.CritsPerSecond = rot.getWeightedCritchance() * rot.getCastsPerSecond(); calculatedStats.MissesPerSecond = rot.getCastsPerSecond() * (1f - rot.getWeightedHitchance()); calculatedStats.LvBPerSecond = rot.getCastsPerSecond(typeof(LavaBurst)); calculatedStats.LBPerSecond = rot.getCastsPerSecond(typeof(LightningBolt)); calculatedStats.FSPerSecond = rot.getCastsPerSecond(typeof(FlameShock)); calculatedStats.LatencyPerSecond = rot.LatencyPerSecond; calculatedStats.RotationDPS = rot.DPS; calculatedStats.RotationMPS = rot.MPS; calculatedStats.TotalDPS = TotalDamage / FightDuration; rot.ClearCasting.TryGetValue(typeof(FlameShock), out calculatedStats.ClearCast_FlameShock); rot.ClearCasting.TryGetValue(typeof(LavaBurst), out calculatedStats.ClearCast_LavaBurst); rot.ClearCasting.TryGetValue(typeof(LightningBolt), out calculatedStats.ClearCast_LightningBolt); calculatedStats.Rotation = rot.ToString(); calculatedStats.RotationDetails = rot.ToDetailedString(); }
public static void solve(CharacterCalculationsElemental calculatedStats, CalculationOptionsElemental calcOpts, BossOptions bossOpts) { Stats stats = calculatedStats.BasicStats; Character character = calculatedStats.LocalCharacter; ShamanTalents talents = character.ShamanTalents; /* Effects: * Clearcasting (-40% mana cost next 2 spells) * Glyph of flame shock or not * Clearcasting (5/10% more total damage) * Elemental Mastery (+15% haste chance, 15 sec/3 min cd) * Trinkets * * Assume LvB used on CD and FS either after LvB, on dot drop or before LvB * Filler: LB * NYI Optional: use of CL */ Estimation e; Rotation rot; float damage; Stats procStats; float FightDuration = bossOpts.BerserkTimer; // WITHOUT PROCS e = new Estimation(stats, new Stats{}, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); // WITH PROCS int nPasses = 2, k; for (k = 0; k < nPasses; k++) { procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); e.Update(stats, procStats, talents, calcOpts); rot = e.getPriorityRotation(calcOpts.RotationType); } // Thunderstorm usage float thunderstormRegen = 0f; #region Thunderstorm if (calcOpts.UseThunderstorm) { float procsPerSecond = Thunderstorm.getProcsPerSecond(talents.GlyphofThunder, (int)FightDuration); thunderstormRegen += (talents.GlyphofThunderstorm ? .1f : .08f) * stats.Mana * procsPerSecond * 5; } #endregion /* Regen variables: (divide by 5 for regen per second) * While casting: ManaRegInFSR * During regen: ManaRegOutFSR */ #region Calculate Regen float spiRegen = 5 * StatConversion.GetSpiritRegenSec(stats.Spirit, stats.Intellect); float replenishRegen = 5 * stats.Mana * stats.ManaRestoreFromMaxManaPerSecond; float judgementRegen = 0;// 5 * rot.GetBaseCastTime() / rot.Duration * stats.ManaRestoreFromBaseManaPPM / 60f * BaseStats.GetBaseStats(character).Mana; float ManaRegInFSR = /*spiRegen * stats.SpellCombatManaRegeneration +*/ stats.Mp5 + replenishRegen + judgementRegen + thunderstormRegen; float ManaRegOutFSR = spiRegen + stats.Mp5 + replenishRegen + thunderstormRegen; float ManaRegen = ManaRegInFSR; #endregion // TotalDamage, CastFraction, TimeUntilOOM #region Calculate total damage in the fight float TimeUntilOOM = 0; float effectiveMPS = rot.MPS - ManaRegen / 5f; if (effectiveMPS <= 0) TimeUntilOOM = FightDuration; else TimeUntilOOM = (calculatedStats.BasicStats.Mana) / effectiveMPS; if (TimeUntilOOM > FightDuration) TimeUntilOOM = FightDuration; #region SpecialEffects from procs etc. procStats = DoSpecialEffects(character, stats, rot, FightDuration); //procStats = getTrinketStats(character, stats, calcOpts.FightDuration, rot); //damage procs (Thunder Capacitor etc.) are effected by spellcrit and damage debuffs damage = procStats.ArcaneDamage * (1 + stats.BonusArcaneDamageMultiplier) + procStats.NatureDamage * (1 + stats.BonusNatureDamageMultiplier) + procStats.FireDamage * (1 + stats.BonusFireDamageMultiplier) + procStats.ShadowDamage * (1 + stats.BonusShadowDamageMultiplier); if (damage > 0) { damage *= (1 + stats.SpellCrit * .5f); // but only with the normal 50% dmg bonus rot.DPS += damage; } #endregion float TotalDamage = TimeUntilOOM * rot.DPS; float TimeToRegenFull = 5f * calculatedStats.BasicStats.Mana / ManaRegOutFSR; float TimeToBurnAll = calculatedStats.BasicStats.Mana / effectiveMPS; float CastFraction = 1f; if (ManaRegOutFSR > 0 && FightDuration > TimeUntilOOM) { float timeLeft = FightDuration - TimeUntilOOM; if (TimeToRegenFull + TimeToBurnAll == 0) CastFraction = 0; else CastFraction = TimeToBurnAll / (TimeToRegenFull + TimeToBurnAll); TotalDamage += timeLeft * rot.DPS * CastFraction; } #endregion float bsRatio = ((float)calcOpts.BSRatio) * 0.01f; calculatedStats.BurstPoints = (1f - bsRatio) * 2f * rot.DPS; calculatedStats.SustainedPoints = bsRatio * 2f * TotalDamage / FightDuration; calculatedStats.OverallPoints = calculatedStats.BurstPoints + calculatedStats.SustainedPoints; calculatedStats.CombatStats = stats.Clone(); calculatedStats.CombatStats.Accumulate(procStats); calculatedStats.ManaRegenInFSR = ManaRegInFSR; calculatedStats.ReplenishMP5 = replenishRegen; calculatedStats.LightningBolt = rot.LB; calculatedStats.ChainLightning = rot.CL; calculatedStats.FlameShock = rot.FS; calculatedStats.LavaBurst = rot.LvB; calculatedStats.EarthShock = rot.ES; calculatedStats.FrostShock = rot.FrS; // asd calculatedStats.FireNova = rot.FN; calculatedStats.SearingTotem = rot.ST; calculatedStats.MagmaTotem = rot.MT; calculatedStats.TimeToOOM = TimeUntilOOM; calculatedStats.CastRegenFraction = CastFraction; calculatedStats.CastsPerSecond = rot.getCastsPerSecond(); calculatedStats.CritsPerSecond = rot.getWeightedCritchance() * rot.getCastsPerSecond(); calculatedStats.MissesPerSecond = rot.getCastsPerSecond() * (1f - rot.getWeightedHitchance()); calculatedStats.LvBPerSecond = rot.getCastsPerSecond(typeof(LavaBurst)); calculatedStats.LBPerSecond = rot.getCastsPerSecond(typeof(LightningBolt)); calculatedStats.FSPerSecond = rot.getCastsPerSecond(typeof(FlameShock)); calculatedStats.LatencyPerSecond = rot.LatencyPerSecond; calculatedStats.RotationDPS = rot.DPS; calculatedStats.RotationMPS = rot.MPS; calculatedStats.TotalDPS = TotalDamage / FightDuration; rot.ClearCasting.TryGetValue(typeof(FlameShock), out calculatedStats.ClearCast_FlameShock); rot.ClearCasting.TryGetValue(typeof(LavaBurst), out calculatedStats.ClearCast_LavaBurst); rot.ClearCasting.TryGetValue(typeof(LightningBolt), out calculatedStats.ClearCast_LightningBolt); calculatedStats.Rotation = rot.ToString(); calculatedStats.RotationDetails = rot.ToDetailedString(); }
public Stats GetBuffsStats(Character character, CalculationOptionsElemental calcOpts) { List<Buff> removedBuffs = new List<Buff>(); List<Buff> addedBuffs = new List<Buff>(); //float hasRelevantBuff; #region Passive Ability Auto-Fixing // Removes the Trueshot Aura Buff and it's equivalents Unleashed Rage and Abomination's Might if you are // maintaining it yourself. We are now calculating this internally for better accuracy and to provide // value to relevant talents /*{ hasRelevantBuff = character.HunterTalents.TrueshotAura; Buff a = Buff.GetBuffByName("Trueshot Aura"); Buff b = Buff.GetBuffByName("Unleashed Rage"); Buff c = Buff.GetBuffByName("Abomination's Might"); if (hasRelevantBuff > 0) { if (character.ActiveBuffs.Contains(a)) { character.ActiveBuffs.Remove(a); removedBuffs.Add(a); } if (character.ActiveBuffs.Contains(b)) { character.ActiveBuffs.Remove(b); removedBuffs.Add(b); } if (character.ActiveBuffs.Contains(c)) { character.ActiveBuffs.Remove(c); removedBuffs.Add(c); } } }*/ #endregion Stats statsBuffs = GetBuffsStats(character.ActiveBuffs, character.SetBonusCount); foreach (Buff b in removedBuffs) { character.ActiveBuffsAdd(b); } foreach (Buff b in addedBuffs) { character.ActiveBuffs.Remove(b); } return statsBuffs; }
public override Stats GetCharacterStats(Character character, Item additionalItem) { CalculationOptionsElemental calcOpts = character.CalculationOptions as CalculationOptionsElemental; Stats statsRace = BaseStats.GetBaseStats(character); Stats statsItems = GetItemStats(character, additionalItem); Stats statsBuffs = GetBuffsStats(character, calcOpts); Stats statsTotal = statsRace + statsItems + statsBuffs; if (statsTotal.HighestStat > 0) { if (statsTotal.Spirit > statsTotal.Intellect) { statsTotal.Spirit += (statsTotal.HighestStat * 15f / 50f); } else { statsTotal.Intellect += (statsTotal.HighestStat * 15f / 50f); } } statsTotal.Strength *= 1 + statsTotal.BonusStrengthMultiplier; statsTotal.Agility *= 1 + statsTotal.BonusAgilityMultiplier; statsTotal.Stamina *= 1 + statsTotal.BonusStaminaMultiplier; statsTotal.Intellect *= 1 + statsTotal.BonusIntellectMultiplier; statsTotal.Spirit *= 1 + statsTotal.BonusSpiritMultiplier; statsTotal.Strength = (float)Math.Floor(statsTotal.Strength); statsTotal.Agility = (float)Math.Floor(statsTotal.Agility); statsTotal.Stamina = (float)Math.Floor(statsTotal.Stamina); statsTotal.Intellect = (float)Math.Floor(statsTotal.Intellect); statsTotal.Spirit = (float)Math.Floor(statsTotal.Spirit); if (Character.ValidateArmorSpecialization(character, ItemType.Mail)) { statsTotal.Intellect *= 1.05f; } statsTotal.AttackPower += statsTotal.Strength + statsTotal.Agility; statsTotal.Mana += StatConversion.GetManaFromIntellect(statsTotal.Intellect); statsTotal.Mana *= (float)Math.Round(1f + statsTotal.BonusManaMultiplier); statsTotal.Health += StatConversion.GetHealthFromStamina(statsTotal.Stamina); statsTotal.Health *= (float)Math.Round(1f + statsTotal.BonusHealthMultiplier); statsTotal.SpellCrit += StatConversion.GetSpellCritFromRating(statsTotal.CritRating); statsTotal.SpellCrit += StatConversion.GetSpellCritFromIntellect(statsTotal.Intellect); statsTotal.SpellCrit += statsTotal.SpellCritOnTarget; statsTotal.SpellHit += StatConversion.GetSpellHitFromRating(statsTotal.HitRating + ((.33f * character.ShamanTalents.ElementalPrecision) * statsTotal.Spirit)); // Flametongue weapon assumed statsTotal.SpellPower += (float)Math.Floor(747.78 * (1f + character.ShamanTalents.ElementalWeapons * .2f)); if (character.ShamanTalents.GlyphofFlametongueWeapon) { statsTotal.SpellCrit += .02f; } // Water shield assumed statsTotal.Mp5 += 100; if (character.ShamanTalents.GlyphofWaterShield) { statsTotal.Mp5 += 30; } return(statsTotal); }