示例#1
0
        public RotationViewer(CalculationOptionsTankDK opts, Character ch)
        {
            InitializeComponent();
            this.calcOpts  = opts;
            this.rotation  = calcOpts.m_Rotation;
            this.character = ch.Clone();
            talents        = character.DeathKnightTalents;

            txtBS.KeyUp         += new KeyEventHandler(txtBS_KeyUp);
            txtDC.KeyUp         += new KeyEventHandler(txtDC_KeyUp);
            txtDuration.KeyUp   += new KeyEventHandler(txtDuration_KeyUp);
            txtFS.KeyUp         += new KeyEventHandler(txtFS_KeyUp);
            txtHB.KeyUp         += new KeyEventHandler(txtHB_KeyUp);
            txtHS.KeyUp         += new KeyEventHandler(txtHS_KeyUp);
            txtIT.KeyUp         += new KeyEventHandler(txtIT_KeyUp);
            txtNumDisease.KeyUp += new KeyEventHandler(txtNumDisease_KeyUp);
            txtOblit.KeyUp      += new KeyEventHandler(txtOblit_KeyUp);
            txtPS.KeyUp         += new KeyEventHandler(txtPS_KeyUp);
            txtSS.KeyUp         += new KeyEventHandler(txtSS_KeyUp);
            txtPest.KeyUp       += new KeyEventHandler(txtPest_KeyUp);
            txtUptime.KeyUp     += new KeyEventHandler(txtUptime_KeyUp);
            txtDS.KeyUp         += new KeyEventHandler(txtDS_KeyUp);
            txtHoW.KeyUp        += new KeyEventHandler(txtHoW_KeyUp);
            txtRS.KeyUp         += new KeyEventHandler(txtRS_KeyUp);
            txtBB.KeyUp         += new KeyEventHandler(txtBB_KeyUp);
            txtDnD.KeyUp        += new KeyEventHandler(txtDnD_KeyUp);

            UpdateStrikes();
        }
示例#2
0
        private void btnRotation_Click(object sender, EventArgs e)
        {
            CalculationOptionsTankDK calcOpts = Character.CalculationOptions as CalculationOptionsTankDK;
            RotationViewer           RV       = new RotationViewer(calcOpts, Character);

            RV.ShowDialog();
            Character.OnCalculationsInvalidated();
        }
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null) Character.CalculationOptions = new CalculationOptionsTankDK();
     calcOpts = Character.CalculationOptions as CalculationOptionsTankDK;
     // Model Specific Code
     //
     _loadingCalculationOptions = false;
 }
示例#4
0
        public CombatTable2(Character c, Stats stats, CharacterCalculationsTankDK calcs, CalculationOptionsTankDK calcOpts)
        {
            if (calcOpts.bExperimental)
            {
                this.m_CState = new CombatState();
                if (c != null)
                {
                    if (c.DeathKnightTalents == null)
                    {
                        c.DeathKnightTalents = new DeathKnightTalents();
                    }
                    this.m_CState.m_Talents = (DeathKnightTalents)c.DeathKnightTalents.Clone();
                }
                this.m_CState.m_Stats = stats.Clone();
                m_Calcs = calcs;
                m_Opts  = calcOpts;
                this.m_CState.m_NumberOfTargets = (float)m_Opts.uNumberTargets;
                m_Rotation = calcOpts.m_Rotation;

                //TODO: Handle Expertise
                if (c.MainHand != null && c.MainHand.Item.Type != ItemType.None)
                {
                    m_CState.MH = new Weapon(c.MainHand.Item, m_CState.m_Stats, m_Opts, 0);
                    m_CState.OH = null;
                    if (c.MainHand.Slot != ItemSlot.TwoHand)
                    {
                        if (c.OffHand != null && c.OffHand.Item.Type != ItemType.None)
                        {
                            m_CState.OH = new Weapon(c.OffHand.Item, this.m_CState.m_Stats, m_Opts, 0);
                        }
                    }
                }
                else
                {
                    m_CState.MH = null;
                    m_CState.OH = null;
                }

                // Checking the rotation:
                if (m_Rotation.IcyTouch == 0 &&
                    m_Rotation.PlagueStrike == 0 &&
                    m_Rotation.BloodStrike == 0)
                {
                    // Then this is probably a null rotation, and
                    // so let's build one?
                    m_Rotation = new Rotation(this.m_CState.m_Talents);
                }

                BuildRotation();

                // TODO: move this out of the constructor
                CompileRotation(m_Rotation);
            }
        }
 public void LoadCalculationOptions()
 {
     _loadingCalculationOptions = true;
     if (Character.CalculationOptions == null)
     {
         Character.CalculationOptions = new CalculationOptionsTankDK();
     }
     calcOpts = Character.CalculationOptions as CalculationOptionsTankDK;
     // Model Specific Code
     //
     _loadingCalculationOptions = false;
 }
