Пример #1
0
        public new StatsPaladin Clone()
        {
            StatsPaladin clone  = (StatsPaladin)this.MemberwiseClone();
            StatsPaladin retVal = new StatsPaladin();

            //
            retVal.Accumulate(base.Clone());
            //
            retVal._rawAdditivePaladinData              = (float[])clone._rawAdditivePaladinData.Clone();
            retVal._rawMultiplicativePaladinData        = (float[])clone._rawMultiplicativePaladinData.Clone();
            retVal._rawInverseMultiplicativePaladinData = (float[])clone._rawInverseMultiplicativePaladinData.Clone();
            retVal._rawNoStackPaladinData = (float[])clone._rawNoStackPaladinData.Clone();
            //
            return(retVal);
        }
        private void GetSpecialEffectsStats_Child(Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances,
            float weaponSpeed, CalculationOptionsProtPaladin calcOpts, BossOptions bossOpts, StatsPaladin stats, ref StatsPaladin statsSpecialEffects)
        {
            StatsPaladin effectsToAdd = new StatsPaladin();
            float uptime = 0f;
            foreach (SpecialEffect effect in stats.SpecialEffects()) {
                switch (effect.Trigger) {
                    case Trigger.Use: {
                        if (calcOpts.TrinketOnUseHandling != "Ignore") {
                            if (calcOpts.TrinketOnUseHandling == "Active") {
                                statsSpecialEffects.Accumulate(effect.Stats);
                            } else {
                                effectsToAdd.Clear();
                                effectsToAdd.Accumulate(effect.GetAverageStats(0f, 1f, weaponSpeed, bossOpts.BerserkTimer));
                                // Health on Use Effects are never averaged.
                                effectsToAdd.BattlemasterHealthProc = 0.0f;
                                effectsToAdd.Health = 0.0f;
                                statsSpecialEffects.Accumulate(effectsToAdd);
                            }

                            // Recursive Effects
                            foreach (SpecialEffect childEffect in effect.Stats.SpecialEffects()) {
                                effectsToAdd.Clear();
                                GetSpecialEffectsStats_Child(triggerIntervals, triggerChances, weaponSpeed, calcOpts, bossOpts, stats, ref effectsToAdd);
                                statsSpecialEffects.Accumulate(effectsToAdd, effect.GetAverageUptime(0.0f, 1.0f));
                            }
                        }
                        break;
                    }
                    case Trigger.MeleeAttack:
                    case Trigger.PhysicalAttack:
                    case Trigger.MeleeHit:
                    case Trigger.PhysicalHit:
                    case Trigger.MeleeCrit:
                    case Trigger.PhysicalCrit:
                    case Trigger.DamageSpellCrit:
                    case Trigger.DamageSpellHit:
                    case Trigger.DoTTick:
                    case Trigger.DamageOrHealingDone: // Need to add Self-Heals
                    case Trigger.DamageDone:
                    case Trigger.JudgementHit:
                    case Trigger.SpellCast:
                    case Trigger.DamageSpellCast:
                    case Trigger.DamageTaken:
                    case Trigger.DamageTakenPhysical:
                    case Trigger.DamageTakenPutsMeBelow35PercHealth:
                    case Trigger.DivineProtection:
                        if (effect.MaxStack != 1) {
                            uptime = effect.GetAverageStackSize(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], weaponSpeed, bossOpts.BerserkTimer);
                        } else {
                            uptime = effect.GetAverageUptime(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], weaponSpeed, bossOpts.BerserkTimer);
                        }
                        statsSpecialEffects.Accumulate(effect.Stats, uptime);
                        break;
                }
            }
        }
        private Stats GetSpecialEffectStats(Character character, StatsPaladin stats, CalculationOptionsProtPaladin calcOpts, BossOptions bossOpts)
        {
            StatsPaladin statsSpecialEffects = new StatsPaladin();

            float weaponSpeed = 1.0f;
            if (character.MainHand != null)
                weaponSpeed = character.MainHand.Speed;

            AttackModel am = new AttackModel(character, stats, calcOpts, bossOpts);

            Dictionary<Trigger, float> triggerIntervals;
            Dictionary<Trigger, float> triggerChances;
            CreateTriggers(am, character, stats, calcOpts, bossOpts, out triggerIntervals, out triggerChances);

            GetSpecialEffectsStats_Child(triggerIntervals, triggerChances, weaponSpeed, calcOpts, bossOpts, stats, ref statsSpecialEffects);

            // Darkmoon card greatness & Paragon procs
            // These should always increase strength, which is going to be the Paladin's top stat outside of stamina
            statsSpecialEffects.Strength += statsSpecialEffects.HighestStat + statsSpecialEffects.Paragon;
            statsSpecialEffects.HighestStat = 0;
            statsSpecialEffects.Paragon = 0;
            if (statsSpecialEffects.HighestSecondaryStat > 0) {
                float paragon = statsSpecialEffects.HighestSecondaryStat;
                statsSpecialEffects.HighestSecondaryStat = 0;
                if ((statsSpecialEffects.CritRating > statsSpecialEffects.HasteRating) && (statsSpecialEffects.CritRating > statsSpecialEffects.MasteryRating))
                    statsSpecialEffects.CritRating += paragon;
                else if ((statsSpecialEffects.HasteRating > statsSpecialEffects.CritRating) && (statsSpecialEffects.HasteRating > statsSpecialEffects.MasteryRating))
                    statsSpecialEffects.HasteRating += paragon;
                else
                    statsSpecialEffects.MasteryRating += paragon;
            }

            // Base Stats
            statsSpecialEffects.Stamina = (float)Math.Floor(statsSpecialEffects.Stamina * (1.0f + stats.BonusStaminaMultiplier));
            statsSpecialEffects.Strength = (float)Math.Floor(statsSpecialEffects.Strength * (1.0f + stats.BonusStrengthMultiplier));
            statsSpecialEffects.Agility = (float)Math.Floor(statsSpecialEffects.Agility * (1.0f + stats.BonusAgilityMultiplier));
            statsSpecialEffects.Health += (float)Math.Floor(statsSpecialEffects.Stamina * 10.0f) + (float)Math.Floor(statsSpecialEffects.BattlemasterHealthProc);

            // Defensive Stats
            statsSpecialEffects.Armor = (float)Math.Floor(statsSpecialEffects.Armor * (1f + stats.BaseArmorMultiplier + statsSpecialEffects.BaseArmorMultiplier));
            statsSpecialEffects.BonusArmor = (float)Math.Floor(statsSpecialEffects.BonusArmor * (1.0f + stats.BonusArmorMultiplier + statsSpecialEffects.BonusArmorMultiplier));
            statsSpecialEffects.Armor += statsSpecialEffects.BonusArmor;
 
            // Offensive Stats
            statsSpecialEffects.AttackPower += statsSpecialEffects.Strength * 2.0f;
            statsSpecialEffects.AttackPower = (float)Math.Floor(statsSpecialEffects.AttackPower * (1.0f + stats.BonusAttackPowerMultiplier + statsSpecialEffects.BonusAttackPowerMultiplier));

            return statsSpecialEffects;
        }
        public StatsPaladin GetCharacterStats(Character character, Item additionalItem, CalculationOptionsProtPaladin calcOpts, BossOptions bossOpts)
        {
            PaladinTalents talents = character.PaladinTalents;

            Stats statsBase = BaseStats.GetBaseStats(character.Level, CharacterClass.Paladin, character.Race);
            statsBase.Expertise += BaseStats.GetRacialExpertise(character, ItemSlot.MainHand);


            Stats statsBuffs = GetBuffsStats(character, calcOpts);
            Stats statsItems = GetItemStats(character, additionalItem, calcOpts);
            Stats statsTalents = new Stats()
            {
                BaseArmorMultiplier = talents.Toughness * 0.1f / 3f,
                BonusStaminaMultiplier = 0.15f // Touched by the Light
            };
            Stats statsGearEnchantsBuffs = new Stats();
            statsGearEnchantsBuffs.Accumulate(statsItems);
            statsGearEnchantsBuffs.Accumulate(statsBuffs);
            StatsPaladin statsTotal = new StatsPaladin();
            statsTotal.Accumulate(statsBase);
            statsTotal.Accumulate(statsItems);
            statsTotal.Accumulate(statsBuffs);
            statsTotal.Accumulate(statsTalents);

            int T11count;
            character.SetBonusCount.TryGetValue("Reinforced Sapphirium Battlearmor", out T11count);
            if (T11count >= 2) { statsTotal.BonusDamageMultiplierCrusaderStrike = 0.05f; }
            if (T11count >= 4) { statsTotal.BonusDurationMultiplierGuardianOfAncientKings = 0.50f; }
            int T12count;
            character.SetBonusCount.TryGetValue("Battlearmor of Immolation", out T12count);
            if (T12count >= 2) { statsTotal.BonusDamageShieldofRighteous = 0.20f; }
            if (T12count >= 4) {
                statsBuffs.AddSpecialEffect(new SpecialEffect(Trigger.DivineProtection,
                    new Stats() { Parry = 0.12f, },
                    10f, 60f));
            }

            statsTotal.Intellect = (float)Math.Floor(statsBase.Intellect * (1.0f + statsTalents.BonusIntellectMultiplier));
            statsTotal.Intellect += (float)Math.Floor((statsItems.Intellect + statsBuffs.Intellect) * (1.0f + statsTalents.BonusIntellectMultiplier));

            statsTotal.BaseAgility = statsBase.Agility + statsTalents.Agility;

            statsTotal.Stamina = (float)Math.Floor(statsBase.Stamina
                                    + statsItems.Stamina
                                    + statsBuffs.Stamina);
            statsTotal.Stamina = (float)Math.Floor(statsTotal.Stamina
                                    * (1.0f + statsTotal.BonusStaminaMultiplier)
                                    * (Character.ValidateArmorSpecialization(character, ItemType.Plate) ? 1.05f : 1f)); // Plate specialization

            statsTotal.Strength = (float)Math.Floor((statsBase.Strength + statsTalents.Strength) * (1.0f + statsTotal.BonusStrengthMultiplier));
            statsTotal.Strength += (float)Math.Floor((statsItems.Strength + statsBuffs.Strength) * (1.0f + statsTotal.BonusStrengthMultiplier));

            statsTotal.ParryRating += (float)Math.Floor((statsTotal.Strength - statsBase.Strength) * 0.27f);

            statsTotal.SpellPower = statsTotal.Strength * 0.60f; // Touched by the Light
            statsTotal.SpellPower += statsTotal.Intellect - 10f;

            if (talents.GlyphOfSealOfTruth && calcOpts.SealChoice == "Seal of Truth")
            {
                statsTotal.Expertise += 10.0f;
            }
            statsTotal.Agility = (float)Math.Floor((statsBase.Agility + statsTalents.Agility) * (1.0f + statsTotal.BonusAgilityMultiplier));
            statsTotal.Agility += (float)Math.Floor((statsItems.Agility + statsBuffs.Agility) * (1.0f + statsTotal.BonusAgilityMultiplier));
            statsTotal.Health += StatConversion.GetHealthFromStamina(statsTotal.Stamina, CharacterClass.Paladin);

            statsTotal.Health *= 1f + statsTotal.BonusHealthMultiplier;
            statsTotal.Mana += StatConversion.GetManaFromIntellect(statsTotal.Intellect, CharacterClass.Paladin) * (1f + statsTotal.BonusManaMultiplier);

            // Armor
            statsTotal.Armor  = (float)Math.Floor(statsTotal.Armor * (1f + statsTotal.BaseArmorMultiplier));
            statsTotal.Armor += (float)Math.Floor(statsTotal.BonusArmor * (1f + statsTotal.BonusArmorMultiplier));

            statsTotal.AttackPower += ((statsTotal.Strength - 10f) * 2f);
            statsTotal.AttackPower = (float)Math.Floor(statsTotal.AttackPower * (1f + statsTotal.BonusAttackPowerMultiplier));
            statsTotal.NatureResistance += statsTotal.NatureResistanceBuff;
            statsTotal.FireResistance += statsTotal.FireResistanceBuff;
            statsTotal.FrostResistance += statsTotal.FrostResistanceBuff;
            statsTotal.ShadowResistance += statsTotal.ShadowResistanceBuff;
            statsTotal.ArcaneResistance += statsTotal.ArcaneResistanceBuff;
            //statsTotal.BonusCritDamageMultiplier = statsBase.BonusCritDamageMultiplier + statsGearEnchantsBuffs.BonusCritDamageMultiplier;
            statsTotal.CritRating = statsBase.CritRating + statsGearEnchantsBuffs.CritRating;
            statsTotal.ExpertiseRating = statsBase.ExpertiseRating + statsGearEnchantsBuffs.ExpertiseRating;
            statsTotal.HasteRating = statsBase.HasteRating + statsGearEnchantsBuffs.HasteRating;
            statsTotal.HitRating = statsBase.HitRating + statsGearEnchantsBuffs.HitRating;
            statsTotal.MasteryRating = statsBase.MasteryRating + statsGearEnchantsBuffs.MasteryRating;
            statsTotal.BlockRating = statsBase.BlockRating + statsGearEnchantsBuffs.BlockRating;
            statsTotal.WeaponDamage += Lookup.WeaponDamage(character, statsTotal.AttackPower, false);
            //statsTotal.ExposeWeakness = statsBase.ExposeWeakness + statsGearEnchantsBuffs.ExposeWeakness; // Nerfed in 3.1

            // Calculate Procs and Special Effects
            statsTotal.Accumulate(GetSpecialEffectStats(character, statsTotal, calcOpts, bossOpts));

            return statsTotal;
        }
