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);
            }
        }
Beispiel #2
0
        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);
        }
Beispiel #3
0
        //
        // 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);
        }
Beispiel #4
0
        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);
            }
        }