示例#6
0
        public void WeaponConstructorTest()
        {
            // Weapon takes an item object.  
            // Refactor idea is for it to inherit from Item.
            Item i = new Item("Weapon Test", ItemQuality.Common, ItemType.OneHandMace, 101, null, ItemSlot.MainHand, null, false, null, null, ItemSlot.None, ItemSlot.None, ItemSlot.None, 10, 20, ItemDamageType.Physical, 2.0f, null);  
            Stats stats = new Stats();
            stats.Stamina = 100;
            CalculationOptionsTankDK calcOpts = new CalculationOptionsTankDK();
//            calcOpts.talents = new DeathKnightTalents();
//            float expertise = 0F; 
//            Weapon target = new Weapon(i, stats, calcOpts, expertise);
//            Assert.IsNotNull(target);
//            Assert.AreNotEqual(0, target.baseDamage, "basedamage");
//            Assert.AreNotEqual(0, target.damage, "adjusted damage");
//            Assert.AreNotEqual(0, target.DPS, "DPS");
        }
示例#7
0
文件: Weapon.cs 项目: tsebalj1/rawr
        /// <summary>
        ///
        /// </summary>
        /// <param name="i">The item that represents the weapon in use</param>
        /// <param name="stats">Character stats</param>
        /// <param name="calcOpts">The calculation Options.</param>
        /// <param name="expertise">Expertise by racial weapon specialization</param>
        public Weapon(Item i, Stats stats, CalculationOptionsTankDK calcOpts, float expertise)
        {
            if (stats == null || calcOpts == null || calcOpts.talents == null)
            {
                // Missing necessary pieces.
                return;
            }

            if (i == null)
            {
                i           = new Item();
                i.Speed     = 2f;
                i.MinDamage = 0;
                i.MaxDamage = 0;
            }

            // Ensure that the weapon that does damage has some sort of speed associated.
            if ((i.MinDamage > 0 || i.MaxDamage > 0) && i.Speed == 0)
            {
                i.Speed = 2f;
#if DEBUG
                throw new Exception("No Speed on Item.");
#endif
            }

            effectiveExpertise = stats.Expertise;
            float fightDuration = calcOpts.FightLength * 60f;

            if (i == null)
            {
                return;
            }

            baseSpeed  = i.Speed;
            baseDamage = (float)(i.MinDamage + i.MaxDamage) / 2f + stats.WeaponDamage;


            #region Attack Speed
            {
                // TODO: make sure we're not double counting haste.
                hastedSpeed  = baseSpeed / (1f + (StatConversion.GetHasteFromRating(stats.HasteRating, CharacterClass.DeathKnight)) + stats.PhysicalHaste);
                hastedSpeed /= 1f + 0.05f * (float)calcOpts.talents.ImprovedIcyTalons;

                if (calcOpts.Bloodlust)
                {
                    // TODO: Update this bloodlust value to be a special effect
                    //float bloodlustUptime = (calcOpts.Bloodlust * 40f);

                    //if (bloodlustUptime > fightDuration) bloodlustUptime = 1f;
                    //else bloodlustUptime /= fightDuration;

                    float numLust     = fightDuration % 300f; // bloodlust changed in 3.0, can only have one every 5 minutes.
                    float fullLustDur = (numLust - 1) * 300f + 40f;
                    if (fightDuration < fullLustDur)          // if the last lust doesn't go its full duration
                    {
                        float lastLustFraction = (fullLustDur - fightDuration) / 40f;
                        numLust -= 1f;
                        numLust += lastLustFraction;
                    }

                    float bloodlustUptime = (numLust * 40f) / fightDuration;

                    hastedSpeed /= 1f + (0.3f * bloodlustUptime);
                }
            }
            #endregion

            #region Dodge
            {
                chanceDodged = StatConversion.WHITE_DODGE_CHANCE_CAP[calcOpts.TargetLevel - 80];
                // Changing this to use the statconversion formula like Target Dodge%;
                chanceDodged -= StatConversion.GetDodgeParryReducFromExpertise(stats.Expertise);
                if (chanceDodged < 0f)
                {
                    chanceDodged = 0f;
                }
            }
            #endregion

            #region White Damage
            {
                // To do, this operation needs to be moved out into it's own space.
                // There's no reason it should sit in the constructor only.
                // White damage per hit.  Basic white hits are use elsewhere.
                damage = baseDamage + (stats.AttackPower / 14f) * baseSpeed;
                DPS    = 0f;
                if (hastedSpeed > 0)
                {
                    DPS = damage / hastedSpeed;
                }
            }
            #endregion
        }