Пример #5
0
 public void Accumulate(StatsPaladin data, float weight)
 {
     #region Base
     if (data.sparseIndices != null)
     {
         int i = 0;
         for (int a = 0; a < data.sparseAdditiveCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawAdditiveData[index] += weight * data.rawAdditiveData[index];
         }
         for (int a = 0; a < data.sparseMultiplicativeCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawMultiplicativeData[index] = (1 + rawMultiplicativeData[index]) * (1 + weight * data.rawMultiplicativeData[index]) - 1;
         }
         for (int a = 0; a < data.sparseInverseMultiplicativeCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawInverseMultiplicativeData[index] = 1 - (1 - rawInverseMultiplicativeData[index]) * (1 - weight * data.rawInverseMultiplicativeData[index]);
         }
         for (int a = 0; a < data.sparseNoStackCount; a++, i++)
         {
             int   index = data.sparseIndices[i];
             float value = weight * data.rawNoStackData[index];
             if (value > rawNoStackData[index])
             {
                 rawNoStackData[index] = value;
             }
         }
     }
     else
     {
         float[] add = data.rawAdditiveData;
         for (int i = 0; i < rawAdditiveData.Length; i++)
         {
             rawAdditiveData[i] += weight * add[i];
         }
         add = data.rawMultiplicativeData;
         for (int i = 0; i < rawMultiplicativeData.Length; i++)
         {
             rawMultiplicativeData[i] = (1 + rawMultiplicativeData[i]) * (1 + weight * add[i]) - 1;
         }
         add = data.rawInverseMultiplicativeData;
         for (int i = 0; i < rawInverseMultiplicativeData.Length; i++)
         {
             rawInverseMultiplicativeData[i] = 1 - (1 - rawInverseMultiplicativeData[i]) * (1 - weight * add[i]);
         }
         add = data.rawNoStackData;
         for (int i = 0; i < rawNoStackData.Length; i++)
         {
             if (weight * add[i] > rawNoStackData[i])
             {
                 rawNoStackData[i] = weight * add[i];
             }
         }
     }
     #endregion
     #region Paladin
     if (data._sparseIndicesPaladin != null)
     {
         int i = 0;
         for (int a = 0; a < data._sparseAdditivePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawAdditivePaladinData[index] += weight * data._rawAdditivePaladinData[index];
         }
         for (int a = 0; a < data._sparseMultiplicativePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawMultiplicativePaladinData[index] = (1 + _rawMultiplicativePaladinData[index]) * (1 + weight * data._rawMultiplicativePaladinData[index]) - 1;
         }
         for (int a = 0; a < data._sparseInverseMultiplicativePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawInverseMultiplicativePaladinData[index] = 1 - (1 - _rawInverseMultiplicativePaladinData[index]) * (1 - weight * data._rawInverseMultiplicativePaladinData[index]);
         }
         for (int a = 0; a < data._sparseNoStackPaladinCount; a++, i++)
         {
             int   index = data._sparseIndicesPaladin[i];
             float value = weight * data._rawNoStackPaladinData[index];
             if (value > _rawNoStackPaladinData[index])
             {
                 _rawNoStackPaladinData[index] = value;
             }
         }
     }
     else
     {
         float[] add = data._rawAdditivePaladinData;
         for (int i = 0; i < _rawAdditivePaladinData.Length; i++)
         {
             _rawAdditivePaladinData[i] += weight * add[i];
         }
         add = data._rawMultiplicativePaladinData;
         for (int i = 0; i < _rawMultiplicativePaladinData.Length; i++)
         {
             _rawMultiplicativePaladinData[i] = (1 + _rawMultiplicativePaladinData[i]) * (1 + weight * add[i]) - 1;
         }
         add = data._rawInverseMultiplicativePaladinData;
         for (int i = 0; i < _rawInverseMultiplicativePaladinData.Length; i++)
         {
             _rawInverseMultiplicativePaladinData[i] = 1 - (1 - _rawInverseMultiplicativePaladinData[i]) * (1 - weight * add[i]);
         }
         add = data._rawNoStackPaladinData;
         for (int i = 0; i < _rawNoStackPaladinData.Length; i++)
         {
             if (weight * add[i] > _rawNoStackPaladinData[i])
             {
                 _rawNoStackPaladinData[i] = weight * add[i];
             }
         }
     }
     #endregion
     if (data._rawSpecialEffectDataSize > 0)
     {
         EnsureSpecialEffectCapacity(_rawSpecialEffectDataSize + data._rawSpecialEffectDataSize);
         Array.Copy(data._rawSpecialEffectData, 0, _rawSpecialEffectData, _rawSpecialEffectDataSize, data._rawSpecialEffectDataSize);
         _rawSpecialEffectDataSize += data._rawSpecialEffectDataSize;
     }
 }
