public static DPSResult MainCalculation(Eidolon pEidolon, DPSCase pCase, Weapon pSniper, Elements[] pElements, Health pHealthType, int pNumberOfUserShotsToCalculateDamageFor, params Mod[] pMods) { var dps = DPSBreakdown.FromPrimitives(pSniper, pCase, pElements, pHealthType, pMods); double MagazineTime = (dps.Magazine / dps.FireRate) + dps.Reload; double BulletsPerSecond = dps.Magazine / MagazineTime; int baseLevel = 0; switch (pEidolon) { case Eidolon.Terry: baseLevel = 50; break; case Eidolon.Gary: baseLevel = 55; break; case Eidolon.Harry: baseLevel = 60; break; default: throw new NotImplementedException("Unknown Eidolon: " + pEidolon.ToString()); } DPSResult result = new DPSResult(); //Current Health = Base Health × (1 + (Current Level − Base Level )^2 × 0.015 ) result.EidolonLimbHealth = 15000 * (1.0 + ((baseLevel - 1) * (baseLevel - 1)) * 0.015); var simInput = new DPSCalcPerformanceCritical.SimulationInput(); simInput.LimbHealth = result.EidolonLimbHealth; simInput.Magazine = dps.Magazine; simInput.FireRate = dps.FireRate; simInput.NumberOfUserShotsToCalculateDamageFor = pNumberOfUserShotsToCalculateDamageFor; simInput.PelletsTillx15 = pSniper.PelletsTillx15; simInput.Case = pCase; simInput.TotalMultishot = dps.TotalMultishot; simInput.TotalDamageWithAllFactorsIncluded = dps.TotalDamage_6_WithHealthTypeFactors; var simResult = DPSCalcPerformanceCritical.Simulate(simInput); result.ToLimbBreak_NumReloads = simResult.NumReloads; result.ToLimbBreak_NumShots = simResult.NumShots; result.ToLimbBreak_TotalDamage = simResult.TotalDamage; result.ToLimbBreak_TimeSeconds = (simResult.NumShots * (1.0 / dps.FireRate)) + (simResult.NumReloads * dps.Reload); result.DamageAfterVariableNumberOfShots = simResult.DamageAfterUserNumberOfShots; result.WFBuilderSustainedRaw = dps.TotalDamage_5_WithMultishot * BulletsPerSecond; result.WFBuilderSustainedDetails = dps.TotalDamage_6_WithHealthTypeFactors * BulletsPerSecond; result.ReloadTime = TimeSpan.FromSeconds(dps.Reload); return(result); }
private static double VsHealthType(DPSBreakdown p, Health pHealthType) { double TotalVsImpact = p.Impact * (1.0 + pHealthType.VsImpact.AsDecimal0to1); double TotalVsPuncture = p.Puncture * (1.0 + pHealthType.VsPuncture.AsDecimal0to1); double TotalVsSlash = p.Slash * (1.0 + pHealthType.VsSlash.AsDecimal0to1); double TotalVsElectric = p.Electric * (1.0 + pHealthType.VsElectric.AsDecimal0to1); double TotalVsCold = p.Cold * (1.0 + pHealthType.VsCold.AsDecimal0to1); double TotalVsHeat = p.Heat * (1.0 + pHealthType.VsHeat.AsDecimal0to1); double TotalVsToxin = p.Toxin * (1.0 + pHealthType.VsToxin.AsDecimal0to1); double TotalVsMag = p.Magnetic * (1.0 + pHealthType.VsMagnetic.AsDecimal0to1); double TotalVsGas = p.Gas * (1.0 + pHealthType.VsGas.AsDecimal0to1); double TotalVsRad = p.Radiation * (1.0 + pHealthType.VsRadiation.AsDecimal0to1); double TotalVsVrl = p.Viral * (1.0 + pHealthType.VsViral.AsDecimal0to1); double TotalVsCrsv = p.Corrosive * (1.0 + pHealthType.VsCorrosive.AsDecimal0to1); double TotalVsBlst = p.Blast * (1.0 + pHealthType.VsBlast.AsDecimal0to1); double TotalDamageVsHealthType = TotalVsImpact + TotalVsPuncture + TotalVsSlash + TotalVsElectric + TotalVsCold + TotalVsHeat + TotalVsToxin + TotalVsVrl + TotalVsRad + TotalVsGas + TotalVsMag + TotalVsCrsv + TotalVsBlst; double finalMulti = p.TotalDamage_5_WithMultishot / p.TotalDamage_2_WithElementMods; var result = TotalDamageVsHealthType * finalMulti; if (result == 0) { Debugger.Break(); } return(result); }
public static DPSBreakdown FromPrimitives(Weapon pSniper, DPSCase pCase, Elements[] pElements, Health pHealthType, params Mod[] pMods) { //First do base damage mods (Serration, Heavy Caliber) double baseImpact = pSniper.Impact; double basePuncture = pSniper.Puncture; double baseSlash = pSniper.Slash; double baseElectric = pSniper.Electric; double baseCold = pSniper.Cold; double baseHeat = pSniper.Heat; double baseToxin = pSniper.Toxin; double baseMagnetic = pSniper.Magnetic; double baseBlast = pSniper.Blast; double baseViral = pSniper.Viral; double baseRadiation = pSniper.Radiation; double baseCorrosive = pSniper.Corrosive; double baseGas = pSniper.Gas; foreach (var mod in pMods) { baseImpact += pSniper.Impact * mod.Damage.AsDecimal0to1; basePuncture += pSniper.Puncture * mod.Damage.AsDecimal0to1; baseSlash += pSniper.Slash * mod.Damage.AsDecimal0to1; baseElectric += pSniper.Electric * mod.Damage.AsDecimal0to1; baseCold += pSniper.Cold * mod.Damage.AsDecimal0to1; baseHeat += pSniper.Heat * mod.Damage.AsDecimal0to1; baseToxin += pSniper.Toxin * mod.Damage.AsDecimal0to1; baseMagnetic += pSniper.Magnetic * mod.Damage.AsDecimal0to1; baseBlast += pSniper.Blast * mod.Damage.AsDecimal0to1; baseViral += pSniper.Viral * mod.Damage.AsDecimal0to1; baseRadiation += pSniper.Radiation * mod.Damage.AsDecimal0to1; baseCorrosive += pSniper.Corrosive * mod.Damage.AsDecimal0to1; baseGas += pSniper.Gas * mod.Damage.AsDecimal0to1; } DPSBreakdown result = new DPSBreakdown(); result.Impact = baseImpact; result.Puncture = basePuncture; result.Slash = baseSlash; result.Cold = baseCold; result.Electric = baseElectric; result.Heat = baseHeat; result.Toxin = baseToxin; result.Magnetic = baseMagnetic; result.Blast = baseBlast; result.Viral = baseViral; result.Radiation = baseRadiation; result.Corrosive = baseCorrosive; result.Gas = baseGas; result.TotalDamage_1_WithDamageMods = baseImpact + basePuncture + baseSlash + baseElectric + baseCold + baseHeat + baseToxin + baseMagnetic + baseBlast + baseViral + baseRadiation + baseCorrosive + baseGas; //Now do mods that can be calculated independent of each other double fMagazine = pSniper.Magazine; result.FireRate = pSniper.FireRate; result.Reload = pSniper.Reload; result.TotalMultishot = 0.0; result.TotalCritChance = pSniper.CritChance.AsDecimal0to1; result.TotalCritMultiplier = pSniper.CritMultiplier; result.AugmentBonusDamage = Percent.Zero; double reloadModifierDecimal0to1 = 0.0; foreach (var mod in pMods) { fMagazine += (pSniper.Magazine * mod.MagazineSize.AsDecimal0to1); result.FireRate += pSniper.FireRate * mod.FireRate.AsDecimal0to1; reloadModifierDecimal0to1 += mod.Reload.AsDecimal0to1; result.Reload += pSniper.Reload * mod.Reload.AsDecimal0to1; result.TotalMultishot += mod.Multishot.AsDecimal0to1; result.TotalCritChance += pSniper.CritChance.AsDecimal0to1 * mod.CritChance.AsDecimal0to1; result.TotalCritMultiplier += pSniper.CritMultiplier * mod.CritDamage.AsDecimal0to1; result.Impact += baseImpact * mod.Impact.AsDecimal0to1; result.Puncture += basePuncture * mod.Puncture.AsDecimal0to1; result.Slash += baseSlash * mod.Slash.AsDecimal0to1; result.Heat += result.TotalDamage_1_WithDamageMods * mod.Heat.AsDecimal0to1; result.Cold += result.TotalDamage_1_WithDamageMods * mod.Cold.AsDecimal0to1; result.Toxin += result.TotalDamage_1_WithDamageMods * mod.Toxin.AsDecimal0to1; result.Electric += result.TotalDamage_1_WithDamageMods * mod.Electric.AsDecimal0to1; if (mod.AugmentBonus != null) { double abd = result.AugmentBonusDamage.AsDecimal0to1; result.AugmentBonusDamage = Percent.FromDecimal0to1(abd + mod.AugmentBonus.AsDecimal0to1); } } result.Magazine = (int)fMagazine; result.Reload = pSniper.Reload / (1.0 + reloadModifierDecimal0to1); result.TotalDamage_2_WithElementMods = result.Impact; result.TotalDamage_2_WithElementMods += result.Puncture; result.TotalDamage_2_WithElementMods += result.Slash; result.TotalDamage_2_WithElementMods += result.Heat; result.TotalDamage_2_WithElementMods += result.Cold; result.TotalDamage_2_WithElementMods += result.Toxin; result.TotalDamage_2_WithElementMods += result.Electric; result.TotalDamage_2_WithElementMods += result.Magnetic; result.TotalDamage_2_WithElementMods += result.Blast; result.TotalDamage_2_WithElementMods += result.Viral; result.TotalDamage_2_WithElementMods += result.Radiation; result.TotalDamage_2_WithElementMods += result.Corrosive; result.TotalDamage_2_WithElementMods += result.Gas; //Now combine multiple elements however the user has them arranged MergeElements(pElements.Contains(Elements.Magnetic), baseMagnetic, ref result.Cold, ref result.Electric, out result.Magnetic); MergeElements(pElements.Contains(Elements.Gas), baseGas, ref result.Heat, ref result.Toxin, out result.Gas); MergeElements(pElements.Contains(Elements.Viral), baseViral, ref result.Cold, ref result.Toxin, out result.Viral); MergeElements(pElements.Contains(Elements.Radiation), baseRadiation, ref result.Heat, ref result.Electric, out result.Radiation); MergeElements(pElements.Contains(Elements.Corrosive), baseCorrosive, ref result.Electric, ref result.Toxin, out result.Corrosive); MergeElements(pElements.Contains(Elements.Blast), baseBlast, ref result.Cold, ref result.Heat, out result.Blast); result.TotalCritChance += pSniper.ZoomBonusCC.AsDecimal0to1; int CritChanceLevel = 0; double CritChanceRemainder = result.TotalCritChance; while (CritChanceRemainder > 1.0) { CritChanceRemainder -= 1.0; CritChanceLevel++; } double CritChanceFloor = 1.0 - CritChanceRemainder; double CritChanceCeiling = CritChanceRemainder; result.TotalCritMultiplier += pSniper.ZoomBonusCD.AsDecimal0to1 * pSniper.CritMultiplier; double CritMultiFloor = CritChanceLevel * (result.TotalCritMultiplier - 1) + 1; double CritMultiCeiling = (CritChanceLevel + 1) * (result.TotalCritMultiplier - 1) + 1; result.TotalDamage_3_WithCriticalHits = 0.0; switch (pCase) { case DPSCase.Average: result.TotalDamage_3_WithCriticalHits += CritMultiFloor * CritChanceFloor * result.TotalDamage_2_WithElementMods; result.TotalDamage_3_WithCriticalHits += CritMultiCeiling * CritChanceCeiling * result.TotalDamage_2_WithElementMods; break; case DPSCase.Best: result.TotalDamage_3_WithCriticalHits = CritMultiCeiling * result.TotalDamage_2_WithElementMods; break; case DPSCase.Worst: result.TotalDamage_3_WithCriticalHits = CritMultiFloor * result.TotalDamage_2_WithElementMods; break; default: throw new NotImplementedException("Unknown DPSCase: " + pCase.ToString()); } result.TotalDamage_4_WithAugmentBonus = result.TotalDamage_3_WithCriticalHits * (1.0 + result.AugmentBonusDamage.AsDecimal0to1); switch (pCase) { case DPSCase.Average: result.TotalDamage_5_WithMultishot = result.TotalDamage_4_WithAugmentBonus * (1.0 + result.TotalMultishot); break; case DPSCase.Best: result.TotalDamage_5_WithMultishot = result.TotalDamage_4_WithAugmentBonus * (1.0 + Math.Ceiling(result.TotalMultishot)); break; case DPSCase.Worst: result.TotalDamage_5_WithMultishot = result.TotalDamage_4_WithAugmentBonus * (1.0 + Math.Floor(result.TotalMultishot)); break; default: throw new NotImplementedException("Unknown DPSCase: " + pCase.ToString()); } result.TotalDamage_6_WithHealthTypeFactors = VsHealthType(result, pHealthType); return(result); }