private float ApplySpecialEffect(SpecialEffect effect, DPSWarrCharacter charStruct, Dictionary<Trigger, float> triggerIntervals, Dictionary<Trigger, float> triggerChances, ref Base.StatsWarrior applyTo) { #if DEBUG //ConstructionCounts["ApplySpecialEffect"]++; #endif float fightDuration = charStruct.BossOpts.BerserkTimer; float fightDuration2Pass = charStruct.CalcOpts.SE_UseDur ? fightDuration : 0; Stats effectStats = effect.Stats; float upTime = 0f; //float avgStack = 1f; /*if (effect.Stats.TargetArmorReduction > 0f || effect.Stats.ArmorPenetrationRating > 0f) { //int j = 0; }*/ if (effect.Trigger == Trigger.Use) { if (effect.Stats._rawSpecialEffectDataSize == 1) { upTime = effect.GetAverageUptime(0f, 1f, charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass); //float uptime = (effect.Cooldown / fightDuration); List<SpecialEffect> nestedEffect = new List<SpecialEffect>(); nestedEffect.Add(effect.Stats._rawSpecialEffectData[0]); Base.StatsWarrior _stats2 = new Base.StatsWarrior(); ApplySpecialEffect(effect.Stats._rawSpecialEffectData[0], charStruct, triggerIntervals, triggerChances, ref _stats2); effectStats = _stats2; } else { upTime = effect.GetAverageStackSize(0f, 1f, charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass); } } else if (effect.Duration == 0f && triggerIntervals.ContainsKey(effect.Trigger) && !float.IsInfinity(triggerIntervals[effect.Trigger])) { upTime = effect.GetAverageProcsPerSecond(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass); } else if (effect.Trigger == Trigger.ExecuteHit) { upTime = effect.GetAverageStackSize(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass * (float)charStruct.BossOpts.Under20Perc); } else if (triggerIntervals.ContainsKey(effect.Trigger) && !float.IsInfinity(triggerIntervals[effect.Trigger])) { upTime = effect.GetAverageStackSize(triggerIntervals[effect.Trigger], triggerChances[effect.Trigger], charStruct.CombatFactors.CMHItemSpeed, fightDuration2Pass); } if (upTime > 0f) { if (effect.Duration == 0f) { applyTo.Accumulate(effectStats, upTime * fightDuration); } else if (upTime <= effect.MaxStack) { applyTo.Accumulate(effectStats, upTime); } return upTime; } return 0f; }
private void DoSpecialEffects(DPSWarrCharacter charStruct, List<SpecialEffect> bersMainHand, List<SpecialEffect> bersOffHand, Base.StatsWarrior statsTotal) { #if DEBUG //ConstructionCounts["DoSpecialEffects"]++; #endif #region Initialize Triggers Dictionary<Trigger, float> triggerIntervals = new Dictionary<Trigger, float>(); Dictionary<Trigger, float> triggerChances = new Dictionary<Trigger, float>(); CalculateTriggers(charStruct, triggerIntervals, triggerChances); #endregion #region ArPen Lists /*List<float> tempArPenRatings = new List<float>(); List<float> tempArPenRatingsCapLimited = new List<float>(); List<float> tempArPenRatingUptimes = new List<float>(); List<SpecialEffect> tempArPenEffects = new List<SpecialEffect>(); List<float> tempArPenEffectIntervals = new List<float>(); List<float> tempArPenEffectChances = new List<float>(); List<float> tempArPenEffectScales = new List<float>();*/ #endregion // First Let's add InnerRage in, because that affects other calcs if (charStruct.CalcOpts.M_InnerRage) { AbilityWrapper ir = charStruct.Rot.GetWrapper<Skills.InnerRage>(); statsTotal.Accumulate(((ir.Ability as Skills.InnerRage).Effect.Stats as Base.StatsWarrior), (ir.Ability as Skills.InnerRage).Effect.GetAverageUptime(0f, 1.00f)); } List<SpecialEffect> critEffects = new List<SpecialEffect>(); List<SpecialEffect> firstPass = new List<SpecialEffect>(); List<SpecialEffect> secondPass = new List<SpecialEffect>(); List<SpecialEffect> thirdPass = new List<SpecialEffect>(); //bool doubleExecutioner = false; foreach (SpecialEffect effect in statsTotal.SpecialEffects()) { effect.Stats.GenerateSparseData(); if (!triggerIntervals.ContainsKey(effect.Trigger)) continue; else if (effect.Stats.CritRating > 0f) { critEffects.Add(effect); } #region ArP Proc (which don't exist anymore) /*else if (effect.Stats.ArmorPenetrationRating > 0f) { if (doubleExecutioner) continue; Trigger realTrigger; if (bersMainHand.Contains(effect)) { bersMainHand.Remove(effect); doubleExecutioner = true; if (bersOffHand.Contains(effect)) { bersOffHand.Remove(effect); realTrigger = Trigger.MeleeHit; } else realTrigger = Trigger.MainHandHit; } else if (bersOffHand.Contains(effect)) { bersOffHand.Remove(effect); realTrigger = Trigger.OffHandHit; } else realTrigger = effect.Trigger; tempArPenEffects.Add(effect); tempArPenEffectIntervals.Add(triggerIntervals[realTrigger]); tempArPenEffectChances.Add(triggerChances[realTrigger]); tempArPenEffectScales.Add(1f); }*/ #endregion else if (!bersMainHand.Contains(effect) && !bersOffHand.Contains(effect) && (effect.Stats.Agility > 0f || effect.Stats.HasteRating > 0f || effect.Stats.HitRating > 0f || effect.Stats.CritRating > 0f || effect.Stats.MasteryRating > 0f || effect.Stats.PhysicalHaste > 0f || effect.Stats.PhysicalCrit > 0f || effect.Stats.PhysicalHit > 0f)) { // These procs affect rotation firstPass.Add(effect); } else if (!bersMainHand.Contains(effect) && !bersOffHand.Contains(effect) && (effect.Stats.FireDamage > 0 || effect.Stats.FireDamage > 0f || effect.Stats.NatureDamage > 0f || effect.Stats.ShadowDamage > 0f || effect.Stats.HolyDamage > 0f || effect.Stats.ArcaneDamage > 0f)) { // It's a Special Damage Proc thirdPass.Add(effect); } else if (!bersMainHand.Contains(effect) && !bersOffHand.Contains(effect)) { // Any other stat proc secondPass.Add(effect); } } #region ArP Proc Cap handling /*if (tempArPenEffects.Count == 0) { //tempArPenRatings.Add(0.0f); //tempArPenRatingUptimes.Add(1.0f); } else if (tempArPenEffects.Count == 1) { //Only one, add it to SpecialEffect effect = tempArPenEffects[0]; float uptime = effect.GetAverageStackSize(tempArPenEffectIntervals[0], tempArPenEffectChances[0], charStruct.combatFactors.CmhItemSpeed, (charStruct.calcOpts.SE_UseDur ? charStruct.bossOpts.BerserkTimer : 0f)) * tempArPenEffectScales[0]; tempArPenRatings.Add(effect.Stats.ArmorPenetrationRating); tempArPenRatingUptimes.Add(uptime); tempArPenRatings.Add(0.0f); tempArPenRatingUptimes.Add(1.0f - uptime); } else if (tempArPenEffects.Count > 1) { //if (tempArPenEffects.Count >= 2) //{ // offset[0] = calcOpts.TrinketOffset; //} WeightedStat[] arPenWeights = SpecialEffect.GetAverageCombinedUptimeCombinations(tempArPenEffects.ToArray(), tempArPenEffectIntervals.ToArray(), tempArPenEffectChances.ToArray(), new float[tempArPenEffectChances.Count], tempArPenEffectScales.ToArray(), charStruct.combatFactors.CmhItemSpeed, charStruct.bossOpts.BerserkTimer, AdditiveStat.ArmorPenetrationRating); for (int i = 0; i < arPenWeights.Length; i++) { tempArPenRatings.Add(arPenWeights[i].Value); tempArPenRatingUptimes.Add(arPenWeights[i].Chance); } }*/ // Get the average Armor Pen Rating across all procs /*if (tempArPenRatings.Count > 0f) { Stats originalStats = charStruct.combatFactors.StatS; int LevelDif = charStruct.bossOpts.Level- charStruct.Char.Level; float arpenBuffs = 0.0f; //float OriginalArmorReduction = StatConversion.GetArmorDamageReduction(charStruct.Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif], originalStats.TargetArmorReduction, arpenBuffs, Math.Max(0f, originalStats.ArmorPenetrationRating)); float AverageArmorPenRatingsFromProcs = 0f; float tempCap = StatConversion.RATING_PER_ARMORPENETRATION - StatConversion.GetRatingFromArmorPenetration(arpenBuffs); for (int i = 0; i < tempArPenRatings.Count; i++) { tempArPenRatingsCapLimited.Add(Math.Max(0f, Math.Min(tempCap - originalStats.ArmorPenetrationRating, tempArPenRatings[i]))); //float bah = StatConversion.GetArmorDamageReduction(charStruct.Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif], originalStats.TargetArmorReduction, arpenBuffs, Math.Max(0f, originalStats.ArmorPenetrationRating + tempArPenRatingsCapLimited[i])); AverageArmorPenRatingsFromProcs += tempArPenRatingUptimes[i] * tempArPenRatingsCapLimited[i]; } Stats dummyStats = new Stats(); //float procArp = StatConversion.GetRatingFromArmorReduction(charStruct.Char.Level, (int)StatConversion.NPC_ARMOR[LevelDif], originalStats.TargetArmorReduction, arpenBuffs, ProccedArmorReduction); originalStats.ArmorPenetrationRating += AverageArmorPenRatingsFromProcs;//(procArp - originalStats.ArmorPenetrationRating); }*/ #endregion IterativeSpecialEffectsStats(charStruct, firstPass, critEffects, triggerIntervals, triggerChances, 0f, true, new Base.StatsWarrior(), charStruct.CombatFactors.StatS); IterativeSpecialEffectsStats(charStruct, secondPass, critEffects, triggerIntervals, triggerChances, 0f, false, null, charStruct.CombatFactors.StatS); IterativeSpecialEffectsStats(charStruct, thirdPass, critEffects, triggerIntervals, triggerChances, 0f, false, null, charStruct.CombatFactors.StatS); }