Пример #6
0
 public void Accumulate(StatsPaladin data, float weight)
 {
     #region Base
     if (data.sparseIndices != null)
     {
         int i = 0;
         for (int a = 0; a < data.sparseAdditiveCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawAdditiveData[index] += weight * data.rawAdditiveData[index];
         }
         for (int a = 0; a < data.sparseMultiplicativeCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawMultiplicativeData[index] = (1 + rawMultiplicativeData[index]) * (1 + weight * data.rawMultiplicativeData[index]) - 1;
         }
         for (int a = 0; a < data.sparseInverseMultiplicativeCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             rawInverseMultiplicativeData[index] = 1 - (1 - rawInverseMultiplicativeData[index]) * (1 - weight * data.rawInverseMultiplicativeData[index]);
         }
         for (int a = 0; a < data.sparseNoStackCount; a++, i++)
         {
             int index = data.sparseIndices[i];
             float value = weight * data.rawNoStackData[index];
             if (value > rawNoStackData[index]) rawNoStackData[index] = value;
         }
     }
     else
     {
         float[] add = data.rawAdditiveData;
         for (int i = 0; i < rawAdditiveData.Length; i++)
         {
             rawAdditiveData[i] += weight * add[i];
         }
         add = data.rawMultiplicativeData;
         for (int i = 0; i < rawMultiplicativeData.Length; i++)
         {
             rawMultiplicativeData[i] = (1 + rawMultiplicativeData[i]) * (1 + weight * add[i]) - 1;
         }
         add = data.rawInverseMultiplicativeData;
         for (int i = 0; i < rawInverseMultiplicativeData.Length; i++)
         {
             rawInverseMultiplicativeData[i] = 1 - (1 - rawInverseMultiplicativeData[i]) * (1 - weight * add[i]);
         }
         add = data.rawNoStackData;
         for (int i = 0; i < rawNoStackData.Length; i++)
         {
             if (weight * add[i] > rawNoStackData[i]) rawNoStackData[i] = weight * add[i];
         }
     }
     #endregion
     #region Paladin
     if (data._sparseIndicesPaladin != null)
     {
         int i = 0;
         for (int a = 0; a < data._sparseAdditivePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawAdditivePaladinData[index] += weight * data._rawAdditivePaladinData[index];
         }
         for (int a = 0; a < data._sparseMultiplicativePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawMultiplicativePaladinData[index] = (1 + _rawMultiplicativePaladinData[index]) * (1 + weight * data._rawMultiplicativePaladinData[index]) - 1;
         }
         for (int a = 0; a < data._sparseInverseMultiplicativePaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             _rawInverseMultiplicativePaladinData[index] = 1 - (1 - _rawInverseMultiplicativePaladinData[index]) * (1 - weight * data._rawInverseMultiplicativePaladinData[index]);
         }
         for (int a = 0; a < data._sparseNoStackPaladinCount; a++, i++)
         {
             int index = data._sparseIndicesPaladin[i];
             float value = weight * data._rawNoStackPaladinData[index];
             if (value > _rawNoStackPaladinData[index]) _rawNoStackPaladinData[index] = value;
         }
     }
     else
     {
         float[] add = data._rawAdditivePaladinData;
         for (int i = 0; i < _rawAdditivePaladinData.Length; i++)
         {
             _rawAdditivePaladinData[i] += weight * add[i];
         }
         add = data._rawMultiplicativePaladinData;
         for (int i = 0; i < _rawMultiplicativePaladinData.Length; i++)
         {
             _rawMultiplicativePaladinData[i] = (1 + _rawMultiplicativePaladinData[i]) * (1 + weight * add[i]) - 1;
         }
         add = data._rawInverseMultiplicativePaladinData;
         for (int i = 0; i < _rawInverseMultiplicativePaladinData.Length; i++)
         {
             _rawInverseMultiplicativePaladinData[i] = 1 - (1 - _rawInverseMultiplicativePaladinData[i]) * (1 - weight * add[i]);
         }
         add = data._rawNoStackPaladinData;
         for (int i = 0; i < _rawNoStackPaladinData.Length; i++)
         {
             if (weight * add[i] > _rawNoStackPaladinData[i]) _rawNoStackPaladinData[i] = weight * add[i];
         }
     }
     #endregion
     if (data._rawSpecialEffectDataSize > 0)
     {
         EnsureSpecialEffectCapacity(_rawSpecialEffectDataSize + data._rawSpecialEffectDataSize);
         Array.Copy(data._rawSpecialEffectData, 0, _rawSpecialEffectData, _rawSpecialEffectDataSize, data._rawSpecialEffectDataSize);
         _rawSpecialEffectDataSize += data._rawSpecialEffectDataSize;
     }
 }
Пример #7
0
 public new StatsPaladin Clone() {
     StatsPaladin clone = (StatsPaladin)this.MemberwiseClone();
     StatsPaladin retVal = new StatsPaladin();
     //
     retVal.Accumulate(base.Clone());
     //
     retVal._rawAdditivePaladinData = (float[])clone._rawAdditivePaladinData.Clone();
     retVal._rawMultiplicativePaladinData = (float[])clone._rawMultiplicativePaladinData.Clone();
     retVal._rawInverseMultiplicativePaladinData = (float[])clone._rawInverseMultiplicativePaladinData.Clone();
     retVal._rawNoStackPaladinData = (float[])clone._rawNoStackPaladinData.Clone();
     //
     return retVal;
 }