public override void Initialize(CharacterCalculationsDPSWarr calcs) { base.Initialize(calcs); bool hsok = CalcOpts.Maintenance[(int)Rawr.DPSWarr.CalculationOptionsDPSWarr.Maintenances.HeroicStrike_]; bool clok = #if RAWR3 || SILVERLIGHT BossOpts.MultiTargs && BossOpts.Targets != null && BossOpts.Targets.Count > 0 #else CalcOpts.MultipleTargets #endif && CalcOpts.Maintenance[(int)Rawr.DPSWarr.CalculationOptionsDPSWarr.Maintenances.Cleave_]; BloodSurge _BS = GetWrapper <BloodSurge>().ability as BloodSurge; percHS = (hsok ? 1f : 0f); if (clok) { #if RAWR3 || SILVERLIGHT //percHS -= (float)BossOpts.MultiTargsPerc; { float time = 0; foreach (TargetGroup tg in BossOpts.Targets) { if (tg.Chance <= 0 || tg.Frequency <= 0 || tg.Duration <= 0) { continue; } time += tg.Frequency / BossOpts.BerserkTimer * tg.Duration / 1000f; } float perc = time / BossOpts.BerserkTimer; percHS -= Math.Max(0f, Math.Min(1f, perc)); } #else percHS -= (float)CalcOpts.MultipleTargetsPerc / 100f; #endif } percCL = (clok ? 1f - percHS : 0f); if (_BS != null) { _BS.maintainActs = MaintainCDs; } }
/// <summary> /// GetCharacterCalculations is the primary method of each model, where a majority of the calculations /// and formulae will be used. GetCharacterCalculations should call GetCharacterStats(), and based on /// those total stats for the character, and any calculationoptions on the character, perform all the /// calculations required to come up with the final calculations defined in /// CharacterDisplayCalculationLabels, including an Overall rating, and all Sub ratings defined in /// SubPointNameColors. /// </summary> /// <param name="character">The character to perform calculations for.</param> /// <param name="additionalItem">An additional item to treat the character as wearing. /// This is used for gems, which don't have a slot on the character to fit in, so are just /// added onto the character, in order to get gem calculations.</param> /// <returns>A custom CharacterCalculations object which inherits from CharacterCalculationsBase, /// containing all of the final calculations defined in CharacterDisplayCalculationLabels. See /// CharacterCalculationsBase comments for more details.</returns> public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem) { /* * To Do: * -Deep wounds * -Allow more talent choices * -Check for certain talents before calculating * -Add in rotation choice * -Add in GCD check for haste and slam rotations. (2.5 second min swing timer otherwise gcd ruins it) * -Add in control for changing rotation during heroism/bloodlust? * -Handle bloodlust/heroism same as mage model instead of average over fight. * */ //character = GetTalents(character); Stats stats = GetCharacterStats(character, additionalItem); CharacterCalculationsDPSWarr calcs = new CharacterCalculationsDPSWarr(); calcs.BasicStats = stats; CalculationOptionsDPSWarr calcOpts = character.CalculationOptions as CalculationOptionsDPSWarr; float avgBaseWeaponHit = 0.0f, hastedSpeed = 2.0f, physicalCritModifier = 0.0f, chanceToBeDodged = 6.5f, chanceToMiss = 9.0f;; float chanceToGlance = 0.25f, glancingAmount = 0.35f; float slamDPS = 0.0f, msDPS = 0.0f, wfDPS = 0.0f, wwDPS = 0.0f; float rotationTime; float FlurryHaste; #region Mitigation //Default Boss Armor float bossArmor = calcOpts.BossArmor; float totalArP = stats.ArmorPenetration; float modifiedTargetArmor = bossArmor - totalArP; float mitigation = 1 - modifiedTargetArmor / (modifiedTargetArmor + 10557.5f); #endregion //Flurry *Assumes 4 attakcs per flurry to refresh. This is a loose average of the # of attacks //for each flurry including instants & slams. //Also allows user to check 100% uptime flurry if desired. FlurryHaste = (0.05f * calcOpts.Flurry); if (calcOpts.FlurryUptime == 0) { FlurryHaste = 1.0f + (1 - (float)Math.Pow((1 - (stats.CritRating / 22.08f / 100.0f)), 4.0f)) * FlurryHaste; } else { FlurryHaste += 1.0f; } //Variables for Bloodlust/Deathwish uptime int remainder = 0, noOfFullDW = 0, noOfFullBL; int div; float partialUptime, totalUptime; //Fight duration float fightDuration = calcOpts.FightLength * 60; float bloodlust = 1.0f; #region Bloodlust if (stats.Bloodlust > 0) { //Bloodlust -- Calculating uptime *Credit to Ret Model //Note, not working correctly in the ret model //Haste is multiplicative something the ret model isn't handling. div = Math.DivRem(Convert.ToInt32(fightDuration), 600, out remainder); if (remainder == 0) { noOfFullBL = div; } else { noOfFullBL = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((fightDuration + 40) / 600))); } partialUptime = fightDuration - noOfFullBL * 600; if (partialUptime < 0) { partialUptime = 0; } totalUptime = partialUptime + noOfFullBL * 40f; bloodlust = (1.0f + (0.30f * (totalUptime / fightDuration))); } #endregion string shattrathFaction = calcOpts.ShattrathFaction; if (stats.ShatteredSunMightProc > 0) { switch (shattrathFaction) { case "Aldor": stats.AttackPower += 39.13f; break; } } //Check if we have the talent impale. float impale = 1.0f + (0.1f * calcOpts.Impale); #region White Damage and Multipliers //2 Handed Spec float twoHandedSpec = 1.0f + (0.01f * calcOpts.TwoHandedSpec); if (character.MainHand != null) { avgBaseWeaponHit = twoHandedSpec * (character.MainHand.MinDamage + character.MainHand.MaxDamage + stats.WeaponDamage * 2f) / 2.0f; hastedSpeed = (stats.HasteRating == 0) ? character.MainHand.Speed : character.MainHand.Speed / (1 + (stats.HasteRating + stats.DrumsOfBattle) / 1576f); hastedSpeed = hastedSpeed / FlurryHaste; hastedSpeed = hastedSpeed / bloodlust; } rotationTime = (hastedSpeed * 4) + (0.5f * 4); rotationTime += ((calcOpts.SlamLatency) * 4); //Add Attack Power Bonus avgBaseWeaponHit += twoHandedSpec * (stats.AttackPower / 14.0f) * ((character.MainHand == null) ? 2.0f : character.MainHand.Speed); //Take Non-Stat Buffs into account physicalCritModifier = 1.0f + ((stats.CritRating / 22.08f) / 100.0f) * (1f + stats.BonusCritMultiplier * 2f); chanceToBeDodged -= (float)(Math.Floor(stats.ExpertiseRating / 3.89f) * 0.25f); chanceToBeDodged -= calcOpts.WeaponMastery; if (chanceToBeDodged < 0.0f) { chanceToBeDodged = 0.0f; } chanceToMiss -= stats.HitRating / 15.76f; if (chanceToMiss < 0.0f) { chanceToMiss = 0.0f; } float avgBaseWeaponHitPost = (avgBaseWeaponHit * physicalCritModifier - avgBaseWeaponHit * (chanceToMiss + chanceToBeDodged) / 100.0f - avgBaseWeaponHit * chanceToGlance * glancingAmount); //Death Wish -- Calculating uptime *Credit to Ret model AW up time. div = Math.DivRem(Convert.ToInt32(fightDuration), 180, out remainder); if (remainder == 0) { noOfFullDW = div; } else { noOfFullDW = Convert.ToInt32(Math.Ceiling(Convert.ToDouble((fightDuration + 20) / 180))); } partialUptime = fightDuration - noOfFullDW * 180; if (partialUptime < 0) { partialUptime = 0; } totalUptime = partialUptime + noOfFullDW * 20f; float deathWish = 1f + 0.20f * totalUptime / fightDuration; //Misery float misery = 1f + stats.BonusSpellPowerMultiplier; //Blood Frenzy : TODO Take from Debuff List float damageMod = 1.0f + stats.BonusPhysicalDamageMultiplier; float impSancAura = 1.0f; //Added Imp Sanc aura to the buff list, if total damage mod is greater then just //blood frenzy assume we have imp sanc... (not the best way...) if (damageMod > 1.04f) { impSancAura = 1.02f; } float ssoNeckProcDPS = 0f; //TODO: Add Mitigation avgBaseWeaponHitPost *= damageMod * deathWish * mitigation; float dpsWhite = (avgBaseWeaponHitPost * 4) / rotationTime; calcs.WhiteDPSPoints = dpsWhite; calcs.HastedSpeed = hastedSpeed; #endregion if (stats.ShatteredSunMightProc > 0) { switch (shattrathFaction) { case "Scryer": ssoNeckProcDPS = 350f * deathWish * misery * impSancAura * physicalCritModifier / 50f; break; } } #region Slam if (character.MainHand != null) { avgBaseWeaponHit = twoHandedSpec * (character.MainHand.MinDamage + character.MainHand.MaxDamage + stats.WeaponDamage * 2f) / 2.0f; } avgBaseWeaponHit += twoHandedSpec * (stats.AttackPower / 14.0f) * ((character.MainHand == null) ? 1.0f : character.MainHand.Speed); //add in slam damage avgBaseWeaponHit += twoHandedSpec * 140; physicalCritModifier = 1.0f + ((stats.CritRating / 22.08f) / 100.0f) * ((1f + stats.BonusCritMultiplier * 2f) * impale); avgBaseWeaponHitPost = (avgBaseWeaponHit * physicalCritModifier - avgBaseWeaponHit * (chanceToMiss + chanceToBeDodged) / 100.0f); avgBaseWeaponHitPost *= damageMod * deathWish * mitigation; slamDPS = (avgBaseWeaponHitPost * 4) / rotationTime; calcs.SlamDPSPoints = slamDPS; #endregion //WW and MS are normalized (2h = 3.3 speed) float normalizedAP = twoHandedSpec * (stats.AttackPower / 14.0f) * 3.3f; #region Mortal Strike if (character.MainHand != null) { avgBaseWeaponHit = twoHandedSpec * (character.MainHand.MinDamage + character.MainHand.MaxDamage + stats.WeaponDamage * 2f) / 2.0f; } avgBaseWeaponHit += normalizedAP; //add in MS damage avgBaseWeaponHit += twoHandedSpec * 210; avgBaseWeaponHitPost = (avgBaseWeaponHit * physicalCritModifier - avgBaseWeaponHit * (chanceToMiss + chanceToBeDodged) / 100.0f); avgBaseWeaponHitPost *= damageMod * deathWish * mitigation; msDPS = (avgBaseWeaponHitPost * 2) / rotationTime; calcs.MSDPSPoints = msDPS; #endregion #region WhirlWind if (character.MainHand != null) { avgBaseWeaponHit = twoHandedSpec * (character.MainHand.MinDamage + character.MainHand.MaxDamage + stats.WeaponDamage * 2f) / 2.0f; } avgBaseWeaponHit += normalizedAP; avgBaseWeaponHitPost = (avgBaseWeaponHit * physicalCritModifier - avgBaseWeaponHit * (chanceToMiss + chanceToBeDodged) / 100.0f); avgBaseWeaponHitPost *= damageMod * deathWish * mitigation; wwDPS = (avgBaseWeaponHitPost * 1) / rotationTime; calcs.WWDPSPoints = wwDPS; #endregion #region Windfury //WF only procs on whites. //White time = rotation time/4 float avgTimeBetnWF = ((rotationTime / 4) / (1.0f - (chanceToBeDodged + chanceToMiss) / 100f)) * 5.0f; float wfAPIncrease = stats.WindfuryAPBonus; float wfHitPre = avgBaseWeaponHit + (wfAPIncrease / 14f) * ((character.MainHand == null) ? 0 : character.MainHand.Speed); float wfHitPost = (wfHitPre * physicalCritModifier) - (wfHitPre * (chanceToMiss + chanceToBeDodged) / 100f) - (wfHitPre * glancingAmount * chanceToGlance); if (wfAPIncrease > 0) { wfHitPost *= damageMod * deathWish * mitigation; } else { wfHitPost = 0f; } wfDPS = wfHitPost / avgTimeBetnWF; calcs.WFDPSPoints = wfDPS; #endregion #region SwordSpec float swordSpecDps = 0.0f; if ((character.MainHand != null) && (character.MainHand.Type == Item.ItemType.TwoHandSword)) { //Assume 11 sword procs every 220 attacks (5%) //Each rotation has 11 attacks float swordSpecHit = (rotationTime * dpsWhite) / 4; swordSpecDps = (swordSpecHit * 11) / (rotationTime * 20); dpsWhite += swordSpecDps; calcs.WhiteDPSPoints += swordSpecDps; } #endregion calcs.DPSPoints = dpsWhite + (character.MainHand == null ? 0 : slamDPS + msDPS + wwDPS) + wfDPS + ssoNeckProcDPS; calcs.SubPoints = new float[] { calcs.DPSPoints }; calcs.OverallPoints = calcs.DPSPoints; calcs.BasicStats.WeaponDamage = avgBaseWeaponHit * impSancAura; return(calcs); }
/*public static string GetConstructionCounts() { string retVal = ""; // foreach (string c in ConstructionCounts.Keys) { retVal += string.Format("{0:000000}/{1:00000.00}: {2}\n", ConstructionCounts[c] < 5 ? 0 : ConstructionCounts[c] - 5, (float)(ConstructionCounts[c] < 5 ? 0 : ConstructionCounts[c] - 5) / (float)(ConstructionCounts["GetCharacterCalculations"] < 5 ? 1 : ConstructionCounts["GetCharacterCalculations"] - 5), c); } // return retVal + "\n"; } public static Dictionary<string, int> ConstructionCounts = new Dictionary<string,int>() { { "GetCharacterCalculations", 0 }, { "GetCharacterStats", 0 }, { "GetCharacterStats_Inner", 0 }, { "GetCharacterStats_Buffed", 0 }, { "GetCharacterStats_Override", 0 }, { "CalculateTriggers", 0 }, { "IterativeSpecialEffectsStats", 0 }, { "ApplySpecialEffect", 0 }, { "UpdateStatsAndAdd", 0 }, { "DoSpecialEffects", 0 }, { "Rotation Base", 0 }, { "Rotation Arms", 0 }, { "Rotation Fury", 0 }, { "CombatFactors", 0 }, };*/ #endif public override CharacterCalculationsBase GetCharacterCalculations(Character character, Item additionalItem, bool referenceCalculation, bool significantChange, bool needsDisplayCalculations) { #if DEBUG //ConstructionCounts["GetCharacterCalculations"]++; #endif CharacterCalculationsDPSWarr calc = new CharacterCalculationsDPSWarr(); try { #region Object Creation // First things first, we need to ensure that we aren't using bad data if (character == null) { return calc; } CalculationOptionsDPSWarr calcOpts = character.CalculationOptions as CalculationOptionsDPSWarr; if (calcOpts == null) { return calc; } // BossOptions bossOpts = character.BossOptions; CombatFactors combatFactors; Skills.WhiteAttacks whiteAttacks; Rotation Rot; Base.StatsWarrior statsRace = null; Base.StatsWarrior stats = GetCharacterStats(character, additionalItem, StatType.Average, calcOpts, bossOpts, out statsRace, out combatFactors, out whiteAttacks, out Rot); DPSWarrCharacter charStruct = new DPSWarrCharacter() { CalcOpts = calcOpts, BossOpts = bossOpts, Rot = Rot, CombatFactors = combatFactors, Char = character, Talents = character.WarriorTalents }; /*if (calcOpts.UseMarkov) { if (combatFactors.FuryStance) { //Markov.StateSpaceGeneratorFuryTest b = new Markov.StateSpaceGeneratorFuryTest(); //Markov.StateSpaceGeneratorFuryTest.StateSpaceGeneratorFuryTest1(character, stats, combatFactors, whiteAttacks, calcOpts, bossOpts, needsDisplayCalculations); } else { //Markov.StateSpaceGeneratorArmsTest b = new Markov.StateSpaceGeneratorArmsTest(); //Markov.StateSpaceGeneratorArmsTest.StateSpaceGeneratorArmsTest1(character, stats, combatFactors, whiteAttacks, calcOpts, bossOpts, needsDisplayCalculations); } }*/ #endregion calc.Duration = bossOpts.BerserkTimer; calc.PTRMode = calcOpts.PtrMode; calc.AverageStats = stats; if (needsDisplayCalculations) { calc.UnbuffedStats = GetCharacterStats(character, additionalItem, StatType.Unbuffed, calcOpts, bossOpts, out statsRace); calc.BuffedStats = GetCharacterStats(character, additionalItem, StatType.Buffed, calcOpts, bossOpts, out statsRace); calc.BuffsStats = GetBuffsStats(charStruct); calc.MaximumStats = GetCharacterStats(character, additionalItem, StatType.Maximum, calcOpts, bossOpts, out statsRace); } calc.CombatFactors = combatFactors; calc.Rot = Rot; calc.TargetLevel = bossOpts.Level; calc.BaseHealth = statsRace.Health; {// == Attack Table == // Miss calc.Miss = stats.Miss; calc.HitRating = stats.HitRating; calc.ExpertiseRating = stats.ExpertiseRating; calc.Expertise = StatConversion.GetExpertiseFromRating(stats.ExpertiseRating, CharacterClass.Warrior) + stats.Expertise; calc.MHExpertise = combatFactors.CMHexpertise; calc.OHExpertise = combatFactors.COhexpertise; calc.AgilityCritBonus = StatConversion.GetCritFromAgility(stats.Agility, CharacterClass.Warrior); calc.CritRating = stats.CritRating; calc.CritPercent = stats.PhysicalCrit; calc.MHCrit = combatFactors.CMHycrit; calc.OHCrit = combatFactors.COhycrit; } // Offensive //calc.ArmorPenetrationRating = stats.ArmorPenetrationRating; //calc.ArmorPenetrationRating2Perc = StatConversion.GetArmorPenetrationFromRating(stats.ArmorPenetrationRating); //calc.ArmorPenetration = Math.Min(1f, calc.ArmorPenetrationRating2Perc); calc.HasteRating = stats.HasteRating; calc.HastePercent = stats.PhysicalHaste; calc.MasteryVal = StatConversion.GetMasteryFromRating(stats.MasteryRating, CharacterClass.Warrior); // DPS Rot.Initialize(calc); calc.PlateSpecValid = HelperFunctions.ValidatePlateSpec(charStruct); // Neutral // Defensive calc.Armor = stats.Armor; Rot.MakeRotationandDoDPS(true, needsDisplayCalculations); #region Special Damage Procs, like Bandit's Insignia or Hand-mounted Pyro Rockets calc.SpecProcDPS = calc.SpecProcDmgPerHit = calc.SpecProcActs = 0f; if (stats._rawSpecialEffectData != null && character.MainHand != null) { bool runIt = false; foreach (SpecialEffect s in stats.SpecialEffects()) { if (s.Stats == null) { continue; } if (s.Stats.ShadowDamage != 0) { runIt = true; break; } if (s.Stats.FireDamage != 0) { runIt = true; break; } if (s.Stats.HolyDamage != 0) { runIt = true; break; } if (s.Stats.FrostDamage != 0) { runIt = true; break; } if (s.Stats.NatureDamage != 0) { runIt = true; break; } if (s.Stats.ArcaneDamage != 0) { runIt = true; break; } } if (runIt) { DamageProcs.SpecialDamageProcs SDP; Dictionary<Trigger, float> triggerIntervals = new Dictionary<Trigger, float>(); Dictionary<Trigger, float> triggerChances = new Dictionary<Trigger, float>(); CalculateTriggers(charStruct, triggerIntervals, triggerChances); if (character.Race == CharacterRace.Goblin && statsRace._rawSpecialEffectData.Length > 0) { // Fix the damage for Goblin Rockets foreach (SpecialEffect s in stats.SpecialEffects()) { if (s.Stats != null && s.Stats.FireDamage == (1f + character.Level * 2)) { s.Stats.FireDamage += stats.AttackPower * 0.25f // AP Bonus + stats.Intellect * 0.50193f; // Int Bonus } } } SDP = new Rawr.DamageProcs.SpecialDamageProcs(character, stats, calc.TargetLevel - character.Level, new List<SpecialEffect>(stats.SpecialEffects()), triggerIntervals, triggerChances, bossOpts.BerserkTimer, combatFactors.DamageReduction); calc.SpecProcDPS = SDP.CalculateAll(); calc.SpecProcDmgPerHit = SDP.GetDamagePerHit; calc.SpecProcActs = SDP.GetTotalNumProcs; } } calc.TotalDPS += calc.SpecProcDPS; #endregion #region Survivability List<Attack> Attacks; if (calcOpts.SurvScale != 0f && (Attacks = bossOpts.Attacks.FindAll(a => a.AffectsRole[PLAYER_ROLES.MeleeDPS])).Count > 0) { Dictionary<ItemDamageType, float> countsDmg = new Dictionary<ItemDamageType, float>() { { ItemDamageType.Physical, 0f }, { ItemDamageType.Arcane, 0f }, { ItemDamageType.Fire, 0f }, { ItemDamageType.Frost, 0f }, { ItemDamageType.Holy, 0f }, { ItemDamageType.Nature, 0f }, { ItemDamageType.Shadow, 0f }, }; Dictionary<ItemDamageType, float> percDmg = new Dictionary<ItemDamageType, float>() { { ItemDamageType.Physical, 0f }, { ItemDamageType.Arcane, 0f }, { ItemDamageType.Fire, 0f }, { ItemDamageType.Frost, 0f }, { ItemDamageType.Holy, 0f }, { ItemDamageType.Nature, 0f }, { ItemDamageType.Shadow, 0f }, }; Dictionary<ItemDamageType, float> highestDmg = new Dictionary<ItemDamageType, float>() { { ItemDamageType.Physical, 0f }, { ItemDamageType.Arcane, 0f }, { ItemDamageType.Fire, 0f }, { ItemDamageType.Frost, 0f }, { ItemDamageType.Holy, 0f }, { ItemDamageType.Nature, 0f }, { ItemDamageType.Shadow, 0f }, }; int totalCount = 0; foreach (Attack a in Attacks) { countsDmg[a.DamageType] += 1; totalCount++; if ((a.DamagePerHit + a.DamagePerTick) > highestDmg[a.DamageType]) { highestDmg[a.DamageType] = (a.DamagePerHit + a.DamagePerTick); } } foreach (ItemDamageType t in countsDmg.Keys) { percDmg[t] = countsDmg[t] / (float)totalCount; } float TotalConstantDamageReduction = 1f - (1f - (stats.Armor > 0 ? StatConversion.GetArmorDamageReduction(bossOpts.Level, character.Level, stats.Armor, 0f, 0f) : 0)) * (1f - stats.DamageTakenReductionMultiplier) * (1f - stats.BossPhysicalDamageDealtReductionMultiplier); Dictionary<ItemDamageType, float> SurvivabilityPointsRaw = new Dictionary<ItemDamageType, float>() { { ItemDamageType.Physical, stats.Health / (1f - TotalConstantDamageReduction) }, { ItemDamageType.Arcane, stats.Health / ((1f - StatConversion.GetMinimumResistance(bossOpts.Level, character.Level, stats.ArcaneResistance, 0)) * (1f - stats.DamageTakenReductionMultiplier)) }, { ItemDamageType.Fire, stats.Health / ((1f - StatConversion.GetMinimumResistance(bossOpts.Level, character.Level, stats.FireResistance, 0)) * (1f - stats.DamageTakenReductionMultiplier)) }, { ItemDamageType.Frost, stats.Health / ((1f - StatConversion.GetMinimumResistance(bossOpts.Level, character.Level, stats.FrostResistance, 0)) * (1f - stats.DamageTakenReductionMultiplier)) }, { ItemDamageType.Holy, stats.Health / ((1f) * (1f - stats.DamageTakenReductionMultiplier)) }, { ItemDamageType.Nature, stats.Health / ((1f - StatConversion.GetMinimumResistance(bossOpts.Level, character.Level, stats.NatureResistance, 0)) * (1f - stats.DamageTakenReductionMultiplier)) }, { ItemDamageType.Shadow, stats.Health / ((1f - StatConversion.GetMinimumResistance(bossOpts.Level, character.Level, stats.ShadowResistance, 0)) * (1f - stats.DamageTakenReductionMultiplier)) }, }; Dictionary<ItemDamageType, float> SurvivabilityPoints = SoftCapSurvivals(charStruct, highestDmg, SurvivabilityPointsRaw); if (stats.HealthRestoreFromMaxHealth > 0) { stats.HealthRestore += stats.HealthRestoreFromMaxHealth * stats.Health * bossOpts.BerserkTimer; } float survs = 0f; foreach (ItemDamageType t in SurvivabilityPoints.Keys) { survs += SurvivabilityPoints[t] * percDmg[t]; } float HealthRest2Surv = survs / 100f + Rot._HPS_TTL + stats.HealthRestore / 100f; calc.TotalHPS = Rot._HPS_TTL; calc.Survivability = calcOpts.SurvScale * HealthRest2Surv; } else { // No point in running all those calcs just to zero them out after calc.TotalHPS = Rot._HPS_TTL; calc.Survivability = 0f; } #endregion calc.OverallPoints = calc.TotalDPS + calc.Survivability; #region Old ArP cap calc, keeping in case another cap has to be implemented //calculatedStats.UnbuffedStats = GetCharacterStats(character, additionalItem, StatType.Unbuffed, calcOpts, bossOpts); /*if (needsDisplayCalculations) { calc.BuffedStats = GetCharacterStats(character, additionalItem, StatType.Buffed, calcOpts, bossOpts, out statsRace); //calculatedStats.MaximumStats = GetCharacterStats(character, additionalItem, StatType.Maximum, calcOpts, bossOpts); float maxArp = calc.BuffedStats.ArmorPenetrationRating; foreach (SpecialEffect effect in calc.BuffedStats.SpecialEffects(s => s.Stats.ArmorPenetrationRating > 0f)) { maxArp += effect.Stats.ArmorPenetrationRating; } calc.MaxArmorPenetration = StatConversion.GetArmorPenetrationFromRating(maxArp); }*/ #endregion #if DEBUG /*foreach (string c in Rotation.ConstructionCounts.Keys) { if (!ConstructionCounts.ContainsKey(c)) { ConstructionCounts.Add(c, 0); } ConstructionCounts[c] = Rotation.ConstructionCounts[c]; } foreach (string c in CombatFactors.ConstructionCounts.Keys) { if (!ConstructionCounts.ContainsKey(c)) { ConstructionCounts.Add(c, 0); } ConstructionCounts[c] = CombatFactors.ConstructionCounts[c]; } string counts = GetConstructionCounts(); Clipboard.SetText(counts); //System.Windows.MessageBox.Show(counts, "DPSWarr Counts", System.Windows.MessageBoxButton.OK);*/ #endif } catch (Exception ex) { new Base.ErrorBox() { Title = "Error in creating Stat Pane Calculations", Function = "GetCharacterCalculations()", TheException = ex, }.Show(); } return calc; }