示例#8
0
        public void TankDK_BuildAcceptance()
        {
            Rawr.TankDK.CalculationsTankDK CalcTankDK = new Rawr.TankDK.CalculationsTankDK();

            CalculationOptionsTankDK calcOpts = new CalculationOptionsTankDK();
            m_char.CalculationOptions = calcOpts;
            this.testContextInstance.BeginTimer("GetCalc");
            CharacterCalculationsBase calcs = CalcTankDK.GetCharacterCalculations(m_char);
            calcs.GetCharacterDisplayCalculationValues();
            this.testContextInstance.EndTimer("GetCalc");
        }
示例#9
0
        public void TankDK_OverallCheck()
        {
            Rawr.TankDK.CalculationsTankDK CalcTankDK = new Rawr.TankDK.CalculationsTankDK();
            CalculationOptionsTankDK calcOpts = new CalculationOptionsTankDK();
            m_char.CalculationOptions = calcOpts;
            Item additionalItem = new Item("TestItem", ItemQuality.Common, ItemType.None, 102010, "", ItemSlot.Back, "", false,
                new Stats(), null,
                ItemSlot.None, ItemSlot.None, ItemSlot.None,
                0, 0, ItemDamageType.Physical, 0, "");

            CharacterCalculationsTankDK calcs = CalcTankDK.GetCharacterCalculations(m_char) as CharacterCalculationsTankDK;
            float OValueBase = calcs.OverallPoints;
            float[] SValueBase = calcs.SubPoints;

            // Setup the stats on what we want.
            additionalItem.Stats.Stamina = 5000;
            calcs = CalcTankDK.GetCharacterCalculations(m_char, additionalItem) as CharacterCalculationsTankDK;
            float OValueStam = calcs.OverallPoints;
            float[] SValueStam = calcs.SubPoints;
            additionalItem.Stats.Stamina = 0;
            Assert.IsTrue(OValueBase < OValueStam, "Stamina");
            
            additionalItem.Stats.DodgeRating = 5000;
            calcs = CalcTankDK.GetCharacterCalculations(m_char, additionalItem) as CharacterCalculationsTankDK;
            float OValueDodge = calcs.OverallPoints;
            float[] SValueDodge = calcs.SubPoints;
            additionalItem.Stats.DodgeRating = 0;

            additionalItem.Stats.DodgeRating = 10000;
            calcs = CalcTankDK.GetCharacterCalculations(m_char, additionalItem) as CharacterCalculationsTankDK;
            float OValueDodge2 = calcs.OverallPoints;
            float[] SValueDodge2 = calcs.SubPoints;
            additionalItem.Stats.DodgeRating = 0;
            Assert.IsTrue(OValueDodge < OValueDodge2, "Dodge2");
            Assert.IsTrue(SValueBase[0] < SValueDodge[0], "Dodge1"); // Due to inverse scaling between Burst & Avoidance, only check Mitigation improvement.

            additionalItem.Stats.ParryRating = 5000;
            calcs = CalcTankDK.GetCharacterCalculations(m_char, additionalItem) as CharacterCalculationsTankDK;
            float OValueParry = calcs.OverallPoints;
            float[] SValueParry = calcs.SubPoints;
            additionalItem.Stats.ParryRating = 0;
            Assert.IsTrue(SValueBase[0] < SValueParry[0], "Parry"); // Due to inverse scaling between Burst & Avoidance, only check Mitigation improvement.
            
            additionalItem.Stats.MasteryRating = 5000;
            calcs = CalcTankDK.GetCharacterCalculations(m_char, additionalItem) as CharacterCalculationsTankDK;
            float OValueMastery = calcs.OverallPoints;
            float[] SValueMastery = calcs.SubPoints;
            additionalItem.Stats.MasteryRating = 0;
            Assert.IsTrue(OValueBase < OValueMastery, "Mastery");
            
        }
