Esempio n. 1
0
        private static void AccumulateProcs(Character character, StatsBear statsTotal)
        {
            CalculationOptionsBear calcOpts = character.CalculationOptions as CalculationOptionsBear ?? new CalculationOptionsBear();
            BossOptions bossOpts = character.BossOptions;
            if (bossOpts.Attacks.Count < 1) { bossOpts.Attacks.Add(BossHandler.ADefaultMeleeAttack); bossOpts.Attacks[0].IsTheDefaultMelee = true; bossOpts.DamagingTargs = true; }
            if (bossOpts.DefaultMeleeAttack == null) { bossOpts.Attacks.Add(BossHandler.ADefaultMeleeAttack); bossOpts.Attacks[bossOpts.Attacks.Count-1].IsTheDefaultMelee = true; bossOpts.DamagingTargs = true; }
            Attack bossAttack = bossOpts.DefaultMeleeAttack;
            int targetLevel = bossOpts.Level;
            float fightDuration = bossOpts.BerserkTimer;

            float hasteBonus = StatConversion.GetHasteFromRating(statsTotal.HasteRating, CharacterClass.Druid);
            float playerHastedAttackSpeed = (2.5f / (1f + hasteBonus)) / (1f + statsTotal.PhysicalHaste);
            float meleeHitInterval = 1f / (1f / playerHastedAttackSpeed + 1f / 1.5f);

            int levelDifference = (bossOpts.Level - character.Level);
            float hitBonus = StatConversion.GetPhysicalHitFromRating(statsTotal.HitRating) + statsTotal.PhysicalHit;
            float expertiseBonus = StatConversion.GetDodgeParryReducFromExpertise(StatConversion.GetExpertiseFromRating(statsTotal.ExpertiseRating, CharacterClass.Druid) + statsTotal.Expertise, CharacterClass.Druid);
            float chanceDodge = Math.Max(0f, StatConversion.WHITE_DODGE_CHANCE_CAP[levelDifference] - expertiseBonus);
            float chanceParry = Math.Max(0f, StatConversion.WHITE_PARRY_CHANCE_CAP[levelDifference] - expertiseBonus);
            float chanceMiss = Math.Max(0f, StatConversion.WHITE_MISS_CHANCE_CAP[levelDifference] - hitBonus);
            float chanceAvoided = chanceMiss + chanceDodge + chanceParry;

            float rawChanceCrit = StatConversion.GetPhysicalCritFromRating(statsTotal.CritRating, CharacterClass.Druid)
                                + StatConversion.GetPhysicalCritFromAgility(statsTotal.Agility, CharacterClass.Druid)
                                + statsTotal.PhysicalCrit
                                + StatConversion.NPC_LEVEL_CRIT_MOD[levelDifference];
            float chanceCrit = rawChanceCrit * (1f - chanceAvoided);
            float chanceHit = 1f - chanceAvoided;

            float levelDifferenceAvoidance = levelDifference * 0.002f;
            float baseAgi = character.Race == CharacterRace.NightElf ? 87 : 77;

            //float defSkill = (float)Math.Floor(StatConversion.GetDefenseFromRating(statsTotal.DefenseRating, CharacterClass.Druid));
            float dodgeNonDR = statsTotal.Dodge - levelDifferenceAvoidance + StatConversion.GetDodgeFromAgility(baseAgi, CharacterClass.Druid);
            float missNonDR = statsTotal.Miss - levelDifferenceAvoidance;
            float dodgePreDR = StatConversion.GetDodgeFromAgility(statsTotal.Agility - baseAgi, CharacterClass.Druid)
                             + StatConversion.GetDodgeFromRating(statsTotal.DodgeRating, CharacterClass.Druid)
                             /*+ defSkill * StatConversion.DEFENSE_RATING_AVOIDANCE_MULTIPLIER / 100f*/;
            float missPreDR = 0f;// (defSkill * StatConversion.DEFENSE_RATING_AVOIDANCE_MULTIPLIER / 100f);
            float dodgePostDR = 0.01f / (1f / 116.890707f + 0.00972f / dodgePreDR);
            float missPostDR = 0.01f / (1f / 16f + 0.00972f / missPreDR);
            float dodgeTotal = dodgeNonDR + dodgePostDR;
            float missTotal = missNonDR + missPostDR;

            float TargAttackSpeed = bossAttack.AttackSpeed / (1f - statsTotal.BossAttackSpeedReductionMultiplier);

            Stats statsProcs = new Stats();
            //float uptime;
            foreach (SpecialEffect effect in statsTotal.SpecialEffects())
            {
                switch (effect.Trigger)
                {
                    case Trigger.Use:
                        effect.AccumulateAverageStats(statsProcs, 0f, 1f, 2.5f, fightDuration);
                        break;
                    case Trigger.MeleeHit:
                    case Trigger.PhysicalHit:
                        effect.AccumulateAverageStats(statsProcs, meleeHitInterval, chanceHit, 2.5f, fightDuration);
                        break;
                    case Trigger.MeleeAttack:
                    case Trigger.PhysicalAttack:
                        if (effect.Stats.MoteOfAnger > 0) {
                            // When in effect stats, MoteOfAnger is % of melee hits
                            // When in character stats, MoteOfAnger is average procs per second
                            statsProcs.MoteOfAnger = effect.Stats.MoteOfAnger * effect.GetAverageProcsPerSecond(meleeHitInterval, 1f, 2.5f, fightDuration) / effect.MaxStack;
                        } else {
                            effect.AccumulateAverageStats(statsProcs, meleeHitInterval, 1f, 2.5f, fightDuration);
                        }
                        break;
                    case Trigger.MeleeCrit:
                    case Trigger.PhysicalCrit:
                        effect.AccumulateAverageStats(statsProcs, meleeHitInterval, chanceCrit, 2.5f, fightDuration);
                        break;
                    case Trigger.DoTTick:
                        effect.AccumulateAverageStats(statsProcs, 3f, 1f, 2.5f, fightDuration);
                        break;
                    case Trigger.DamageDone:
                        effect.AccumulateAverageStats(statsProcs, meleeHitInterval / 2f, 1f, 2.5f, fightDuration);
                        break;
                    case Trigger.DamageOrHealingDone:
                        effect.AccumulateAverageStats(statsProcs, meleeHitInterval / 2f, 1f, 2.5f, fightDuration); // also needs healing
                        break;
                    case Trigger.MangleBearHit:
                        effect.AccumulateAverageStats(statsProcs, 6f - statsTotal.MangleCooldownReduction, chanceHit, 2.5f, fightDuration);
                        break;
                    case Trigger.MangleCatOrShredOrInfectedWoundsHit:
                        effect.AccumulateAverageStats(statsProcs, 1f /
                            (1f / (6f - statsTotal.MangleCooldownReduction) + //Mangles Per Second
                            1f / meleeHitInterval) //Mauls Per Second
                            , chanceHit, 2.5f, fightDuration);
                        break;
                    case Trigger.SwipeBearOrLacerateHit:
                        effect.AccumulateAverageStats(statsProcs, 2.25f, chanceHit, 2.5f, fightDuration);
                        break;
                    case Trigger.LacerateTick:
                        effect.AccumulateAverageStats(statsProcs, 3f, 1f, 2.5f, fightDuration);
                        break;
                    case Trigger.DamageTakenPutsMeBelow35PercHealth:
                        effect.AccumulateAverageStats(statsProcs, TargAttackSpeed * 0.8f, (1f - 0.8f * (dodgeTotal + missTotal)) * 0.35f, fightDuration); //Assume you get hit by other things, like dots, aoes, etc, making you get targeted with damage 35% more often than the boss, and half the hits you take are unavoidable.
                        break;
                    case Trigger.DamageTakenPutsMeBelow50PercHealth:
                        effect.AccumulateAverageStats(statsProcs, TargAttackSpeed * 0.8f, (1f - 0.8f * (dodgeTotal + missTotal)) * 0.50f, fightDuration); //Assume you get hit by other things, like dots, aoes, etc, making you get targeted with damage 50% more often than the boss, and half the hits you take are unavoidable.
                        break;
                    case Trigger.DamageTaken:
                        effect.AccumulateAverageStats(statsProcs, TargAttackSpeed * 0.8f, 1f - 0.8f * (dodgeTotal + missTotal), fightDuration); //Assume you get hit by other things, like dots, aoes, etc, making you get targeted with damage 25% more often than the boss, and half the hits you take are unavoidable.
                        break;
                    case Trigger.DamageTakenPhysical:
                        effect.AccumulateAverageStats(statsProcs, TargAttackSpeed, 1f - (dodgeTotal + missTotal), fightDuration); //Assume you get hit by other things, like dots, aoes, etc, making you get targeted with damage 25% more often than the boss, and half the hits you take are unavoidable.
                        break;
                    case Trigger.Barkskin:
                        effect.AccumulateAverageStats(statsProcs, 60f, 1f, 0f, fightDuration);
                        break;
                    case Trigger.Berserk:
                        effect.AccumulateAverageStats(statsProcs, 180f, 1, 0f, fightDuration);
                        break;
                }
            }

            statsProcs.Agility += statsProcs.HighestStat + statsProcs.Paragon;
            statsProcs.Stamina = (float)Math.Floor(statsProcs.Stamina * (1f + statsTotal.BonusStaminaMultiplier));
            statsProcs.Strength = (float)Math.Floor(statsProcs.Strength * (1f + statsTotal.BonusStrengthMultiplier));
            statsProcs.Agility = (float)Math.Floor(statsProcs.Agility * (1f + statsTotal.BonusAgilityMultiplier));
            statsProcs.AttackPower += statsProcs.Strength + statsProcs.Agility * 2f;
            statsProcs.AttackPower = (float)Math.Floor(statsProcs.AttackPower * (1f + statsTotal.BonusAttackPowerMultiplier));
            statsProcs.Health += (float)Math.Floor(statsProcs.Stamina * 14f) + (float)Math.Floor(statsProcs.BattlemasterHealthProc);
            statsProcs.Health *= (1f + statsProcs.BonusHealthMultiplier);
            statsProcs.Armor += /*2f * (float)Math.Floor(statsProcs.Agility)*/ + statsProcs.BonusArmor; // Armor no longer gets bonuses from Agi in Cata
            statsProcs.Armor = (float)Math.Floor(statsProcs.Armor * (1f + statsTotal.BonusArmorMultiplier));
            if (statsProcs.HighestSecondaryStat > 0) {
                if (statsTotal.CritRating > statsTotal.HasteRating && statsTotal.CritRating > statsTotal.MasteryRating) {
                    statsProcs.CritRating += statsProcs.HighestSecondaryStat; // this will be invalidated after this, but I'm at least putting it in for now
                }
                else if (statsTotal.HasteRating > statsTotal.CritRating && statsTotal.HasteRating > statsTotal.MasteryRating) {
                    statsProcs.HasteRating += statsProcs.HighestSecondaryStat;
                }
                else if (statsTotal.MasteryRating > statsTotal.CritRating && statsTotal.MasteryRating > statsTotal.HasteRating) {
                    statsProcs.MasteryRating += statsProcs.HighestSecondaryStat;
                }
                statsProcs.HighestSecondaryStat = 0;
            }

            statsTotal.Accumulate(statsProcs);
        }