public MainForm() { InitializeComponent(); database = ObjectDatabase.Database; var pw = database.GetUnitByName("Photon Walker"); var force = new Force { Name = "Robots Test", Formation = database.GetFormationByName("Rage Vindicator") }; force.AddUnit(database.GetUnitByName("Field Marshall Riggs")); for (var i = 0; i < force.Formation.AssaultSlots - 1; i++) force.AddUnit(pw); force.AddUnit(database.GetUnitByName("Mammoth Tank")); force.AddUnit(database.GetUnitByName("Beowulf Cluster")); force.AddUnit(database.GetUnitByName("Omega, Machine of War")); force.AddReinforcement(pw, 2); var enemy = new Force { Name = "Dummy", IsEpicBoss = true }; ForceReportTextBox.Text = force.ForceReport(enemy); ForceReportTextBox.SelectionStart = ForceReportTextBox.Text.Length; }
public CombatResult CalculateAverageDamage(Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { EnsureEffectProcs(); var result = new CombatResult(); foreach (var effect in Effects) { result.Add(effect.CalculateAverageDamage(myForce, enemyForce, boosts, vsEpic)); } // Apply Rally Effects - Rally will only work once for each ability and will affect abilities which deal no damage if (boosts != null) { foreach (var rallyEffect in boosts.Where(x => x.Type == EffectType.Rally)) { var abilBonus = rallyEffect.ParentAbilityProcChance*rallyEffect.EffectValue*this.ProcChance; if (HasEffect(EffectType.FlurryDamage)) { var baseBonus = abilBonus; abilBonus = 0; foreach (var effect in GetEffects(EffectType.FlurryDamage)) { abilBonus += baseBonus*effect.EffectValue; } } result.Damage += abilBonus; } } return result; }
public CombatResult CalculateAverageDamage(Force myForce, Force enemyForce, bool vsEpic = true) { var result = new CombatResult(); foreach (var ability in Abilities) { // Formations can never recieve Boosts result.Add(ability.CalculateAverageDamage(myForce, enemyForce, null, vsEpic)); } return result; }
public CombatResult CalculateAverageDamage(Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { var result = new CombatResult(); var useableBoosts = new List<Effect>(); if(boosts != null) { useableBoosts.AddRange(boosts.Where(effect => effect.IsBoostEffect() && this.IsClassification(effect.TargetType)).ToList()); } foreach (var ability in Abilities) { result.Add(ability.CalculateAverageDamage(myForce, enemyForce, useableBoosts, vsEpic)); } return result; }
public double CalculateBoostToForce(Force myForce, Force enemyForce, bool vsEpic = true) { var bonus = 0.0; var boostEffects = new List<Effect>(); foreach (var ability in Abilities) { boostEffects.AddRange(ability.GetEffects(EffectType.Rally)); boostEffects.AddRange(ability.GetEffects(EffectType.Boost)); } foreach (var effect in boostEffects) { foreach (var unit in myForce.GetUnits()) // TODO: Get this to count Reinforced units { bonus += unit.CalculateBoostBonus(myForce, enemyForce, effect, vsEpic); } } return Math.Round(bonus, 2, MidpointRounding.AwayFromZero); }
public CombatResult CalculateTotalDamageContribution(Guid claimerID, Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { var result = new CombatResult(); result.Add(this.CalculateAverageDamage(myForce, enemyForce, boosts, vsEpic)); result.Add(this.CalculateReinforcedDamage(claimerID, myForce, enemyForce, boosts, vsEpic)); return result; }
public CombatResult CalculateReinforcedDamage(Guid claimerID, Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { EnsureEffectProcs(); var result = new CombatResult(); if (HasEffect(EffectType.Reinforce) == false) { return result; } foreach (var effect in GetEffects(EffectType.Reinforce)) { result.Add(effect.CalculateReinforcedDamage(claimerID, myForce, enemyForce, boosts, vsEpic)); } return result; }
public string ForceReport(Force enemy) { ResetCombat(); var boosts = GetBoostAbilities(); var repeatedUnits = new List<Guid>(); var commandersString = new StringBuilder(); foreach (var unit in Commanders) { commandersString.Append(unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ")); } var assaultString = new StringBuilder(); foreach (var unit in AssaultUnits) { if (repeatedUnits.Contains(unit.ID)) { continue; } var count = AssaultUnits.Count(x => x.ID == unit.ID); if (unit.Abilities.Any(x => x.HasEffect(EffectType.Reinforce)) == false && count > 1) { repeatedUnits.Add(unit.ID); assaultString.AppendFormat(" {0}x {1}", count, unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ", hideNamePrefix:true)); } else { assaultString.Append(unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ")); } } var structureString = new StringBuilder(); foreach (var unit in Structures) { if (repeatedUnits.Contains(unit.ID)) { continue; } var count = AssaultUnits.Count(x => x.ID == unit.ID); if (unit.Abilities.Any(x => x.HasEffect(EffectType.Reinforce)) == false && count > 1) { repeatedUnits.Add(unit.ID); structureString.AppendFormat(" {0}x {1}", count, unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ", hideNamePrefix: true)); } else { structureString.Append(unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ")); } } var vindiFormString = new StringBuilder(); foreach (var unit in Vindicators) { vindiFormString.Append(unit.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ")); } vindiFormString.Append("\r\n"); vindiFormString.Append(Formation.DamageReport(this, enemy, boosts, enemy.IsEpicBoss, " ")); ResetCombat(); var total = CalculateAverageForceDamage(enemy); var report = string.Format(ReportTemplate, Name, Formation, commandersString, assaultString, structureString, vindiFormString, total.Damage, total.Healing, total.AntiHeal, total.Damage * 5); return report; }
public CombatResult CalculateAverageForceDamage(Force enemy) { var total = new CombatResult(); foreach (var unit in GetUnits()) { total.Add(unit.CalculateTotalDamageContribution(this, enemy, this.GetBoostAbilities(), enemy.IsEpicBoss)); } return total; }
public CombatResult CalculateReinforcedDamage(Guid claimerID, Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic) { var result = new CombatResult(); foreach (var unit in myForce.ClaimReinforcements(claimerID, TargetType, EffectValue)) { // Add each reinforced units total average damage potential (including reinforcements it might bring in too) var baseDamage = unit.CalculateTotalDamageContribution(myForce, enemyForce, boosts, vsEpic); result.Add(baseDamage.AdjustToProcChance(ParentAbilityProcChance)); } return result; }
// boosts is populated with only effects that can boost the source abilities unit public CombatResult CalculateAverageDamage(Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { var result = new CombatResult(); if (VsEpicOnly && (vsEpic == false)) { return result; } var min = Min + (vsEpic ? MinBonusVsEpic : 0); var max = Max + (vsEpic ? MaxBonusVsEpic : 0); var avg = ((min + max)/2.0); if (IsDamageEffect()) { if (Type == EffectType.FlurryDamage) { avg *= EffectValue; } if (Type == EffectType.ConditionalDamage && enemyForce != null) { avg *= enemyForce.AvgNumOfUnitTypeAfterReinforcements(TargetType); } result.Damage += (avg*ParentAbilityProcChance); // Apply Percentile Boosts if (boosts != null) { foreach (var boostEffect in boosts.Where(x => x.Type == EffectType.Boost)) { var boostBonus = 1 + (boostEffect.ParentAbilityProcChance*(boostEffect.EffectValue*0.01)); result.Damage *= boostBonus; } } } if (IsHealingEffect()) { if (Type == EffectType.ConditionalHeal && myForce != null) { avg *= myForce.AvgNumOfUnitTypeAfterReinforcements(TargetType); } result.Healing += (avg*ParentAbilityProcChance); } if (Type == EffectType.AntiHeal) { result.AntiHeal += (avg*ParentAbilityProcChance); } return result; }
public string DamageReport(Force force, Force enemy, List<Effect> boosts, bool isEpicBoss, string prefix = "") { var sb = new StringBuilder(); sb.AppendFormat(prefix + "{0} [{1}]\r\n", Name, CalculateTotalDamageContribution(force, enemy, boosts, isEpicBoss).ToSimpleString()); foreach (var ability in Abilities) { sb.AppendFormat(prefix + " * {0} [{1}]\r\n", ability.Name, ability.CalculateTotalDamageContribution(this.ID, force, enemy, null, isEpicBoss).ToSimpleString()); foreach (var reinforcement in force.GetReinforcedUnits(ID)) { sb.AppendFormat(prefix + " * Reinforced - {0}", reinforcement.DamageReport(force, enemy, boosts, isEpicBoss, prefix + "\t ")); } if(ability.HasEffect(EffectType.Boost)) { sb.AppendFormat(prefix + " * Boosts units in this force for a total bonus of {0}\r\n", CalculateBoostToForce(force, enemy, isEpicBoss)); } if(ability.HasEffect(EffectType.Rally)) { sb.AppendFormat(prefix + " * Rallies units in this force for a total bonus of {0}\r\n", CalculateBoostToForce(force, enemy, isEpicBoss)); } } return sb.ToString(); }
private void RunTests() { var database = ObjectDatabase.Database; var riggs = database.GetUnitByName("Field Marshall Riggs"); var pw = database.GetUnitByName("Photon Walker"); var mt = database.GetUnitByName("Mammoth Tank"); var beowulf = database.GetUnitByName("Beowulf Cluster"); var omega = database.GetUnitByName("Omega, Machine of War"); var rageVindi = database.GetFormationByName("Rage Vindicator"); var force = new Force { Name = "Robots Test", Formation = rageVindi }; var riggsDmg = riggs.CalculateAverageDamage(force, null, null, true); var pwNDmg = pw.CalculateAverageDamage(force, null, null, false); var pwEDmg = pw.CalculateAverageDamage(force, null, null, true); var mtDmg = mt.CalculateAverageDamage(force, null, null, true); var omegaDmg = omega.CalculateAverageDamage(force, null, null, true); var omegaBoost = pw.CalculateBoostBonus(force, null, omega.Abilities[0].Effects[0], true); var mtBoost = mt.CalculateBoostBonus(force, null, rageVindi.Abilities[0].Effects[0], true); force.AddUnit(riggs); force.AddUnit(riggs); for (int i = 0; i < force.Formation.AssaultSlots - 1; i++) force.AddUnit(pw); force.AddUnit(mt); force.AddUnit(beowulf); force.AddUnit(omega); force.AddReinforcement(pw, 2); var boosts = force.GetBoostAbilities(); var poweredPW = pw.CalculateAverageDamage(force, null, boosts, true); // This is counting the vs epic & vs non-epic twice for rallys // These don't count reinforcements from Riggs var beoBonus = beowulf.CalculateBoostToForce(force, null, true); var rvBonus = rageVindi.CalculateBoostToForce(force, null, true); var omegaBonus = omega.CalculateBoostToForce(force, null, true); var riggsReinf = riggs.CalculateReinforcedDamage(force, null, boosts, true); force.ResetCombat(); var riggsTotal = riggs.CalculateTotalDamageContribution(force, null, boosts, true); var pwTotal = pw.CalculateTotalDamageContribution(force, null, boosts, true); var mtTotal = mt.CalculateTotalDamageContribution(force, null, boosts, true); var beowulfTotal = beowulf.CalculateTotalDamageContribution(force, null, boosts, true); var omegaTotal = omega.CalculateTotalDamageContribution(force, null, boosts, true); force.ResetCombat(); var enemy = new Force { Name = "Dummy", IsEpicBoss = true }; var forceDmg = force.CalculateAverageForceDamage(enemy); }
public double CalculateBoostBonus(Force myForce, Force enemyForce, Effect boostEffect, bool vsEpic = true) { // Find all effects that can boost this unit if (IsClassification(boostEffect.TargetType) == false) { return 0.0; } var bonus = 0.0; foreach (var unitAbility in Abilities) { bonus += unitAbility.CalculateBoostBonus(myForce, enemyForce, boostEffect, vsEpic); } return Math.Round(bonus, 2, MidpointRounding.AwayFromZero); }
public CombatResult CalculateReinforcedDamage(Force myForce, Force enemyForce, List<Effect> boosts, bool vsEpic = true) { var result = new CombatResult(); foreach (var ability in Abilities.Where(x => x.HasEffect(EffectType.Reinforce))) { result.Add(ability.CalculateReinforcedDamage(this.ID, myForce, enemyForce, boosts, vsEpic)); } return result; }
// This method assumes that the effect must be able to apply to this ability public double CalculateBoostBonus(Force myForce, Force enemyForce, Effect boostEffect, bool vsEpic = true) { var bonus = 0.0; if (boostEffect.Type == EffectType.Boost) { var boostBonus = (boostEffect.ParentAbilityProcChance * (boostEffect.EffectValue * 0.01)); bonus += (CalculateAverageDamage(myForce, enemyForce, null, vsEpic).Damage * boostBonus); } else if (boostEffect.Type == EffectType.Rally) { var abilBonus = boostEffect.ParentAbilityProcChance * boostEffect.EffectValue * ProcChance; var flurryEffects = Effects.Where(x => x.Type == EffectType.FlurryDamage).ToList(); if (flurryEffects.Count > 0) { var baseBonus = abilBonus; abilBonus = 0; foreach (var flurryEffect in flurryEffects) { abilBonus += baseBonus * flurryEffect.EffectValue; } } bonus += abilBonus; } return Math.Round(bonus, 2, MidpointRounding.AwayFromZero); }
public string DamageReport(Force force, Force enemy, List<Effect> boosts, bool isEpicBoss, string prefix = "", bool hideNamePrefix = false, double reinforcementRate = 0.0) { var sb = new StringBuilder(); if (reinforcementRate > 0.0) // TODO: Better fix for this { var contrib = CalculateTotalDamageContribution(force, enemy, boosts, isEpicBoss); sb.AppendFormat((hideNamePrefix ? "" : prefix) + "{0} [{1}] at {2}% = [{3}]\r\n", Name, contrib.ToSimpleString(), reinforcementRate * 100, contrib.AdjustToProcChance(reinforcementRate).ToSimpleString()); } else { sb.AppendFormat((hideNamePrefix ? "" : prefix) + "{0} [{1}]\r\n", Name, CalculateTotalDamageContribution(force, enemy, boosts, isEpicBoss).ToSimpleString()); } var useableBoosts = new List<Effect>(); if (boosts != null) { useableBoosts.AddRange(boosts.Where(effect => effect.IsBoostEffect() && this.IsClassification(effect.TargetType)).ToList()); } foreach (var ability in Abilities) { var dmg = ability.CalculateTotalDamageContribution(this.ID, force, enemy, useableBoosts, isEpicBoss); sb.AppendFormat(prefix + " * {0} [{1}]\r\n", ability.Name, dmg.ToSimpleString()); if(dmg.DoneAnything() && useableBoosts.Count > 0) { sb.AppendFormat(prefix + " * Base [{0}]\r\n", ability.CalculateTotalDamageContribution(this.ID, force, enemy, null, isEpicBoss).ToSimpleString()); } foreach (var effect in useableBoosts) { if(IsClassification(effect.TargetType)) { sb.AppendFormat(prefix + " + {0} {1} {2}\r\n", ability.CalculateBoostBonus(force, enemy, effect, isEpicBoss), effect.ParentsName, effect.Type == EffectType.Boost ? "Boost" : "Rally"); } } var repeatedReinforcements = new List<Guid>(); foreach (var reinforcement in force.GetReinforcedUnits(ID)) { if (repeatedReinforcements.Contains(reinforcement.ID)) { continue; } var count = force.GetReinforcedUnits(ID).Count(x => x.ID == reinforcement.ID); if (reinforcement.Abilities.Any(x => x.HasEffect(EffectType.Reinforce)) == false && count > 1) { repeatedReinforcements.Add(reinforcement.ID); sb.AppendFormat(prefix + " * {0}x Reinforced - {1}", count, reinforcement.DamageReport(force, enemy, boosts, isEpicBoss, prefix + "\t ", hideNamePrefix: true, reinforcementRate: 0.5)); // TODO: Better fix for this } else { sb.AppendFormat(prefix + " * Reinforced - {0}", reinforcement.DamageReport(force, enemy, boosts, isEpicBoss, prefix + "\t ", hideNamePrefix: true)); } } if (ability.HasEffect(EffectType.Boost)) { sb.AppendFormat(prefix + " * Boosts units in this force for a total bonus of {0}\r\n", CalculateBoostToForce(force, enemy, isEpicBoss)); } if (ability.HasEffect(EffectType.Rally)) { sb.AppendFormat(prefix + " * Rallies units in this force for a total bonus of {0}\r\n", CalculateBoostToForce(force, enemy, isEpicBoss)); } } return sb.ToString(); }