public static Session ToSession(this Combat combat, Session defaultValues) { if (combat == null) return null; var target = combat.Targets.OrderBy(t => t.DamageDone).Last().Character; int additionalTargetNumber = combat.Targets.Count(t => t.Character == null || !t.Character.IsPlayer) - 1; Session session = new Session { Duration = combat.Duration, Name = $"{target}{(additionalTargetNumber > 0 ? $" (+{additionalTargetNumber})" : "")}, {combat.Duration.ToString("0.###", CultureInfo.InvariantCulture)}s, {combat.Dps.ToString("0.###", CultureInfo.InvariantCulture)}dps" }; foreach (var ability in combat.Abilities.Where(a => a.Targets.Any(t => t.DamageDone > 0 && t.Character != combat.Player))) { var sessionAbility = new SessionAbility { Id = ability.Id }; // not in db if (sessionAbility.Ability == null) continue; var hittingActions = ability.Activations.SelectMany(activation => activation.Actions.Where(a => a.Amount > 0 && !a.IsCritical)).ToList(); var criticalActions = ability.Activations.SelectMany(activation => activation.Actions.Where(a => a.Amount > 0 && a.IsCritical)).ToList(); int maximumCritical = criticalActions.Count > 0 ? criticalActions.Max(aa => aa.Amount) : 0; int maximum = hittingActions.Count > 0 ? hittingActions.Max(aa => aa.Amount) : 0; int minimum = hittingActions.Count > 0 ? hittingActions.Min(aa => aa.Amount) : 0; int average = hittingActions.Count > 0 ? (int) hittingActions.Average(aa => aa.Amount) : 0; double surge = maximum > 0 && maximumCritical > 0 ? (maximumCritical - maximum) / (double) maximum : 0; sessionAbility.Activations = ability.Activations.Count; sessionAbility.Info = $"Activations: {ability.Activations.Count}\n" + $"Total hits: {ability.Activations.Sum(a => a.Actions.Count)}\n" + $"Hits per activation: {(double) ability.Activations.Sum(a => a.Actions.Count)/ability.Activations.Count} [{string.Join("/", ability.Activations.Select(a => a.Actions.Count).Distinct().OrderBy(n => n))}]\n" + $"Maximum critical hit damage: {maximumCritical}\n" + $"Surge: {surge:P}\n" + $"Maximum hit damage: {maximum}\n" + $"Minimum hit damage: {minimum}\n" + $"Average hit damage: {average}\n" + $"Total Damage: {ability.Targets.Sum(t => t.DamageDone)}"; var abilityDefauls = defaultValues?.Abilities.FirstOrDefault(a => a.Id == ability.Id); if (abilityDefauls != null) { sessionAbility.SurgeBonus = abilityDefauls.SurgeBonus; sessionAbility.Autocrit = abilityDefauls.Autocrit; sessionAbility.DamageMultiplier = abilityDefauls.DamageMultiplier; sessionAbility.ArmorReduction = abilityDefauls.ArmorReduction; sessionAbility.ForceOffHand = abilityDefauls.ForceOffHand; } session.Abilities.Add(sessionAbility); } session.Abilities.Sort((a1, a2) => string.CompareOrdinal(a1.Ability.Name, a2.Ability.Name)); return session; }
public SessionViewModel(Session session, Configuration configuration, Session defaultValues) { Session = session; Abilities = new ObservableCollection<SessionAbilityViewModel>(); foreach (var sessionAbility in session.Abilities) { var ability = new SessionAbilityViewModel(sessionAbility, configuration, defaultValues); ability.SessionAbilityUpdated += OnSessionUpdated; Abilities.Add(ability); } }
public SessionAbilityViewModel(SessionAbility sessionAbility, Configuration configuration, Session defaultValues) { _sessionAbility = sessionAbility; _configuration = configuration; _defaultValues = defaultValues; UpdateCanForceOffHand(); configuration.DualWieldUpdated += UpdateCanForceOffHand; SaveAsDefaultCommand = new CommandHandler(SaveAsDefault); }
public static double CalculateDps(Session session, Configuration configuration) { lock (Lock) { if (session == null) return 0; return session.Abilities.Sum ( a => GetAbilityDamage(configuration, a, session.EnergyKineticDamageReduction, session.ElementalInternalDamageReduction, session.DefenseChance) * a.Activations * a.DamageMultiplier * (a.Ability.IgnoresAlacrity ? 1 : 1 + configuration.Alacrity) ) / session.Duration; } }
private static ConfigurationCorrection FindHighestDpsCorrection(Session session, Configuration configuration, ConfigurationCorrection correction, int budget, int step, int lastStep) { // ncalc is not thread-safe, we need lock here since we're using static instance of formulas lock (Lock) { correction.Dps = 0; var range = (lastStep + 1) * 2 + 1; var al = Math.Max(correction.AlacrityPoints - lastStep - 1, 0); var pw = Math.Max(correction.PowerPoints - lastStep - 1, 0); var cr = Math.Max(correction.CriticalPoints - lastStep - 1, 0); var ac = Math.Max(correction.AccuracyPoints - lastStep - 1, 0); for ( configuration.PowerPoints = pw; configuration.PowerPoints <= Math.Min(budget, pw + range); configuration.PowerPoints += step ) { for ( configuration.CriticalPoints = cr; configuration.CriticalPoints <= Math.Min(budget - configuration.PowerPoints, cr + range); configuration.CriticalPoints += step ) { for ( configuration.AlacrityPoints = al; configuration.AlacrityPoints <= Math.Min(budget - configuration.PowerPoints - configuration.CriticalPoints, al + range); configuration.AlacrityPoints += step ) { for ( configuration.AccuracyPoints = ac; configuration.AccuracyPoints <= Math.Min(budget - configuration.PowerPoints - configuration.CriticalPoints - configuration.AlacrityPoints, ac + range); configuration.AccuracyPoints += step ) { configuration.AugmentMasteryPoints = budget - configuration.PowerPoints - configuration.CriticalPoints - configuration.AlacrityPoints - configuration.AccuracyPoints; var dps = CalculateDps(session, configuration); if (correction.Dps < dps) { correction.Dps = dps; correction.AccuracyPoints = configuration.AccuracyPoints; correction.CriticalPoints = configuration.CriticalPoints; correction.MasteryPoints = configuration.AugmentMasteryPoints; correction.AlacrityPoints = configuration.AlacrityPoints; correction.PowerPoints = configuration.PowerPoints; } } } } } if (step == 1) return correction; return FindHighestDpsCorrection(session, configuration, correction, budget, Math.Max(step / 2, 1), step); } }
public static ConfigurationCorrection FindHighestDpsCorrection(Profile profile, Session session) { var budget = profile.Configuration.Budget; return FindHighestDpsCorrection(session, profile.Configuration.Clone(), new ConfigurationCorrection(), budget, budget/10, budget); }