示例#1
0
 public CombatStats(Character character, Stats stats, CalculationOptionsEnhance calcOpts, BossOptions bossOpts)
 {
     _stats          = stats;
     _character      = character;
     _calcOpts       = calcOpts;
     _bossOpts       = bossOpts;
     _talents        = _character.ShamanTalents;
     fightLength     = _bossOpts.BerserkTimer;
     levelDifference = _bossOpts.Level - _character.Level;
     if (levelDifference > 3)
     {
         levelDifference = 3;
     }
     else if (levelDifference < 0)
     {
         levelDifference = 0;
     }
     whiteCritDepression  = StatConversion.NPC_LEVEL_CRIT_MOD[levelDifference]; // 0.03f + 0.006f * levelDifference;
     yellowCritDepression = StatConversion.NPC_LEVEL_CRIT_MOD[levelDifference]; // 0.006f * levelDifference;
     UpdateCalcs(true);
     SetManaRegen();
     _rotation = new Priorities(this, _calcOpts, _bossOpts, _character, _stats, _talents);
     _rotation.CalculateAbilities();
     UpdateCalcs(false); // second pass to revise calcs based on new ability cooldowns
 }
示例#2
0
 public Priorities(CombatStats cs, CalculationOptionsEnhance calcOpts, Character character, Stats stats, ShamanTalents talents)
 {
     _cs         = cs;
     _calcOpts   = calcOpts;
     _character  = character;
     _stats      = stats;
     _talents    = talents;
     fightLength = _calcOpts.FightLength * 60f;
     _abilities  = SetupAbilities();
 }
示例#3
0
 public CombatFactors(ShamanTalents talents, Stats stats, int additionalTargets, float latencyCast, float latencyGcd, bool useFireNova, bool useChainLightning, bool useDpsFireTotem)
 {
     Talents = talents;
     Stats = stats;
     AdditionalTargets = additionalTargets;
     LatencyCast = latencyCast;
     LatencyGCD = latencyGcd;
     UseFireNova = useFireNova;
     UseChainLightning = useChainLightning;
     UseDpsFireTotem = useDpsFireTotem;
 }
示例#4
0
 public CombatFactors(ShamanTalents talents, Stats stats, int additionalTargets, float latencyCast, float latencyGcd, bool useFireNova, bool useChainLightning, bool useDpsFireTotem)
 {
     Talents           = talents;
     Stats             = stats;
     AdditionalTargets = additionalTargets;
     LatencyCast       = latencyCast;
     LatencyGCD        = latencyGcd;
     UseFireNova       = useFireNova;
     UseChainLightning = useChainLightning;
     UseDpsFireTotem   = useDpsFireTotem;
 }
示例#5
0
        /// <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);
        }
示例#6
0
        public TalentsBase TalentSpec()
        {
            if (Spec == null)
            {
                return(null);
            }
            TalentsBase spec;

            if (Class == CharacterClass.DeathKnight)
            {
                spec = new DeathKnightTalents(Spec);
            }
            else if (Class == CharacterClass.Warrior)
            {
                spec = new WarriorTalents(Spec);
            }
            else if (Class == CharacterClass.Paladin)
            {
                spec = new PaladinTalents(Spec);
            }
            else if (Class == CharacterClass.Shaman)
            {
                spec = new ShamanTalents(Spec);
            }
            else if (Class == CharacterClass.Hunter)
            {
                spec = new HunterTalents(Spec);
            }
            else if (Class == CharacterClass.Rogue)
            {
                spec = new RogueTalents(Spec);
            }
            else if (Class == CharacterClass.Druid)
            {
                spec = new DruidTalents(Spec);
            }
            else if (Class == CharacterClass.Warlock)
            {
                spec = new WarlockTalents(Spec);
            }
            else if (Class == CharacterClass.Priest)
            {
                spec = new PriestTalents(Spec);
            }
            else
            {
                spec = new MageTalents(Spec);
            }
            return(spec);
        }
示例#7
0
        /// <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);
        }
示例#8
0
        //slowly being moved back into GetCharacterStats to reduce Stats
        public Stats GetTalentStats(ShamanTalents talents)
        {
            Stats statsTalents = new Stats()
            {
                #region Elemental
                SpellHit = .01f * talents.ElementalPrecision,
                #endregion
                #region Enhancement
                BonusIntellectMultiplier = .02f * talents.AncestralKnowledge,
                PhysicalCrit             = .01f * talents.ThunderingStrikes,
                SpellCrit = 0.01f * talents.ThunderingStrikes,
                #endregion
                #region Glyphs
                SpellPower = talents.GlyphofTotemofWrath ? talents.TotemOfWrath * 84 : 0
                             #endregion
            };

            return(statsTalents);
        }
