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; }
private void SaveAsDefault() { var ability = _defaultValues.Abilities.FirstOrDefault(a => a.Ability.NameId == _sessionAbility.Ability.NameId); if (ability == null) { ability = new SessionAbility {Id = _sessionAbility.Ability.NameId}; _defaultValues.Abilities.Add(ability); } ability.SurgeBonus = SurgeBonus; ability.Autocrit = Autocrit; ability.DamageMultiplier = DamageMultiplier; ability.ArmorReduction = ArmorReduction; ability.ForceOffHand = ForceOffHand; }
public SessionAbilityViewModel(SessionAbility sessionAbility, Configuration configuration, Session defaultValues) { _sessionAbility = sessionAbility; _configuration = configuration; _defaultValues = defaultValues; UpdateCanForceOffHand(); configuration.DualWieldUpdated += UpdateCanForceOffHand; SaveAsDefaultCommand = new CommandHandler(SaveAsDefault); }
private static double GetAbilityDamage(Configuration configuration, SessionAbility ability, double energyKineticReduction, double internalElementalReduction, double defenseChance) { double damage = ( from token in ability.Ability.GetAbilityTokenDamageList(configuration, DamageRange.Average, ability.ForceOffHand) let tokenDamage = token.Sum ( action => { var modifier = Math.Min(1 - internalElementalReduction, 1); if (action.DamageType == DamageType.Kinetic || action.DamageType == DamageType.Energy) modifier = Math.Min(1, action.IsOffHand ? configuration.OffHandAccuracy : configuration.Accuracy) * Math.Min(1 - Math.Min(defenseChance, 1 + defenseChance - (action.IsOffHand ? configuration.OffHandAccuracy : configuration.Accuracy)), 1) * Math.Min(1 + ability.ArmorReduction - energyKineticReduction, 1); return action.Damage * modifier; } ) select tokenDamage * token.Multiplier ).Sum(); damage = damage + damage * ability.Autocrit * (configuration.Surge + ability.SurgeBonus) * (1 + configuration.Critical) + damage * (1 - ability.Autocrit) * configuration.Critical * (configuration.Surge + ability.SurgeBonus); return damage; }