/// <summary> /// Gets the amount of damage, healing, and crit chance/damage a status effect does as a list of key value pairs. /// </summary> /// <param name="character">The character to use to calculate the amount of damage and healing a status effect does.</param> /// <param name="status">The status effect to get data for.</param> /// <returns>A list of key value pairs containing the name of the stat and the value of that stat.</returns> private List <KeyValuePair <string, int> > GetStatusDamageData(Character character, StatusEffect status) { var data = new List <KeyValuePair <string, int> >(); var damage = GetElementalData(DamageCalculator.GetDamage(character, status), "Damage/Turn"); // Calculate heals int healAmount = DamageCalculator.GetHealing(character, status); int healPercent = DamageCalculator.GetHealingPercentage(character, status); bool healsOrDamage = damage.Any() || healAmount != 0 || healPercent != 0; // Add damage first data.AddRange(damage); if (healsOrDamage) { data.Add(new KeyValuePair <string, int>("Crit Chance", status.DamageCritChance + character.CritChance)); data.Add(new KeyValuePair <string, int>("Crit Damage", status.DamageCritMultiplier + character.CritMultiplier)); } // Add any healing amounts if (healAmount != 0) { data.Add(new KeyValuePair <string, int>("Health Restored/Turn", healAmount)); } if (healPercent != 0) { data.Add(new KeyValuePair <string, int>("% Health Restored/Turn", healPercent)); } return(data); }
/// <summary> /// Gets all possible actions for the active character and splits them into offensive and defensive actions, /// giving each a priority based on the amount of healing, damage, and/or ai weight provided by the action. /// </summary> /// <returns>A struct providing the action priorities of offensive and defensive actions.</returns> protected virtual ActionPriorities EvaluateActions() { var defensiveActionsPoints = new Dictionary <ActionBase, int>(); var offensiveActionsPoints = new Dictionary <ActionBase, int>(); var defensiveActionPriorities = new Dictionary <ActionBase, int>(); var offensiveActionPriorities = new Dictionary <ActionBase, int>(); var allActions = new List <ActionBase>(); allActions.AddRange(_activeCharacter.Attacks); allActions.AddRange(_activeCharacter.SpellList); allActions.AddRange(_activeCharacter.SkillList); var consumables = _activeCharacter.Inventory .Where(item => item is Consumable) .Select(item => ((Consumable)item).ItemSpell); allActions.AddRange(consumables); // Use average max health as basis for effectiveness of damage and healing int averageMaxHealth = 0; foreach (var character in AICharacters) { averageMaxHealth += character.CurrentMaxHealth; } averageMaxHealth /= AICharacters.Count(); // Calculate total healing and damage and use it to determine if an action is offensive or defensive foreach (var action in allActions) { int damage = DamageCalculator.GetDamageAsInt(_activeCharacter, action); int healing = DamageCalculator.GetHealing(_activeCharacter, action); int percentHealing = DamageCalculator.GetHealingPercentage(_activeCharacter, action); int netDamage = damage - healing; if (netDamage < 0 || percentHealing > 0 || !action.IsOffensive) { int maxPotential = -netDamage; maxPotential += (percentHealing * averageMaxHealth / 100); defensiveActionsPoints[action] = maxPotential; } else { int maxPotential = netDamage; offensiveActionsPoints[action] = maxPotential; } } int medianHealing = MathExtensions.GetMedian(defensiveActionsPoints.Values.ToList()); int medianDamage = MathExtensions.GetMedian(offensiveActionsPoints.Values.ToList()); // Assign action priorities based on how an action performs on par with other actions foreach (var key in defensiveActionsPoints.Keys) { int healing = defensiveActionsPoints[key]; defensiveActionPriorities[key] = key.AiWeight; if (medianHealing > 0) { if (PercentageCalculator.GetPercentage(healing, medianHealing) >= 150) { defensiveActionPriorities[key] += 3; } else if (PercentageCalculator.GetPercentage(healing, medianHealing) >= 120) { defensiveActionPriorities[key] += 2; } } else { defensiveActionPriorities[key] += 1; } } foreach (var key in offensiveActionsPoints.Keys) { int damage = offensiveActionsPoints[key]; offensiveActionPriorities[key] = key.AiWeight; if (medianDamage > 0) { if (PercentageCalculator.GetPercentage(damage, medianDamage) >= 150) { offensiveActionPriorities[key] += 3; } else if (PercentageCalculator.GetPercentage(damage, medianDamage) >= 120) { offensiveActionPriorities[key] += 2; } } else { offensiveActionPriorities[key] += 1; } } return(new ActionPriorities() { DefensiveActionPriorities = defensiveActionPriorities, OffensiveActionPriorities = offensiveActionPriorities }); }