private void GenerateSpellList(Character character) { _AvailableSpells.Clear(); float tankHealingModifier = (_CalculationOptions.EarthShield && _CalculationOptions.Targets == "Tank") ? 0.15f : 0f; short orbValue = (short)((1516 * (1 + (character.ShamanTalents.ImprovedShields * .05f)))); if (_CalculationOptions.EarthShield) { EarthShield es = new EarthShield() { BaseManaCost = (int)(0.19f * _BaseMana), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f), BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0f }; if (character.ShamanTalents.GlyphofEarthShield) es.EffectModifier += 0.2f; if (character.ShamanTalents.ImprovedShields > 0) es.EffectModifier += character.ShamanTalents.ImprovedShields * 0.05f; _AvailableSpells.Add(es); } if (character.ShamanTalents.Riptide > 0) { Riptide riptide = new Riptide() { BaseManaCost = (int)(0.10f * _BaseMana), DurationModifer = (character.ShamanTalents.GlyphofRiptide ? 6f : 0f), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = (1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier), BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ProvidesTidalWaves = (character.ShamanTalents.TidalWaves > 0) }; _AvailableSpells.Add(riptide); } HealingRain healingRain = new HealingRain() { BaseManaCost = (int)(0.46f * _BaseMana), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f), AbsorbOrbChance = 0f, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f) }; //_AvailableSpells.Add(healingRain); ChainHeal chainHeal = new ChainHeal() { BaseManaCost = (int)(0.17f * _BaseMana), ChainedHeal = false, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.15f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ProvidesTidalWaves = (character.ShamanTalents.TidalWaves > 0) }; _AvailableSpells.Add(chainHeal); HealingSpell healingSurge = new HealingSpell() { SpellId = 8004, SpellName = "Healing Surge", SpellAbrv = "HS", BaseManaCost = (int)(0.27f * _BaseMana), BaseCastTime = 1.5f, BaseCoefficient = 1.5f / 3.5f, BaseEffect = 6004f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.3f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ConsumesTidalWaves = true }; if (character.ShamanTalents.TidalWaves > 0) healingSurge.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellCrit = 0.1f * character.ShamanTalents.TidalWaves } }; _AvailableSpells.Add(healingSurge); HealingSpell healingWave = new HealingSpell() { SpellId = 331, SpellName = "Healing Wave", SpellAbrv = "HW", BaseManaCost = (int)(0.09f * _BaseMana), BaseCastTime = 3f, BaseCoefficient = 3f / 3.5f, BaseEffect = 3002f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), ConsumesTidalWaves = true, AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, CastTimeReduction = 0.5f // Purification }; if (character.ShamanTalents.TidalWaves > 0) healingWave.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellHaste = 0.1f * character.ShamanTalents.TidalWaves } }; _AvailableSpells.Add(healingWave); HealingSpell greaterHw = new HealingSpell() { SpellId = 77472, SpellName = "Greater Healing Wave", SpellAbrv = "GHW", BaseManaCost = (int)(0.3f * _BaseMana), BaseCastTime = 3f, BaseCoefficient = 3f / 3.5f, BaseEffect = 8005f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), ConsumesTidalWaves = true, AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, CastTimeReduction = 0.5f // Purification }; if (character.ShamanTalents.TidalWaves > 0) greaterHw.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellHaste = 0.1f * character.ShamanTalents.TidalWaves } }; _AvailableSpells.Add(greaterHw); if (character.ShamanTalents.TelluricCurrents > 0) { LightningBolt lb = new LightningBolt() { BaseManaCost = (int)(0.06f * _BaseMana), CostScale = 1f - character.ShamanTalents.Convection * .05f, EffectModifier = 1f + (character.ShamanTalents.Concussion * 0.02f) + (character.ShamanTalents.GlyphofLightningBolt ? 0.04f : 0f), TCPercent = character.ShamanTalents.TelluricCurrents * 0.2f }; _AvailableSpells.Add(lb); } }
public CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, Stats statModifier) { Stats stats = GetCharacterStats(character, additionalItem, statModifier); CharacterCalculationsRestoSham calcStats = new CharacterCalculationsRestoSham(); calcStats.BasicStats = stats; calcStats.Mp5OutsideFSR = 5f * (.001f + (float)Math.Sqrt((double)stats.Intellect) * stats.Spirit * .009327f) + stats.Mp5; calcStats.SpellCrit = .022f + ((stats.Intellect / 80f) / 100) + ((stats.SpellCritRating / 22.08f) / 100) + stats.SpellCrit; CalculationOptionsRestoSham options = character.CalculationOptions as CalculationOptionsRestoSham; // Total Mana Pool for the fight: float onUse = 0.0f; if (options.ManaPotTime > 0) { onUse += (float)Math.Truncate(options.FightLength / options.ManaPotTime) * (options.ManaPotAmount * (1 + stats.BonusManaPotion)); } if (options.ManaTideEveryCD) { onUse += ((float)Math.Truncate(options.FightLength / 5.025f) + 1) * (stats.Mana * .24f); } float mp5 = (stats.Mp5 * (1f - (options.OutsideFSRPct / 100f))); mp5 += (calcStats.Mp5OutsideFSR * (options.OutsideFSRPct / 100f)); mp5 += options.SPriestMP5; if (character.ActiveBuffsContains("Mana Spring Totem")) { int points = GetTalentPoints("Restorative Totems", "Restoration", character.Talents); mp5 += 50f * (points * .05f); mp5 += stats.ManaSpringMp5Increase; } calcStats.TotalManaPool = stats.Mana + onUse + (mp5 * (60f / 5f) * options.FightLength); // Get a list of the heals we're casting, and assign relative weights to them: List <HealSpell> list = new List <HealSpell>(); float totalRatio = options.HWRatio + options.LHWRatio + options.CHRatio; if (options.LHWRatio > 0) { LesserHealingWave lhw = new LesserHealingWave(); lhw.Calcluate(stats, character); lhw.Weight = options.LHWWeight; list.Add(lhw); } if (options.HWRatio > 0) { if (options.HWDownrank.Ratio > 0) { HealingWave hw = new HealingWave(options.HWDownrank.MaxRank); hw.Calcluate(stats, character); hw.Weight = options.HWWeight * (options.HWDownrank.Ratio / 100f); list.Add(hw); } if (options.HWDownrank.Ratio < 100) { HealingWave hw = new HealingWave(options.HWDownrank.MinRank); hw.Calcluate(stats, character); hw.Weight = options.HWWeight * ((100 - options.HWDownrank.Ratio) / 100f); list.Add(hw); } } if (options.CHRatio > 0) { if (options.CHDownrank.Ratio > 0) { ChainHeal ch = new ChainHeal(options.CHDownrank.MaxRank); ch.Calcluate(stats, character); ch.Weight = options.CHWeight * (options.CHDownrank.Ratio / 100f); list.Add(ch); } if (options.CHDownrank.Ratio < 100) { ChainHeal ch = new ChainHeal(options.CHDownrank.MinRank); ch.Calcluate(stats, character); ch.Weight = options.CHWeight * ((100 - options.CHDownrank.Ratio) / 100f); list.Add(ch); } } // Now get weighted average heal, weighted average mana cost, and weighted average cast time: calcStats.AverageHeal = 0; calcStats.AverageManaCost = 0; calcStats.AverageCastTime = 0; foreach (HealSpell spell in list) { calcStats.AverageHeal += spell.AverageHealed * spell.Weight; calcStats.AverageCastTime += spell.CastTime * spell.Weight; calcStats.AverageManaCost += spell.ManaCost * spell.Weight; } calcStats.AverageManaCost -= stats.ManaRestorePerCast_5_15 * .02f; // Insightful Earthstorm Diamond // Earth Shield computations: float esMana = 0f; float esHeal = 0f; float esNum = 0f; if (options.ESInterval > 0) { EarthShield es = new EarthShield(options.ESRank); es.Calcluate(stats, character); esNum = (float)Math.Round((options.FightLength / (options.ESInterval / 60f)) + 1, 0); esMana = es.ManaCost * esNum; esHeal = es.AverageHealed * esNum; } float numHeals = Math.Min((options.FightLength * 60) / calcStats.AverageCastTime, (calcStats.TotalManaPool - esMana) / calcStats.AverageManaCost); // Now, Shattered Sun Pendant of Restoration Aldor proc. From what I understand, this has a // 4% proc rate with no cooldown. This is a rough estimation of the value of this proc, and // doesn't take into account other things that might proc it (Gift of the Naaru, Earth Shield // if cast on the shaman, etc): if (options.ExaltedFaction == Faction.Aldor && stats.ShatteredSunRestoProc > 0) { // Determine how many more "casts" we get from Chain Heal second / third targets // and Earth Shield (assumption is Earth Shield procs it?): float ssNumHeals = numHeals; if (options.CHRatio > 0) { ssNumHeals += numHeals * options.CHWeight * (options.NumCHTargets - 1); } ssNumHeals += esNum; float ssHeal = (((ssNumHeals * .04f) * 10f) / (options.FightLength * 60f)) * 220f; // Now, we have to recalculate the amount healed based on the proc's addition to healing bonus: stats.Healing += ssHeal; calcStats.AverageHeal = 0f; foreach (HealSpell spell in list) { spell.Calcluate(stats, character); calcStats.AverageHeal += spell.AverageHealed * spell.Weight; } stats.Healing -= ssHeal; } calcStats.TotalHealed = (numHeals * calcStats.AverageHeal) + esHeal; // Shattered Sun Pendant of Restoration Scryers proc. This is going to be a best case // scenario (procs every cooldown, and the proc actually heals someone. Healers using // a mouseover healing system (like Clique) might not benefit at all from this proc): if (options.ExaltedFaction == Faction.Scryers && stats.ShatteredSunRestoProc > 0) { float numProcs = (float)Math.Round((options.FightLength / 60f) / 45f, 0) + 1f; float crit = .022f + ((stats.Intellect / 80f) / 100) + ((stats.SpellCritRating / 22.08f) / 100) + stats.SpellCrit; float critRate = 1 + 0.5f * crit; float ssHealed = numProcs * 650 * critRate; calcStats.TotalHealed += ssHealed; } calcStats.FightHPS = calcStats.TotalHealed / (options.FightLength * 60); calcStats.OverallPoints = calcStats.TotalHealed / 10f; calcStats.SubPoints[0] = calcStats.TotalHealed / 10f; return(calcStats); }
// // Data for custom charts: // public override ComparisonCalculationBase[] GetCustomChartData(Character character, string chartName) { CharacterCalculationsRestoSham calc = GetCharacterCalculations(character) as CharacterCalculationsRestoSham; if (calc == null) { calc = new CharacterCalculationsRestoSham(); } CalculationOptionsRestoSham options = character.CalculationOptions as CalculationOptionsRestoSham; if (options == null) { options = new CalculationOptionsRestoSham(); } List <ComparisonCalculationBase> list = new List <ComparisonCalculationBase>(); switch (chartName) { case "Stat Relative Weights": StatRelativeWeight[] stats = new StatRelativeWeight[] { new StatRelativeWeight("Int", new Stats() { Intellect = 1f }), new StatRelativeWeight("Spirit", new Stats() { Spirit = 1f }), new StatRelativeWeight("+Heal", new Stats() { Healing = 1f }), new StatRelativeWeight("Mp5", new Stats() { Mp5 = 1f }), new StatRelativeWeight("Spell Crit", new Stats() { SpellCritRating = 1f }) }; // Get the percentage total healing is changed by a change in a single stat: float healPct = 0f; foreach (StatRelativeWeight weight in stats) { CharacterCalculationsRestoSham statCalc = (CharacterCalculationsRestoSham)GetCharacterCalculations(character, null, weight.Stat); weight.PctChange = (statCalc.TotalHealed - calc.TotalHealed) / calc.TotalHealed; if (weight.Name == "+Heal") { healPct = weight.PctChange; } } // Create the chart data points: foreach (StatRelativeWeight weight in stats) { ComparisonCalculationRestoSham comp = new ComparisonCalculationRestoSham(weight.Name); comp.OverallPoints = weight.PctChange / healPct; comp.SubPoints[0] = comp.OverallPoints; list.Add(comp); } break; case "Healing Spell Ranks": // Healing Wave ranks: for (int i = 1; i <= 12; i++) { HealingWave hw = new HealingWave(i); hw.Calcluate(calc.BasicStats, character); ComparisonCalculationRestoSham comp = new ComparisonCalculationRestoSham(hw.FullName); comp.OverallPoints = hw.AverageHealed + hw.HealingWay; comp.SubPoints[0] = hw.AverageHealed; comp.SubPoints[3] = hw.HealingWay; list.Add(comp); } // Lesser Healing Wave ranks: for (int i = 1; i <= 7; i++) { LesserHealingWave lhw = new LesserHealingWave(i); lhw.Calcluate(calc.BasicStats, character); ComparisonCalculationRestoSham comp = new ComparisonCalculationRestoSham(lhw.FullName); comp.OverallPoints = comp.SubPoints[0] = lhw.AverageHealed; list.Add(comp); } // Chain Heal ranks: for (int i = 1; i <= 5; i++) { ChainHeal ch = new ChainHeal(i); ch.Calcluate(calc.BasicStats, character); ComparisonCalculationRestoSham comp = new ComparisonCalculationRestoSham(ch.FullName); comp.OverallPoints = ch.TotalHealed; for (int j = 0; j < 3; j++) { comp.SubPoints[j] = ch.HealsOnTargets[j]; } list.Add(comp); } // The Draenei racial: if (character.Race == Character.CharacterRace.Draenei) { GiftOfTheNaaru gift = new GiftOfTheNaaru(); gift.Calcluate(calc.BasicStats, character); ComparisonCalculationRestoSham comp = new ComparisonCalculationRestoSham(gift.FullName); comp.OverallPoints = comp.SubPoints[0] = gift.AverageHealed; list.Add(comp); } break; } ComparisonCalculationBase[] retVal = new ComparisonCalculationBase[list.Count]; if (list.Count > 0) { list.CopyTo(retVal); } return(retVal); }
private void GenerateSpellList(Character character) { _AvailableSpells.Clear(); float tankHealingModifier = (_CalculationOptions.EarthShield && _CalculationOptions.Targets == "Tank") ? 0.15f : 0f; short orbValue = (short)((1516 * (1 + (character.ShamanTalents.ImprovedShields * .05f)))); if (_CalculationOptions.EarthShield) { EarthShield es = new EarthShield() { BaseManaCost = (int)(0.19f * _BaseMana), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f), BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0f }; if (character.ShamanTalents.GlyphofEarthShield) { es.EffectModifier += 0.2f; } if (character.ShamanTalents.ImprovedShields > 0) { es.EffectModifier += character.ShamanTalents.ImprovedShields * 0.05f; } _AvailableSpells.Add(es); } if (character.ShamanTalents.Riptide > 0) { Riptide riptide = new Riptide() { BaseManaCost = (int)(0.10f * _BaseMana), DurationModifer = (character.ShamanTalents.GlyphofRiptide ? 6f : 0f), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = (1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier), BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ProvidesTidalWaves = (character.ShamanTalents.TidalWaves > 0) }; _AvailableSpells.Add(riptide); } HealingRain healingRain = new HealingRain() { BaseManaCost = (int)(0.46f * _BaseMana), CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f), AbsorbOrbChance = 0f, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f) }; //_AvailableSpells.Add(healingRain); ChainHeal chainHeal = new ChainHeal() { BaseManaCost = (int)(0.17f * _BaseMana), ChainedHeal = false, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.15f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ProvidesTidalWaves = (character.ShamanTalents.TidalWaves > 0) }; _AvailableSpells.Add(chainHeal); HealingSpell healingSurge = new HealingSpell() { SpellId = 8004, SpellName = "Healing Surge", SpellAbrv = "HS", BaseManaCost = (int)(0.27f * _BaseMana), BaseCastTime = 1.5f, BaseCoefficient = 1.5f / 3.5f, BaseEffect = 6004f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), AbsorbOrbChance = 0.3f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, ConsumesTidalWaves = true }; if (character.ShamanTalents.TidalWaves > 0) { healingSurge.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellCrit = 0.1f * character.ShamanTalents.TidalWaves } } } ; _AvailableSpells.Add(healingSurge); HealingSpell healingWave = new HealingSpell() { SpellId = 331, SpellName = "Healing Wave", SpellAbrv = "HW", BaseManaCost = (int)(0.09f * _BaseMana), BaseCastTime = 3f, BaseCoefficient = 3f / 3.5f, BaseEffect = 3002f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), ConsumesTidalWaves = true, AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, CastTimeReduction = 0.5f // Purification }; if (character.ShamanTalents.TidalWaves > 0) { healingWave.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellHaste = 0.1f * character.ShamanTalents.TidalWaves } } } ; _AvailableSpells.Add(healingWave); HealingSpell greaterHw = new HealingSpell() { SpellId = 77472, SpellName = "Greater Healing Wave", SpellAbrv = "GHW", BaseManaCost = (int)(0.3f * _BaseMana), BaseCastTime = 3f, BaseCoefficient = 3f / 3.5f, BaseEffect = 8005f, CostScale = 1f - character.ShamanTalents.TidalFocus * .02f, EffectModifier = 1.1f + (character.ShamanTalents.SparkOfLife * .02f) + tankHealingModifier, BonusSpellPower = 1 * ((1 + character.ShamanTalents.ElementalWeapons * .2f) * 150f), ConsumesTidalWaves = true, AbsorbOrbChance = 0.5f * character.ShamanTalents.ImprovedWaterShield, OrbValue = orbValue, CastTimeReduction = 0.5f // Purification }; if (character.ShamanTalents.TidalWaves > 0) { greaterHw.TidalWavesBuff = new TemporaryBuff() { Name = "Tidal Waves", Stats = new Stats() { SpellHaste = 0.1f * character.ShamanTalents.TidalWaves } } } ; _AvailableSpells.Add(greaterHw); if (character.ShamanTalents.TelluricCurrents > 0) { LightningBolt lb = new LightningBolt() { BaseManaCost = (int)(0.06f * _BaseMana), CostScale = 1f - character.ShamanTalents.Convection * .05f, EffectModifier = 1f + (character.ShamanTalents.Concussion * 0.02f) + (character.ShamanTalents.GlyphofLightningBolt ? 0.04f : 0f), TCPercent = character.ShamanTalents.TelluricCurrents * 0.2f }; _AvailableSpells.Add(lb); } }