Example #1
0
        public override double calculateDPS(int hitratingIncrease = 0,
            int critratingIncrease = 0,
            int hasteratingIncrease = 0,
            int strengthIncrease = 0,
            int agilityIncrease = 0,
            int staminaIncrease = 0,
            int intelectIncrease = 0,
            int spiritIncrease = 0,
            int armorpenetrationIncrease = 0,
            int baseSpeedIncrease = 0,
            int powerIncrease = 0,
            int expertiseratingIncrease = 0,
            int rangedPowerIncrease = 0,
            int spellpowerIncrease = 0,
            int manaregenIncrease = 0)
        {
            //talents requiring talents
            curseOfExhaustion.requiredTalent = amplifyCurse;
            unstableAffliction.requiredTalent = contagion;
            pandemic.requiredTalent = unstableAffliction;

            unholyPower.requiredTalent = soulLink;
            masterSummoner.requiredTalent = felDomination;
            manaFeed.requiredTalent = unholyPower;
            masterDemonologist.requiredTalent = unholyPower;
            demonicEmpowerment.requiredTalent = masterDemonologist;
            improvedDemonicTactics.requiredTalent = demonicTactics;

            devastation.requiredTalent = ruin;
            conflagrate.requiredTalent = improvedImmolate;
            backdraft.requiredTalent = conflagrate;
            improvedSoulLeech.requiredTalent = soulLeech;
            //end of talents

            double _hitrating = hitrating + hitratingIncrease;
            double _stamina = stamina + staminaIncrease;
            double _spellpower = spellPower + spellpowerIncrease;
            double _critrating = critrating + critratingIncrease;
            double _hasterating = hasterating + hasteratingIncrease;
            double _intelect = intelect + intelectIncrease;
            double _spirit = spirit + spiritIncrease;
            double _manaregen = manaregen + manaregenIncrease;

            ///////////////////////////////////////////////////////////////////////////////////////
            //STATS CALC
            //Hitrating:
            double buffHitPercent = raidbuffs.spellHitPercent();
            double hitPercentBonus = suppression.pointsSpend + buffHitPercent;

            //Intelect:
            double intFromBuffs = raidbuffs.intelect();
            _intelect += intFromBuffs;
            _intelect *= raidbuffs.intelectFactor();

            updateMinionStats(intel: _intelect);

            //Critrating:
            //TODO: move most of this to talent section/////////////////////////////
            double intCrit = _intelect / 166.666666;
            double stoneCritFlat = (stone == WarlockWeaponEnchant.Firestone ? 1 : 0) * (49 * (1 + (1.5 * masterConjurer.pointsSpend)));
            double CritFromCrit = (_critrating + stoneCritFlat) / 45.91;
            double improvedShadowBoltProcChance = 0.2 * improvedShadowBolt.pointsSpend;
            double improvedShadowBoltCritPercent = improvedShadowBolt.pointsSpend > 0 ? 5 : 0;
            double improvedShadowBoltUptimeFactor = 1 - (improvedShadowBolt.pointsSpend * .03);                                      //TODO: calculation
            double talentsCritPercent = (2 * demonicTactics.pointsSpend) + improvedShadowBoltCritPercent * improvedShadowBoltUptimeFactor + 5 * devastation.pointsSpend;
            double talentsShadowCritPercent = (minion.kind == Minion.Succubus ? masterDemonologist.pointsSpend : 0);
            double talentsFireCritPercent = (minion.kind == Minion.Imp ? masterDemonologist.pointsSpend : 0);

            double setPieceCritPercent = (t10_2PieceBonus ? 5 : 0);

            double CorruptionUptimeFactor = 1 /*Corruption.cooldown / Corruption.effectiveCooldown*/;
            double moltenCoreChance = 0.04 * moltenCore.pointsSpend * CorruptionUptimeFactor;
            double SFMoltenCoreCritIncreasePercent = 5 * moltenCore.pointsSpend;

            //double SBCritFactor = (((CritFromCrit) + talentsCritPercent + talentsShadowCritPercent + setPieceCritPercent + intCrit) * (0.005 * (1 + (0.2 * ruin)))) + 1;
            //double IncinerateCritFactor = (((CritFromCrit) + talentsCritPercent + talentsFireCritPercent + setPieceCritPercent + intCrit) * (0.005 * (1 + (0.2 * ruin)))) + 1;
            //double SFCritFactor = (((CritFromCrit) + talentsCritPercent + talentsFireCritPercent + setPieceCritPercent + (moltenCoreChance * SFMoltenCoreCritIncreasePercent) + intCrit) * (0.005 * (1 + (0.2 * ruin)))) + 1;
            //double immoCritFactor = (((CritFromCrit) + talentsCritPercent + talentsFireCritPercent + intCrit) * (0.005 * (1 + (0.2 * ruin)))) + 1;
            //double shadowCleaveCritFactor = (((CritFromCrit + talentsCritPercent + talentsShadowCritPercent + intCrit) * (0.005 * (1 + (0.2 * ruin)))) + 1;

            updateMinionStats(crit: ((intCrit + talentsCritPercent) * 45.91));

            //Hasterating:
            double stoneHasteFlat = (stone == WarlockWeaponEnchant.Spellstone ? 1 : 0) * (60 * (1 + (1.5 * masterConjurer.pointsSpend)));
            _hasterating += stoneHasteFlat;
            double buffHaste = raidbuffs.spellHastePercent() * 32.79;
            _hasterating += buffHaste;

            //Stamina:
            double demonicEmbraceFactor = demonicEmbrace.pointsSpend > 0 ? 1.01 + (0.03 * demonicEmbrace.pointsSpend) : 1;
            double stam = (_stamina + raidbuffs.stamina()) * demonicEmbraceFactor * raidbuffs.staminaFactor();

            updateMinionStats(stam: stam);

            //Spirit:
            _spirit += raidbuffs.spirit();
            _spirit *= raidbuffs.spiritFactor();

            //Spellpower:
            double demonicKnowledgeSP = demonicKnowledge.pointsSpend * 0.04 * (minion.getStamina() + minion.getIntelect());
            double setPieceSP = (PvP_2PieceBonus ? 29 : 0) + (PvP_4PieceBonus ? 88 : 0);
            double demonicAegisFactor = 1 + (0.1 * demonicAegis.pointsSpend);
            double demonicAegisSP = (180 * demonicAegisFactor) + ((0.3 * demonicAegisFactor) * _spirit);
            double glyphOfLifeTapSP = glyphOfLifeTap ? 0.2 * _spirit : 0; //asuming 100% uptime, 1 lifetap every 40 sec.
            double procBonusSP = procIncrease(Stat.Spellpower); //TODO: UI part
            double demonicPactSPFactor = 1 + (0.02 * demonicPact.pointsSpend);
            double raceSP = race.getRaceBonus().spelldamageFlat;
            double sp = (_spellpower + demonicAegisSP + glyphOfLifeTapSP + setPieceSP + procBonusSP + demonicKnowledgeSP + raceSP + raidbuffs.spellpower()) * demonicPactSPFactor;

            updateMinionStats(sp: sp);

            //Mana and manaregen:
            double mana = baseMana + ((_intelect - 20) * 15) + 20;
            double mp5FromReplenishment = raidbuffs.percentualManaregen() * (mana / 100);
            double mp5FromBuffs = raidbuffs.manaregen() + mp5FromReplenishment;
            double mp5 = _manaregen + mp5FromBuffs;
            double mps = mp5 / 5;

            ///////////////////////////////////////////////////////////////////////////////////////
            //Damage multipliers
            double setPieceImmoCorrUADmgFactor = (t9_4PieceBonus ? 1.1 : 1);
            double deviousMindsUptimeFactor = CalculateUptimeFactor(0.15, 1/3,0,10);
            double t10_4PieceBonusUptime = (t10_4PieceBonus ? deviousMindsUptimeFactor : 0);
            double setPieceAllDmgFactor = (t10_4PieceBonusUptime * 0.1) + 1.0;

            bool metamorphosisLearned = metamorphosis.pointsSpend == 1;
            double metamorphosisCD = 180 * (1 - (0.1 * nemesis.pointsSpend));
            double metamorphosisDuration = 30 + (glyphOfMetamorphosis ? 6 : 0);
            double metamorphosisDmgFactor = 1 + (metamorphosisLearned ? ((metamorphosisDuration / metamorphosisCD) * 0.2) : 0);

            double stoneDirectDmgFactor = (stone == WarlockWeaponEnchant.Firestone ? 1.01 : 1);
            double stoneDoTDmgFactor = (stone == WarlockWeaponEnchant.Spellstone ? 1.01 : 1);

            double improvedShadowBoltDamageFactor = 1 + (improvedShadowBolt.pointsSpend * 0.02);
            double glyphOfIncinerateFactor = glyphOfIncinerate ? 1.05 : 1;
            double glyphOfImmolateDoTFactor = glyphOfImmolate ? 1.1 : 1;
            double talentsShadowDamageFactor = (minion.kind == Minion.Succubus || minion.kind == Minion.Felguard ? 1 + (0.01 * masterDemonologist.pointsSpend) : 1);    //succubus or felguard
            double talentsFireDamageFactor = (minion.kind == Minion.Imp || minion.kind == Minion.Felguard ? 1 + (0.01 * masterDemonologist.pointsSpend) : 1);           //imp or felguar
            talentsFireDamageFactor *= (1 + 0.03 * emberstorm.pointsSpend);

            ////////CASTTIME//////////
            double hasteFactor = 1 + ((_hasterating / 32.79) / 100);
            double gcd = applyMinimumGCD(1.5 / hasteFactor);

            double backdraftFactor = 1 - (0.1 * backdraft.pointsSpend);
            double moltenCoreCastTimeFactor = 1 - (0.1 * moltenCore.pointsSpend);

            double pushbackReduction = raidbuffs.pushbackReductionPercent();
            double pushbackReductionDestro = (35 * intensity.pointsSpend) + pushbackReduction;
            double pushbackReductionAffli = (23.3 * felConcentration.pointsSpend) + pushbackReduction;
            double castTimeLostFactor = 1 + (0.2 / 3); //getting hit once every 7.5 sec
            double castTimeLostFactorDestro = castTimeLostFactor;
            double castTimeLostFactorAffli = castTimeLostFactor;

            if (pushbackReductionDestro > 100)
                castTimeLostFactorDestro = 1;
            else
                castTimeLostFactorDestro = ((castTimeLostFactorDestro - 1) * (1 - (pushbackReductionDestro / 100))) + 1;

            if (pushbackReductionAffli > 100)
                castTimeLostFactorAffli = 1;
            else
                castTimeLostFactorAffli = ((castTimeLostFactorAffli - 1) * (1 - (pushbackReductionAffli / 100))) + 1;

            ///////SPELLLIST///////
            List<Spell> spellList = new List<Spell>();
            //curses
            Spell CurseOfTheElements = new Spell(SpellName.CurseOfTheElements, Affliction,
                                                directSpellSchool: Shadow,
                                                duration: 300,
                                                manaCostOfBaseMana: 0.1
                                                );
            CurseOfTheElements.applyGCD(gcd);

            Spell CurseOfDoom = new Spell(SpellName.CurseOfDoom, Affliction,
                                                DoTSpellSchool: Shadow,
                                                duration: 60,
                                                cooldown: 60,
                                                manaCostOfBaseMana: 0.15,
                                                averageDoTBaseDamage: 7300,
                                                SPDoTScaling: 2);
            CurseOfDoom.applyGCD(gcd);

            Spell CurseOfAgony = new Spell(SpellName.CurseOfAgony, Affliction,
                                                DoTSpellSchool: Shadow,
                                                duration: 24 + (glyphOfCurseOfAgony ? 4 : 0),
                                                manaCostOfBaseMana: 0.1,
                                                averageDoTBaseDamage: 1740, //CHECK
                                                SPDoTScaling: 1.2);
            CurseOfAgony.applyGCD(gcd);

            Spell CurseOfWeakness = new Spell(SpellName.CurseOfWeakness, Affliction,
                                                directSpellSchool: Shadow,
                                                duration:120,
                                                manaCostOfBaseMana: 0.1);
            CurseOfWeakness.applyGCD(gcd);

            Spell CurseOfTongues = new Spell(SpellName.CurseOfTongues, Affliction,
                                                directSpellSchool: Shadow,
                                                duration: 30,
                                                manaCostOfBaseMana: 0.04);
            CurseOfTongues.applyGCD(gcd);

            //standard warlock spells
            Spell LifeTap = new Spell(SpellName.LifeTap, Affliction);   //prolly never using it
            LifeTap.applyGCD(gcd);

            Spell DrainLife = new Spell(SpellName.DrainLife, Affliction,
                                                DoTSpellSchool: Shadow,
                                                baseCasttime:5,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.17,
                                                averageDoTBaseDamage: 665,
                                                SPDoTScaling: 0.143,
                                                channeled: true,
                                                numOfTicks: 5);
            DrainLife.applyCastTimeFactor(castTimeLostFactorAffli);
            DrainLife.applyGCD(gcd);

            Spell DrainSoul = new Spell(SpellName.DrainSoul, Affliction,
                                                DoTSpellSchool: Shadow,
                                                baseCasttime: 15,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                requiredBuffUptimeFactor: 0.75,
                                                averageDoTBaseDamage: 710,
                                                SPDoTScaling: 0.429,
                                                channeled: true,
                                                numOfTicks: 5);
            DrainSoul.applyCastTimeFactor(castTimeLostFactorAffli);
            DrainSoul.applyGCD(gcd);

            Spell DrainSoulUnder25 = new Spell(SpellName.DrainSoul, Affliction,
                                                DoTSpellSchool: Shadow,
                                                baseCasttime: 15,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                requiredBuffUptimeFactor: 0.75,
                                                averageDoTBaseDamage: 710,
                                                SPDoTScaling: 0.429,
                                                channeled: true,
                                                numOfTicks: 5,
                                                DoTDamageFactor: 4);
            DrainSoulUnder25.applyCastTimeFactor(castTimeLostFactorAffli);
            DrainSoulUnder25.applyGCD(gcd);

            Spell Corruption = new Spell(SpellName.Corruption, Affliction,
                                                DoTSpellSchool: Shadow,
                                                duration:18,
                                                hasteAffectsDuration: glyphOfQuickDecay,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                averageDoTBaseDamage: 1080,
                                                SPDoTScaling: 0.2,
                                                numOfTicks: 6);
            Corruption.applyGCD(gcd);

            //asuming enough dps on target to never have seed of corruption tick
            Spell SeedOfCorruption = new Spell(SpellName.SeedOfCorruption, Affliction,
                                                directSpellSchool: Shadow,
                                                baseCasttime: 2,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.34,
                                                averageDirectBaseDamage: 1518,
                                                SPDirectScaling: 0.2129);
            SeedOfCorruption.applyCastTimeFactor(castTimeLostFactor);
            SeedOfCorruption.applyGCD(gcd);

            Spell Shadowflame = new Spell(SpellName.Shadowflame, Destruction,
                                                directSpellSchool: Shadow,
                                                DoTSpellSchool: Fire,
                                                duration: 8,
                                                cooldown: 15,
                                                manaCostOfBaseMana: 0.25,
                                                averageDirectBaseDamage: 643.5,
                                                averageDoTBaseDamage: 0,
                                                SPDirectScaling: 0.1064,
                                                SPDoTScaling: 0.0667,
                                                numOfTicks: 4);
            Shadowflame.applyGCD(gcd);

            Spell SearingPain = new Spell(SpellName.SearingPain, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 1.5,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.08,
                                                averageDirectBaseDamage: 374.5,
                                                SPDirectScaling: 0.4293);
            SearingPain.applyCastTimeFactor(castTimeLostFactorDestro);
            SearingPain.applyGCD(gcd);

            Spell Immolate = new Spell(SpellName.Immolate, Destruction,
                                                directSpellSchool: Fire,
                                                DoTSpellSchool: Fire,
                                                duration: 15,
                                                baseCasttime: 2,
                                                flatCasttimeReduction: 0.1 * bane.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.17,
                                                averageDirectBaseDamage: 460,
                                                averageDoTBaseDamage: 785,
                                                SPDirectScaling: 0.2,
                                                SPDoTScaling: 0.2,
                                                numOfTicks: 5);
            Immolate.applyCastTimeFactor(castTimeLostFactorDestro);
            Immolate.applyGCD(gcd);

            Spell Shadowbolt = new Spell(SpellName.ShadowBolt, Destruction,
                                                directSpellSchool: Shadow,
                                                baseCasttime: 3,
                                                flatCasttimeReduction: 0.1 * bane.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.17,
                                                averageDirectBaseDamage: 803,
                                                SPDirectScaling: 0.8569);
            Shadowbolt.applyCastTimeFactor(castTimeLostFactorDestro);
            Shadowbolt.applyGCD(gcd);

            Spell ShadowBoltInstant = new Spell(SpellName.ShadowBoltInstant,Destruction,
                                                directSpellSchool: Shadow,
                                                manaCostOfBaseMana: 0.17,
                                                requiredBuffUptimeFactor: ((nightfall.pointsSpend * 0.02) + ((glyphOfCorruption ? 1 : 0) * 0.04)) * CorruptionUptimeFactor, // TEMP!
                                                averageDirectBaseDamage: 803,
                                                SPDirectScaling: 0.8569);
            ShadowBoltInstant.applyGCD(gcd);

            Spell Incinerate = new Spell(SpellName.Incinerate, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.05 * emberstorm.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                averageDirectBaseDamage: 629.5,
                                                SPDirectScaling: 0.7139);
            Incinerate.applyCastTimeFactor(castTimeLostFactorDestro);
            Incinerate.applyGCD(gcd);

            Spell Soulfire = new Spell(SpellName.Soulfire, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 6,
                                                flatCasttimeReduction: 0.4 * bane.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.09,
                                                reagent: Reagent.Soulshard,
                                                averageDirectBaseDamage: 1490.5,
                                                SPDirectScaling: 1.15);
            Soulfire.applyCastTimeFactor(castTimeLostFactorDestro);
            Soulfire.applyGCD(gcd);

            Spell SoulfireDecimation = new Spell(SpellName.SoulfireDecimation, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 6,
                                                flatCasttimeReduction: 0.4 * bane.pointsSpend,
                                                percentualCasttimeReduction: 20 * decimation.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.09,
                                                requiredBuffUptimeFactor: 0,
                                                reagent: Reagent.Soulshard,
                                                averageDirectBaseDamage: 1490.5,
                                                SPDirectScaling: 1.15);
            SoulfireDecimation.applyCastTimeFactor(castTimeLostFactorDestro);
            SoulfireDecimation.applyGCD(gcd);

            Spell DarkPact = new Spell(SpellName.DarkPact, Affliction);
            DarkPact.applyGCD(gcd);

            Spell UnstableAffliction = new Spell(SpellName.UnstableAffliction, Affliction,
                                                DoTSpellSchool: Shadow,
                                                duration: 15,
                                                baseCasttime: 1.5,
                                                flatCasttimeReduction: (glyphOfUnstableAffliction ? 0.2 : 0),
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.15,
                                                averageDoTBaseDamage: 1150,
                                                SPDoTScaling: 0.2,
                                                numOfTicks: 5);
            UnstableAffliction.applyCastTimeFactor(castTimeLostFactorAffli);
            UnstableAffliction.applyGCD(gcd);

            Spell Haunt = new Spell(SpellName.Haunt, Affliction,
                                                directSpellSchool: Shadow,
                                                DoTSpellSchool: Shadow,
                                                duration: 12,
                                                baseCasttime: 1.5,
                                                hasteFactor: hasteFactor,
                                                cooldown: 8,
                                                manaCostOfBaseMana: 0.12,

                                                averageDirectBaseDamage: 699,
                                                averageDoTBaseDamage: 0,
                                                SPDirectScaling: 0.4793,
                                                numOfTicks: 0);
            Haunt.applyCastTimeFactor(castTimeLostFactorAffli);
            Haunt.applyGCD(gcd);

            Spell IncinerateMoltenCore = new Spell(SpellName.IncinerateMoltenCore, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.05 * emberstorm.pointsSpend,
                                                percentualCasttimeReduction: 10 * moltenCore.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                requiredBuffUptimeFactor: 0,
                                                averageDirectBaseDamage: 629.5,
                                                SPDirectScaling: 0.7139,
                                                directDamageFactor: 1 + (0.06 * moltenCore.pointsSpend));
            IncinerateMoltenCore.applyCastTimeFactor(castTimeLostFactorDestro);
            IncinerateMoltenCore.applyGCD(gcd);

            Spell DemonicEmpowerment = new Spell(SpellName.DemonicEmpowerment, Demonology);

            Spell Metamorphosis = new Spell(SpellName.Metamorphosis, Demonology,
                                                duration: metamorphosis.pointsSpend > 0 ? (glyphOfMetamorphosis ? 36 : 30) : 0,
                                                cooldown: 180 * (1 - (0.1 * nemesis.pointsSpend)));

            Spell ImmolationAura = new Spell(SpellName.ImmolationAura, Demonology,
                                                DoTSpellSchool: Fire,
                                                duration: 15,
                                                hasteAffectsDuration: true,
                                                hasteFactor: hasteFactor,
                                                cooldown: 30,
                                                manaCostOfBaseMana: 0.64,
                                                requiredBuffUptimeFactor: Metamorphosis.uptimeFactor(),
                                                averageDoTBaseDamage: 251,
                                                SPDoTScaling: 0, //CHECK
                                                numOfTicks: 15);
            ImmolationAura.applyGCD(gcd);

            Spell ShadowCleave = new Spell(SpellName.ShadowCleave, Demonology,
                                                directSpellSchool: Shadow,
                                                cooldown: 6,
                                                manaCostOfBaseMana: 0.04,
                                                requiredBuffUptimeFactor: Metamorphosis.uptimeFactor(),
                                                averageDirectBaseDamage: 110,
                                                SPDirectScaling: 0); //CHECK seems to be 1, but prolly not exactly 1

            Spell Shadowburn = new Spell(SpellName.Shadowburn, Destruction,
                                                cooldown: 10, //CHECK!
                                                manaCostOfBaseMana: 0.2,
                                                requiredBuffUptimeFactor: 1,
                                                reagent: Reagent.Soulshard,
                                                averageDirectBaseDamage: 820.5,
                                                SPDirectScaling: 0.4293);
            Shadowburn.applyGCD(gcd);

            Spell ShadowburnGlyphed = new Spell(SpellName.ShadowburnGlyphed,Destruction,
                                                cooldown: 10, //CHECK!
                                                manaCostOfBaseMana: 0.2,
                                                requiredBuffUptimeFactor: 0,
                                                reagent: Reagent.Soulshard,
                                                averageDirectBaseDamage: 820.5,
                                                SPDirectScaling: 0.4293,
                                                directCritChance: 20);
            ShadowburnGlyphed.applyGCD(gcd);

            Spell Conflagrate = new Spell(SpellName.Conflagrate, Destruction,
                                                directSpellSchool: Fire,
                                                DoTSpellSchool: Fire,
                                                duration: 6,
                                                cooldown: 10,
                                                manaCostOfBaseMana: 0.16,
                                                requiredBuffUptimeFactor: Immolate.uptimeFactor() / (glyphOfConflagrate ? 1 : 2),
                                                averageDirectBaseDamage: Immolate.totalDamagePerCast(_spellpower) * 0.6,
                                                averageDoTBaseDamage: Immolate.totalDamagePerCast(_spellpower) * 0.6 * 0.4,
                                                numOfTicks: 3); //CHECK
            Conflagrate.applyGCD(gcd);

            Spell IncinerateMoltenCoreBackdraft = new Spell(SpellName.IncinerateMoltenCoreBackdraft, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.05 * emberstorm.pointsSpend,
                                                percentualCasttimeReduction: moltenCoreCastTimeFactor * backdraftFactor,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                requiredBuffUptimeFactor: 0 /* molten core uptime * (3 / confla cd) ofso.. */,
                                                averageDirectBaseDamage: 629.5,
                                                SPDirectScaling: 0.7139);
            IncinerateMoltenCoreBackdraft.applyCastTimeFactor(castTimeLostFactorDestro);
            IncinerateMoltenCoreBackdraft.applyGCD(gcd * backdraftFactor);

            Spell IncinerateBackdraft = new Spell(SpellName.IncinerateBackdraft, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.05 * emberstorm.pointsSpend,
                                                percentualCasttimeReduction: backdraftFactor,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.14,
                                                requiredBuffUptimeFactor: 0 /* (3 / confla cd) ofso.. */,
                                                averageDirectBaseDamage: 629.5,
                                                SPDirectScaling: 0.7139);
            IncinerateBackdraft.applyGCD(gcd * backdraftFactor);

            Spell Shadowfury = new Spell(SpellName.Shadowfury, Destruction,
                                                directSpellSchool: Shadow,
                                                cooldown: 20,
                                                manaCostOfBaseMana: 0.27,
                                                averageDirectBaseDamage: 1060,
                                                SPDirectScaling: 0.1); //CHECK
            Shadowfury.applyGCD(0.5); //triggers a small gcd. CHECK

            Spell ChaosBolt = new Spell(SpellName.ChaosBolt, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.1 * bane.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                cooldown: glyphOfChaosBolt ? 10 : 12,
                                                manaCostOfBaseMana: 0.07,
                                                averageDirectBaseDamage: 1621,
                                                SPDirectScaling: 0.7139);
            ChaosBolt.applyCastTimeFactor(castTimeLostFactorDestro);
            ChaosBolt.applyGCD(gcd);

            Spell ChaosBoltBackdraft = new Spell(SpellName.ChaosBoltBackdraft, Destruction,
                                                directSpellSchool: Fire,
                                                baseCasttime: 2.5,
                                                flatCasttimeReduction: 0.1 * bane.pointsSpend,
                                                percentualCasttimeReduction: 10 * backdraft.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                cooldown: glyphOfChaosBolt ? 10 : 12,
                                                manaCostOfBaseMana: 0.07,
                                                averageDirectBaseDamage: 1621,
                                                SPDirectScaling: 0.7139);
            ChaosBoltBackdraft.applyCastTimeFactor(castTimeLostFactorDestro);
            ChaosBoltBackdraft.applyGCD(gcd * backdraftFactor);

            Spell ShadowboltBackdraft = new Spell(SpellName.ShadowboltBackdraft, Destruction,
                                                directSpellSchool: Shadow,
                                                baseCasttime: 3,
                                                flatCasttimeReduction: 0.1 * bane.pointsSpend,
                                                percentualCasttimeReduction: 10 * backdraft.pointsSpend,
                                                hasteFactor: hasteFactor,
                                                manaCostOfBaseMana: 0.17,
                                                averageDirectBaseDamage: 803,
                                                SPDirectScaling: 0.8569);
            ShadowboltBackdraft.applyCastTimeFactor(castTimeLostFactorDestro);
            ShadowboltBackdraft.applyGCD(gcd * backdraftFactor);

            spellList.Add(Shadowflame);
            updateEffectiveSpellCooldown(spellList);

            double instaSBBuffUptimeFactor =
            Shadowbolt.baseCasttime = (instaSBBuffUptimeFactor * gcd) + ((1 - instaSBBuffUptimeFactor) * Shadowbolt.baseCasttime);

            ///////////////////////////////////////////////////////////////////////////////////////
            //MANA USAGE
            double improvedLifeTapFactor = 1 + (0.1 * improvedLifeTap.pointsSpend);
            double manaFromLifeTap = (2000 + 0.5 * sp) * improvedLifeTapFactor;
            double manaFromDarkPact = 1200 + 0.96 * sp;

            double cataclysmFactor = 1 - (cataclysm.pointsSpend > 0 ? 0.01 + 0.03 * cataclysm.pointsSpend : 0);
            double suppressionManaCostFactor = 1 - (0.02 * suppression.pointsSpend);
            double manaFactor = raidbuffs.manaCostFactor();

            Shadowbolt.manaCostFactor *= glyphOfShadowbolt ? 0.9 : 1;
            ShadowboltBackdraft.manaCostFactor *= glyphOfShadowbolt ? 0.9 : 1;
            ShadowBoltInstant.manaCostFactor *= glyphOfShadowbolt ? 0.9 : 1;

            foreach(Spell s in spellList){
                if(s.talentSchool == Affliction)
                    s.manaCostFactor *= suppressionManaCostFactor;
                if(s.talentSchool == Destruction)
                    s.manaCostFactor *= cataclysmFactor;
                s.manaCostFactor *= manaFactor;

                s.effectiveCasttime += (s.manaCost(baseMana,mps)/manaFromLifeTap) * LifeTap.effectiveCasttime;
            }

            //TALENTS

            //affli
            UnstableAffliction.baseCasttime = (1.5 - (glyphOfUnstableAffliction ? 0.2 : 0)) / hasteFactor;
            Haunt.baseCasttime = 1.5 / hasteFactor;
            //demo
            IncinerateMoltenCore.baseCasttime = ((2.5 * moltenCoreCastTimeFactor) - (0.05 * emberstorm.pointsSpend)) / hasteFactor;
            //hybrid
            IncinerateMoltenCoreBackdraft.baseCasttime = ((2.5 * moltenCoreCastTimeFactor * backdraftFactor) - (0.05 * emberstorm.pointsSpend)) / hasteFactor;
            //destro
            Shadowfury.baseCasttime = 0.5 / hasteFactor;                                                                    //triggers small gcd, does haste apply?
            IncinerateBackdraft.baseCasttime = ((2.5 * backdraftFactor) - (0.05 * emberstorm.pointsSpend)) / hasteFactor;
            ChaosBolt.baseCasttime = (2.5 - (0.1 * bane.pointsSpend)) / hasteFactor;
            ChaosBoltBackdraft.baseCasttime = ((2.5 * backdraftFactor) - (0.1 * bane.pointsSpend)) / hasteFactor;

            double moltenCoreDamageFactor = 1 + (0.06 * moltenCore.pointsSpend);

            double ImprovedCorruptionDmgFactor = 1 + (improvedCorruption.pointsSpend * 0.02);
            double AftermathDmgFactor = 1 + (0.03 * aftermath.pointsSpend);
            double improvedImmolateDmgFactor = 1 + (0.1 * improvedImmolate.pointsSpend);

            double CorruptionDamageFactor = setPieceImmoCorrUADmgFactor * ImprovedCorruptionDmgFactor;

            double corrDPS = (((1080 / 6) + (0.2 * sp)) / CorruptionTickSpeed) * CorruptionDamageFactor * stoneDoTDmgFactor * CorruptionUptimeFactor;
            double immoDPS = ((((460 + 0.2 * sp) * stoneDirectDmgFactor) + ((((1256 / 8) + (0.2 * sp)) * 8) * stoneDoTDmgFactor * glyphOfImmolateDoTFactor * immolateUptimeFactor * AftermathDmgFactor)) / 24) * setPieceImmoCorrUADmgFactor * improvedImmolateDmgFactor;
            double SBDPS = ((((759 + 847) / 2) + (0.8569 * sp)) * improvedShadowBoltDamageFactor * talentsShadowDamageFactor * stoneDirectDmgFactor) / SBEffectiveCastTime;
            double IncinDPS = ((((611 + 710) / 2 + (152 + 178) / 2) + 0.7139 * sp) * glyphOfIncinerateFactor * moltenCoreDamageFactor * talentsFireDamageFactor * stoneDirectDmgFactor) / IncinMoltenCoreCastTime;
            double SFDPS = ((((1323 + 1657) / 2) + (1.15 * sp)) * talentsFireDamageFactor * stoneDirectDmgFactor) / SFDecimationCastTime;

            bool decimate = decimation.pointsSpend > 0;
            double SBIncinPart = decimate ? 0.65 : 1;
            double SFPart = decimate ? 0.35 : 0;

            double corruptionTicksPerSec = 1 / CorruptionTickSpeed;
            double chanceIncin = CalculateUptimeFactor(moltenCoreChance, corruptionTicksPerSec, 0, 3 * IncinMoltenCoreEffectiveTime);
            double chanceSB = 1 - chanceIncin;

            double chanceMoltenCoreWhileSF = ((SFDecimationCastTime / CorruptionTickSpeed) * moltenCoreChance) * 3;

            int numImmolationAuraTicks = metamorphosisLearned ? (glyphOfMetamorphosis ? 30 : 15) : 0;
            double immolationAuraDamage = numImmolationAuraTicks * (251 + (0.1714 * sp)) * stoneDoTDmgFactor * talentsFireDamageFactor * setPieceAllDmgFactor; //asuming all ticks are within demo form uptime
            double immolationAuraDPS = immolationAuraDamage / metamorphosisCD;

            int numShadowCleaves = metamorphosisLearned ? (glyphOfMetamorphosis ? 6 : 5) : 0;
            double shadowCleaveDamage = numShadowCleaves * (110 + (0.2571 * sp)) * stoneDirectDmgFactor * talentsShadowDamageFactor * shadowCleaveCritFactor * setPieceAllDmgFactor;
            double shadowCleaveDPS = shadowCleaveDamage / metamorphosisCD;

            double lockDPS = ((((immoDPS * immoCritFactor) + corrDPS + (SBIncinPart * ((chanceIncin * (IncinDPS * IncinerateCritFactor)) + (chanceSB * (SBDPS * SBCritFactor))) + SFPart * (SFDPS * SFCritFactor))) * (metamorphosisDmgFactor * setPieceAllDmgFactor))) + shadowCleaveDPS + immolationAuraDPS;
            lockDPS = applySpellHitrating(lockDPS, (int)_hitrating, hitPercentBonus);
            double minionDPS = minion.getDPS();
            minionDPS *= 1 + (race.getRaceBonus().petDamagePercent * 0.01);
            minionDPS = applySpellHitrating(minionDPS, 0, buffHitPercent);
            double dps = lockDPS + minionDPS;
            return dps;
        }