示例#9
0
文件: Rotation.cs 项目: tsebalj1/rawr
        public Rotation(ShamanTalents talents, SpellBox spellBox, IRotationOptions rotOpt)
            : this()
        {
            Talents = talents;
            LB      = spellBox.LB;
            CL      = spellBox.CL;
            LvB     = spellBox.LvB;
            LvBFS   = spellBox.LvBFS;
            FS      = spellBox.FS;
            ES      = spellBox.ES;
            FrS     = spellBox.FrS;
            FN      = spellBox.FN;
            ST      = spellBox.ST;
            MT      = spellBox.MT;
            FE      = spellBox.FE;

            useDpsFireTotem = rotOpt.UseDpsFireTotem;

            CalculateRotation(rotOpt.UseFireNova, rotOpt.UseChainLightning, rotOpt.UseDpsFireTotem, rotOpt.UseFireEle);
        }
示例#10
0
 public CombatStats(Character character, Stats stats, CalculationOptionsEnhance calcOpts)
 {
     _stats          = stats;
     _character      = character;
     _calcOpts       = calcOpts;
     _talents        = _character.ShamanTalents;
     fightLength     = _calcOpts.FightLength * 60f;
     levelDifference = _calcOpts.TargetLevel - _character.Level;
     if (levelDifference > 3)
     {
         levelDifference = 3;
     }
     if (levelDifference < 0)
     {
         levelDifference = 0;
     }
     whiteCritDepression  = 0.03f + 0.006f * levelDifference;
     yellowCritDepression = 0.006f * levelDifference;
     SetManaRegen();
     UpdateCalcs(true);
     _rotation = new Priorities(this, _calcOpts, _character, _stats, _talents);
     _rotation.CalculateAbilities();
     UpdateCalcs(false); // second pass to revise calcs based on new ability cooldowns
 }
示例#11
0
        public Rotation(ShamanTalents talents, SpellBox spellBox, IRotationOptions rotOpt)
            : this()
        {
            Talents = talents;
            LB = spellBox.LB;
            CL = spellBox.CL;
            LvB = spellBox.LvB;
            LvBFS = spellBox.LvBFS;
            FS = spellBox.FS;
            ES = spellBox.ES;
            FrS = spellBox.FrS;
            FN = spellBox.FN;
            ST = spellBox.ST;
            MT = spellBox.MT;
            FE = spellBox.FE;
            FrS = spellBox.FrS;

            useDpsFireTotem = rotOpt.UseDpsFireTotem;

            CalculateRotation(rotOpt.UseFireNova, rotOpt.UseChainLightning, rotOpt.UseDpsFireTotem, rotOpt.UseFireEle);
        }
示例#12
0
 public CombatFactors(ShamanTalents talents, Stats stats, int additionalTargets, float latencyCast, float latencyGcd) : this(talents, stats, additionalTargets, latencyCast, latencyGcd, true, true, false)
 {
 }
示例#13
0
 public static bool HasTalent(ShamanTalents tal)
 {
     return TalentManager.IsSelected((int)tal);
 }
示例#14
0
 public CombatStats(Character character, Stats stats, CalculationOptionsEnhance calcOpts, BossOptions bossOpts)
 {
     _stats = stats;
     _character = character;
     _calcOpts = calcOpts;
     _bossOpts = bossOpts;
     _talents = _character.ShamanTalents;
     fightLength = _bossOpts.BerserkTimer;
     levelDifference = _bossOpts.Level - _character.Level;
     if (levelDifference > 3) levelDifference = 3;
     else if (levelDifference < 0) levelDifference = 0;
     whiteCritDepression = StatConversion.NPC_LEVEL_CRIT_MOD[levelDifference];// 0.03f + 0.006f * levelDifference;
     yellowCritDepression = StatConversion.NPC_LEVEL_CRIT_MOD[levelDifference];// 0.006f * levelDifference;
     UpdateCalcs(true);
     SetManaRegen();
     _rotation = new Priorities(this, _calcOpts, _bossOpts, _character, _stats, _talents);
     _rotation.CalculateAbilities();
     UpdateCalcs(false); // second pass to revise calcs based on new ability cooldowns
 }