示例#10
0
        public void TankDK_Rotation()
        {
            Rawr.TankDK.CharacterCalculationsTankDK CalcTankDK = new Rawr.TankDK.CharacterCalculationsTankDK();
            CalculationOptionsTankDK calcOpts = new CalculationOptionsTankDK();
            Rawr.DK.StatsDK TotalStats = new Rawr.DK.StatsDK();

            Rawr.DPSDK.CharacterCalculationsDPSDK DPSCalcs = new Rawr.DPSDK.CharacterCalculationsDPSDK();
            Rawr.DPSDK.CalculationOptionsDPSDK DPSopts = new Rawr.DPSDK.CalculationOptionsDPSDK();

            Rawr.DK.DKCombatTable ct = new Rawr.DK.DKCombatTable(m_char, TotalStats, DPSCalcs, DPSopts, m_char.BossOptions);
            Rawr.DK.Rotation rot = new Rawr.DK.Rotation(ct, false);
            rot.PRE_BloodDiseased();
            Assert.IsTrue(rot.m_TPS > 0, "rotation BloodDiseased produces 0 DPS");
        }
示例#11
0
        public Stats getSpecialEffects(CalculationOptionsTankDK calcOpts, SpecialEffect effect)
        {
            Stats    statsAverage = new Stats();
            Rotation rRotation    = calcOpts.m_Rotation;

            if (effect.Trigger == Trigger.Use)
            {
                if (calcOpts.bUseOnUseAbilities == true)
                {
                    statsAverage.Accumulate(effect.GetAverageStats());
                }
            }
            else
            {
                float trigger             = 0f;
                float chance              = effect.Chance;
                float duration            = effect.Duration;
                float unhastedAttackSpeed = 2f;
                switch (effect.Trigger)
                {
                case Trigger.MeleeCrit:
                case Trigger.PhysicalCrit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    chance              = combatTable.physCrits * effect.Chance;
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.MeleeHit:
                case Trigger.PhysicalHit:
                    trigger             = (1f / (rRotation.getMeleeSpecialsPerSecond() * (combatTable.m_bDW ? 2 : 1))) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.CurrentHandHit:
                case Trigger.MainHandHit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.MH.hastedSpeed != 0 ? 1f / combatTable.MH.hastedSpeed : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.OffHandHit:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.OH.hastedSpeed != 0 ? 1f / combatTable.OH.hastedSpeed : 0.5f);
                    chance              = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    break;

                case Trigger.DamageDone:
                case Trigger.DamageOrHealingDone:
                    trigger             = (1f / rRotation.getMeleeSpecialsPerSecond()) + (combatTable.combinedSwingTime != 0 ? 1f / combatTable.combinedSwingTime : 0.5f);
                    unhastedAttackSpeed = (combatTable.MH != null ? combatTable.MH.baseSpeed : 2.0f);
                    chance = effect.Chance * (1f - (combatTable.missedSpecial + combatTable.dodgedSpecial));
                    break;

                case Trigger.DamageSpellCast:
                case Trigger.SpellCast:
                case Trigger.DamageSpellHit:
                case Trigger.SpellHit:
                    trigger = 1f / rRotation.getSpellSpecialsPerSecond();
                    chance  = 1f - combatTable.spellResist;
                    break;

                case Trigger.DamageSpellCrit:
                case Trigger.SpellCrit:
                    trigger = 1f / rRotation.getSpellSpecialsPerSecond();
                    chance  = combatTable.spellCrits * effect.Chance;
                    break;

                case Trigger.DoTTick:
                    trigger = (rRotation.BloodPlague + rRotation.FrostFever) / 3;
                    break;

                case Trigger.DamageTaken:
                case Trigger.DamageTakenPhysical:
                    trigger             = calcOpts.BossAttackSpeed;
                    chance             *= 1f - (stats.Dodge + stats.Parry + stats.Miss);
                    unhastedAttackSpeed = calcOpts.BossAttackSpeed;
                    break;

                case Trigger.DamageTakenMagical:
                    trigger = calcOpts.IncomingFromMagicFrequency;
                    break;

                //////////////////////////////////
                // DK specific triggers:
                case Trigger.BloodStrikeHit:
                case Trigger.HeartStrikeHit:
                    trigger = rRotation.curRotationDuration / (rRotation.BloodStrike + rRotation.HeartStrike);
                    break;

                case Trigger.PlagueStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.PlagueStrike;
                    break;

                case Trigger.RuneStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.RuneStrike;
                    break;

                case Trigger.IcyTouchHit:
                    trigger = rRotation.curRotationDuration / rRotation.IcyTouch;
                    break;

                case Trigger.DeathStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.DeathStrike;
                    break;

                case Trigger.ObliterateHit:
                    trigger = rRotation.curRotationDuration / rRotation.Obliterate;
                    break;

                case Trigger.ScourgeStrikeHit:
                    trigger = rRotation.curRotationDuration / rRotation.ScourgeStrike;
                    break;

                case Trigger.FrostFeverHit:
                    // Icy Talons triggers off this.
                    trigger = rRotation.curRotationDuration / rRotation.IcyTouch;
                    if (character.DeathKnightTalents.GlyphofHowlingBlast)
                    {
                        trigger += rRotation.curRotationDuration / rRotation.HowlingBlast;
                    }
                    break;
                }
                if (!float.IsInfinity(trigger) && !float.IsNaN(trigger))
                {
                    if (effect.UsesPPM())
                    {
                        // If effect.chance < 0 , then it's using PPM.
                        // Let's get the duration * how many times it procs per min:
                        float UptimePerMin = 0;
                        float fWeight      = 0;
                        if (duration == 0) // Duration of 0 means that it's a 1 time effect that procs every time the proc comes up.
                        {
                            fWeight = Math.Abs(effect.Chance) / 60;
                        }
                        else
                        {
                            UptimePerMin = duration * Math.Abs(effect.Chance);
                            fWeight      = UptimePerMin / 60;
                        }
                        statsAverage.Accumulate(effect.Stats, fWeight);
                    }
                    else
                    {
                        effect.AccumulateAverageStats(statsAverage, trigger, chance, unhastedAttackSpeed, calcOpts.FightLength * 60);
                    }
                }
            }
            return(statsAverage);
        }