示例#15
0
 public static bool HasTalent(ShamanTalents tal)
 {
     return(TalentManager.IsSelected((int)tal));
 }
示例#16
0
        TalentsBase parse_talents_wowhead(CharacterClass characterclass, string talent_string)
        {
            // wowhead format: [tree_1]Z[tree_2]Z[tree_3] where the trees are character encodings
            // each character expands to a pair of numbers [0-5][0-5]
            // unused deeper talents are simply left blank instead of filling up the string with zero-zero encodings

            bool hasGlyphs = talent_string.Contains(":");

            int[] talent_trees = new int[] { 0, 0, 0 };
            int[] glyph_trees  = new int[] { 3, 3, 3 };

            switch (characterclass)
            {
            case CharacterClass.Warrior:     { WarriorTalents talents = new WarriorTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Paladin:     { PaladinTalents talents = new PaladinTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Hunter:      { HunterTalents talents = new HunterTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Rogue:       { RogueTalents talents = new RogueTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Priest:      { PriestTalents talents = new PriestTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.DeathKnight: { DeathKnightTalents talents = new DeathKnightTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Shaman:      { ShamanTalents talents = new ShamanTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Mage:        { MageTalents talents = new MageTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Warlock:     { WarlockTalents talents = new WarlockTalents(); talent_trees = talents.TreeLengths; break; }

            case CharacterClass.Druid:       { DruidTalents talents = new DruidTalents(); talent_trees = talents.TreeLengths; break; }
            }

            int[]   encoding      = new int[talent_trees[0] + talent_trees[1] + talent_trees[2]];
            int[][] glyphEncoding = new int[][] {
                new int[3],
                new int[3],
                new int[3],
            };
            int[] tree_count  = new int[] { 0, 0, 0 };
            int[] glyph_count = new int[] { 0, 0, 0 };

            int tree  = 0;
            int count = 0;

            #region Talents parsing
            for (int i = 1; i < talent_string.Length; i++)
            {
                if (tree >= 3)
                {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                    return(null);
                }

                char c = talent_string[i];

                if (c == ':')
                {
                    break;           // glyph encoding follows
                }
                if (c == 'Z')
                {
                    count = 0;
                    for (int j = 0; j <= tree; j++)
                    {
                        count += talent_trees[tree];
                    }
                    tree++;
                    continue;
                }

                decode_t decode = null;
                for (int j = 0; decoding[j].key != '\0' && decode == null; j++)
                {
                    if (decoding[j].key == c)
                    {
                        decode = decoding[j];
                    }
                }

                if (decode == null)
                {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                    return(null);
                }

                encoding[count++] += decode.first - '0';
                tree_count[tree]  += 1;

                if (tree_count[tree] < talent_trees[tree])
                {
                    encoding[count++] += decode.second - '0';
                    tree_count[tree]  += 1;
                }

                if (tree_count[tree] >= talent_trees[tree])
                {
                    tree++;
                }
            }
            #endregion

            #region Glyphs Parsing
            #region Notes

            /* This is totally crappy....
             * Glyphs do not follow the same parsing rules. If you apply what was there for talents directly
             * to glyphs you get 1202032213120011050000000000000000. Which should only have 1's and 0's
             *
             *
             * Warriors: As I'm checking glyphs, here's what I get:
             * == PRIMES ==
             *   Link                           decode  id       Name
             * * http://www.wowhead.com/talent#L:0 00 43415 58388 Devastate
             * * http://www.wowhead.com/talent#L:z 01 43416 58367 Bloodthirst
             * * http://www.wowhead.com/talent#L:M 02 43421 58368 Mortal Strike
             * * http://www.wowhead.com/talent#L:c 03 43422 58386 Overpower
             * * http://www.wowhead.com/talent#L:m 04 43423 58385 Slam
             * * http://www.wowhead.com/talent#L:V 05 43424 58364 Revenge
             * * http://www.wowhead.com/talent#L:o 10 43425 58375 Shield Slam
             * * http://www.wowhead.com/talent#L:k 11 43432 58370 Raging Blow
             * * http://www.wowhead.com/talent#L:R 12 45790 63324 Bladestorm
             * == MAJORS ==
             * * http://www.wowhead.com/talent#L:0 00 43397 Long Charge
             * * http://www.wowhead.com/talent#L:z 01 43399 Thunder Clap
             * * http://www.wowhead.com/talent#L:M 02 43413 Rapid Charge
             * * http://www.wowhead.com/talent#L:c 03 43414 Cleaving
             * * http://www.wowhead.com/talent#L:m 04 43417 Piercing Howl
             * * http://www.wowhead.com/talent#L:V 05 43418 Heroic Throw
             * * http://www.wowhead.com/talent#L:o 10 43419 Intervene
             * * http://www.wowhead.com/talent#L:k 11 43427 Sunder Armor
             * * http://www.wowhead.com/talent#L:R 12 43428 Sweeping Strikes
             * * http://www.wowhead.com/talent#L:s 13 43430 Resonating Power
             * * http://www.wowhead.com/talent#L:a 14 43431 Victory Rush
             * * http://www.wowhead.com/talent#L:q 15 45792 Shockwave
             * * http://www.wowhead.com/talent#L:b 20 45795 Spell Reflection
             * * http://www.wowhead.com/talent#L:d 21 45797 Shield Wall
             * * http://www.wowhead.com/talent#L:r 22 63481 Colossus Smash
             * * http://www.wowhead.com/talent#L:f 23 67482 Intercept
             * * http://www.wowhead.com/talent#L:w 24 67483 Death Wish
             * == MINORS ==
             * * http://www.wowhead.com/talent#L:0 00 43395 Battle
             * * http://www.wowhead.com/talent#L:z 01 43396 Berserker Rage
             * * http://www.wowhead.com/talent#L:M 02 43398 Demoralizing Shout
             * * http://www.wowhead.com/talent#L:c 03 43400 Enduring Victory
             * * http://www.wowhead.com/talent#L:m 04 43412 Bloody Healing
             * * http://www.wowhead.com/talent#L:V 05 45793 Furious Sundering
             * * http://www.wowhead.com/talent#L:o 10 45794 Intimidating Shout
             * * http://www.wowhead.com/talent#L:k 11 49084 Command
             *
             * So http://www.wowhead.com/talent#LubcfRMRurkcrZ0b:RMcrsR0kV would mean:
             *   Prime: Bladestorm, Mortal Strike, Overpower
             *   Major: Colossus Smash, Resonating Power, Sweeping Strikes
             *   Minor: Battle, Command, Furious Sundering
             * Which is correct, that's what we come out to
             */
            #endregion

            tree  = 0;
            count = 0;

            if (hasGlyphs)
            {
                for (int i = talent_string.IndexOf(":") + 1; i < talent_string.Length; i++)
                {
                    if (tree >= 3)
                    {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                        return(null);
                    }

                    char c = talent_string[i];

                    if (c == 'Z')
                    {
                        count = 0;

                        /*for (int j = 0; j <= tree; j++) {
                         *  count += glyph_trees[tree];
                         * }*/
                        tree++;
                        continue;
                    }

                    decode_t decode = null;
                    for (int j = 0; decoding[j].key != '\0' && decode == null; j++)
                    {
                        if (decoding[j].key == c)
                        {
                            decode = decoding[j];
                        }
                    }

                    if (decode == null)
                    {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                        return(null);
                    }

                    glyphEncoding[tree][count++] += (decode.first - '0') * 10 + decode.second - '0';
                    glyph_count[tree]            += 1;

                    if (glyph_count[tree] >= (glyph_trees[tree]))
                    {
                        tree++; count = 0;
                    }
                }
            }
            #endregion

            string newtalentstring = "";
            foreach (int i in encoding)
            {
                newtalentstring += i.ToString();
            }
            if (hasGlyphs)
            {
                //newtalentstring += ".";
                //for (int t = 0; t < 3; t++) {
                //    foreach (int i in glyphEncoding[t]) { newtalentstring += i.ToString(); }
                //}
            }

            switch (characterclass)
            {
            case CharacterClass.Warrior: { return(new WarriorTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Paladin: { return(new PaladinTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Hunter: { return(new HunterTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Rogue: { return(new RogueTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Priest: { return(new PriestTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.DeathKnight: { return(new DeathKnightTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Shaman: { return(new ShamanTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Mage: { return(new MageTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Warlock: { return(new WarlockTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }

            case CharacterClass.Druid: { return(new DruidTalents(newtalentstring, hasGlyphs ? glyphEncoding : null)); }
            }
            return(null);
        }
示例#17
0
        TalentsBase parse_talents_wowhead(CharacterClass characterclass, string talent_string)
        {
            // wowhead format: [tree_1]Z[tree_2]Z[tree_3] where the trees are character encodings
            // each character expands to a pair of numbers [0-5][0-5]
            // unused deeper talents are simply left blank instead of filling up the string with zero-zero encodings

            bool hasGlyphs = talent_string.Contains(":");

            int[] talent_trees = new int[] { 0, 0, 0 };
            int[] glyph_trees = new int[] { 3, 3, 3 };

            switch (characterclass)
            {
                case CharacterClass.Warrior:     { WarriorTalents talents = new WarriorTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Paladin:     { PaladinTalents talents = new PaladinTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Hunter:      { HunterTalents talents = new HunterTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Rogue:       { RogueTalents talents = new RogueTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Priest:      { PriestTalents talents = new PriestTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.DeathKnight: { DeathKnightTalents talents = new DeathKnightTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Shaman:      { ShamanTalents talents = new ShamanTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Mage:        { MageTalents talents = new MageTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Warlock:     { WarlockTalents talents = new WarlockTalents(); talent_trees = talents.TreeLengths; break; }
                case CharacterClass.Druid:       { DruidTalents talents = new DruidTalents(); talent_trees = talents.TreeLengths; break; }
            }

            int[] encoding = new int[talent_trees[0] + talent_trees[1] + talent_trees[2]];
            int[][] glyphEncoding = new int[][] {
                new int[3],
                new int[3],
                new int[3],
            };
            int[] tree_count = new int[] { 0, 0, 0 };
            int[] glyph_count = new int[] { 0, 0, 0 };

            int tree = 0;
            int count = 0;

            #region Talents parsing
            for (int i=1; i < talent_string.Length; i++) {
                if (tree >= 3) {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                    return null;
                }

                char c = talent_string[i];

                if (c == ':') break; // glyph encoding follows
 
                if (c == 'Z') {
                    count = 0;
                    for (int j = 0; j <= tree; j++) {
                        count += talent_trees[tree];
                    }
                    tree++;
                    continue;
                }

                decode_t decode = null;
                for (int j=0; decoding[j].key != '\0' && decode==null; j++) {
                    if (decoding[j].key == c) { decode = decoding[j]; }
                }

                if (decode == null) {
                    //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                    return null;
                }

                encoding[count++] += decode.first - '0';
                tree_count[tree] += 1;

                if (tree_count[tree] < talent_trees[tree]) {
                    encoding[count++] += decode.second - '0';
                    tree_count[tree] += 1;
                }

                if (tree_count[tree] >= talent_trees[tree]) {
                    tree++;
                }
            }
            #endregion

            #region Glyphs Parsing
            #region Notes
            /* This is totally crappy....
             * Glyphs do not follow the same parsing rules. If you apply what was there for talents directly
             * to glyphs you get 1202032213120011050000000000000000. Which should only have 1's and 0's
             * 
             * 
             * Warriors: As I'm checking glyphs, here's what I get:
             * == PRIMES ==
             *   Link                           decode  id       Name
            * * http://www.wowhead.com/talent#L:0 00 43415 58388 Devastate
            * * http://www.wowhead.com/talent#L:z 01 43416 58367 Bloodthirst
            * * http://www.wowhead.com/talent#L:M 02 43421 58368 Mortal Strike
            * * http://www.wowhead.com/talent#L:c 03 43422 58386 Overpower
            * * http://www.wowhead.com/talent#L:m 04 43423 58385 Slam
            * * http://www.wowhead.com/talent#L:V 05 43424 58364 Revenge
            * * http://www.wowhead.com/talent#L:o 10 43425 58375 Shield Slam
            * * http://www.wowhead.com/talent#L:k 11 43432 58370 Raging Blow
            * * http://www.wowhead.com/talent#L:R 12 45790 63324 Bladestorm
             * == MAJORS ==
             * * http://www.wowhead.com/talent#L:0 00 43397 Long Charge
             * * http://www.wowhead.com/talent#L:z 01 43399 Thunder Clap
             * * http://www.wowhead.com/talent#L:M 02 43413 Rapid Charge
             * * http://www.wowhead.com/talent#L:c 03 43414 Cleaving
             * * http://www.wowhead.com/talent#L:m 04 43417 Piercing Howl
             * * http://www.wowhead.com/talent#L:V 05 43418 Heroic Throw
             * * http://www.wowhead.com/talent#L:o 10 43419 Intervene
             * * http://www.wowhead.com/talent#L:k 11 43427 Sunder Armor
             * * http://www.wowhead.com/talent#L:R 12 43428 Sweeping Strikes
             * * http://www.wowhead.com/talent#L:s 13 43430 Resonating Power
             * * http://www.wowhead.com/talent#L:a 14 43431 Victory Rush
             * * http://www.wowhead.com/talent#L:q 15 45792 Shockwave
             * * http://www.wowhead.com/talent#L:b 20 45795 Spell Reflection
             * * http://www.wowhead.com/talent#L:d 21 45797 Shield Wall
             * * http://www.wowhead.com/talent#L:r 22 63481 Colossus Smash
             * * http://www.wowhead.com/talent#L:f 23 67482 Intercept
             * * http://www.wowhead.com/talent#L:w 24 67483 Death Wish
             * == MINORS ==
             * * http://www.wowhead.com/talent#L:0 00 43395 Battle
             * * http://www.wowhead.com/talent#L:z 01 43396 Berserker Rage
             * * http://www.wowhead.com/talent#L:M 02 43398 Demoralizing Shout
             * * http://www.wowhead.com/talent#L:c 03 43400 Enduring Victory
             * * http://www.wowhead.com/talent#L:m 04 43412 Bloody Healing
             * * http://www.wowhead.com/talent#L:V 05 45793 Furious Sundering
             * * http://www.wowhead.com/talent#L:o 10 45794 Intimidating Shout
             * * http://www.wowhead.com/talent#L:k 11 49084 Command
             * 
             * So http://www.wowhead.com/talent#LubcfRMRurkcrZ0b:RMcrsR0kV would mean:
             *   Prime: Bladestorm, Mortal Strike, Overpower
             *   Major: Colossus Smash, Resonating Power, Sweeping Strikes
             *   Minor: Battle, Command, Furious Sundering
             * Which is correct, that's what we come out to
             */
            #endregion

            tree = 0;
            count = 0;

            if (hasGlyphs) {
                for (int i=talent_string.IndexOf(":")+1; i < talent_string.Length; i++) {
                    if (tree >= 3) {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Too many talent trees specified.\n", name() );
                        return null;
                    }

                    char c = talent_string[i];

                    if (c == 'Z') {
                        count = 0;
                        /*for (int j = 0; j <= tree; j++) {
                            count += glyph_trees[tree];
                        }*/
                        tree++;
                        continue;
                    }

                    decode_t decode = null;
                    for (int j=0; decoding[j].key != '\0' && decode==null; j++) {
                        if (decoding[j].key == c) { decode = decoding[j]; }
                    }

                    if (decode == null) {
                        //sim -> errorf( "Player %s has malformed wowhead talent string. Translation for '%c' unknown.\n", name(), c );
                        return null;
                    }

                    glyphEncoding[tree][count++] += (decode.first - '0') * 10 + decode.second - '0';
                    glyph_count[tree] += 1;

                    if (glyph_count[tree] >= (glyph_trees[tree])) { tree++; count = 0; }
                }
            }
            #endregion

            string newtalentstring = "";
            foreach (int i in encoding) { newtalentstring += i.ToString(); }
            if (hasGlyphs) {
                //newtalentstring += ".";
                //for (int t = 0; t < 3; t++) {
                //    foreach (int i in glyphEncoding[t]) { newtalentstring += i.ToString(); }
                //}
            }

            switch (characterclass)
            {
                case CharacterClass.Warrior: { return new WarriorTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Paladin: { return new PaladinTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Hunter: { return new HunterTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Rogue: { return new RogueTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Priest: { return new PriestTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.DeathKnight: { return new DeathKnightTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Shaman: { return new ShamanTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Mage: { return new MageTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Warlock: { return new WarlockTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
                case CharacterClass.Druid: { return new DruidTalents(newtalentstring, hasGlyphs ? glyphEncoding : null); }
            }
            return null;
        }
示例#18
0
        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();
        }
示例#19
0
 public CombatFactors(ShamanTalents talents, Stats stats, int additionalTargets, float latencyCast, float latencyGcd) : this(talents, stats, additionalTargets, latencyCast, latencyGcd, true, true, false)
 {
 }