/// <summary> /// Calculate all data /// </summary> /// <param name="castle">Current castle context</param> /// <param name="battle">Current battle context</param> /// <returns>Calculated data</returns> public CalculationResult Calculate(CastleRuntime castle, BattleRuntime battle) { if (castle == null) throw new ArgumentNullException("castle"); var cr = new CalculationResult(); var currentToon = GetUsedToon(castle.Toon); // Calculate and append stats provided by talents and its bonuses var talc = new TalentCalculator(commonFunctions.ApplyStatValue); talc.Calculate(GetUsedTalents(castle.TalentLevelDistribution), castle.TalentLevelDistribution, battle, cr); // Calculate and append stats provided by toon and talents might var toonc = new ToonCalculator(commonFunctions.ApplyStatValue); toonc.Calculate(currentToon, cr); // Calculate and append stats distributed in castle (such as guild bonuses, stats for character level, ect.) var sdc = new StatDistributionCalculator(commonFunctions.ApplyStatValue); sdc.Calculate(castle.CastleStatDistribution, cr); // Calculate and append values of dependent properties var dpc = new DependentPropertiesCaclulator(); dpc.Calculate(cr, currentToon.MainAttackStat, currentToon.AttackModifier); return cr; }
/// <summary> /// Append stats distributed in castle /// </summary> /// <param name="castleStatsDictionary">Stats distributed in castle</param> /// <param name="calculationResult">Current calculation result</param> public void Calculate(IDictionary<StatTypeEnum, byte> castleStatsDictionary, CalculationResult calculationResult) { if (castleStatsDictionary == null) throw new ArgumentNullException("castleStatsDictionary"); if (calculationResult == null) throw new ArgumentNullException("calculationResult"); castleStatsDictionary .ToList() .ForEach(y => applyStatValue(y.Key, y.Value, calculationResult)); }
/// <summary> /// Apply specific stat value to calculation result /// </summary> /// <param name="type">Stat type</param> /// <param name="value">Stat value</param> /// <param name="calculationResult">Current calculation result</param> public void ApplyStatValue(StatTypeEnum type, double value, CalculationResult calculationResult) { if (calculationResult == null) throw new ArgumentNullException("calculationResult"); switch (type) { case StatTypeEnum.Agility: calculationResult.Agility += value; break; // This case is included here to append attack power provided by "icy bow" talent case StatTypeEnum.Attack: calculationResult.AttackPowerLow += value; calculationResult.AttackPowerTop += value; break; case StatTypeEnum.Cunning: calculationResult.Cunning += value; break; case StatTypeEnum.Durability: calculationResult.Durability += value; break; case StatTypeEnum.Health: calculationResult.Health += value; break; case StatTypeEnum.HealthSteal: calculationResult.HealthSteal += value; break; case StatTypeEnum.Intelligence: calculationResult.Intelligence += value; break; case StatTypeEnum.Mana: calculationResult.Mana += value; break; case StatTypeEnum.Moveement: calculationResult.MovementSpeed += value; break; case StatTypeEnum.RegenerationHP: calculationResult.RegenerationHP += value; break; case StatTypeEnum.RegenerationMP: calculationResult.RegenerationMP += value; break; case StatTypeEnum.Strength: calculationResult.Strength += value; break; case StatTypeEnum.Will: calculationResult.Will += value; break; default: throw new CalculationException(string.Format("Found unsupported stat type: {0}", type)); } }
/// <summary> /// Calculates stats provided by toon at maximal level with known might /// </summary> /// <param name="currentToon">Current character</param> /// <param name="calculationResult">Calculation results, containing calculated talents data</param> public void Calculate(Toon currentToon, CalculationResult calculationResult) { if (currentToon == null) throw new ArgumentNullException("currentToon"); // Append initial stats (independent from might and talents) ApplyInitial(currentToon.InitialStats); // Append stats given by might (depends on current might value) ApplyMight(currentToon.InitialStats, calculationResult.Might); // Append all values to final result currentToon.InitialStats .ToList() .ForEach(x => applyStatValue(x.Type, x.Value, calculationResult)); }
/// <summary> /// Calculate and append dependent properties values to final result /// </summary> /// <param name="calculationResult">Current calculation result</param> /// <param name="mainStat">Main stat</param> /// <param name="attackModifier">Attack modifier value (percent)</param> public void Calculate(CalculationResult calculationResult, StatTypeEnum mainStat, double attackModifier) { if (calculationResult == null) throw new ArgumentNullException("calculationResult"); var armorPenetration = CalculateArmorPenetration(calculationResult.Agility, calculationResult.Cunning); calculationResult.ArmorPenetration = armorPenetration; var mainStatValue = GetMainStatValue(calculationResult, mainStat); var attackPower = CalculateAttackPower(mainStatValue, attackModifier); calculationResult.AttackPowerLow += attackPower.LowBorderValue; calculationResult.AttackPowerTop += attackPower.TopBorderValue; var attackSpeed = CalculateAttackSpeed(calculationResult.Agility); calculationResult.AttackSpeed = attackSpeed; var critChance = CalculateCritChance(calculationResult.Cunning); calculationResult.CritChance = critChance; var armor = CalculateResistance(calculationResult.Will, calculationResult.Durability); calculationResult.MagicalResistance = armor.First(x => x.Key == StatTypeEnum.Will).Value; calculationResult.PhisycalResistance = armor.First(x => x.Key == StatTypeEnum.Durability).Value; }
/// <summary> /// Calculate stats given by talents /// </summary> /// <param name="talentsUsed">Used talents</param> /// <param name="talentLevelDistribution">Levels for used talents</param> /// <param name="battleContext">Battle conditions description</param> /// <param name="calculationResult">Processing calculation result</param> public void Calculate(IEnumerable<Talent> talentsUsed, IDictionary<Guid, byte> talentLevelDistribution, BattleRuntime battleContext, CalculationResult calculationResult) { if (talentLevelDistribution == null) throw new ArgumentNullException("talentLevelDistribution"); if (calculationResult == null) throw new ArgumentNullException("calculationResult"); if (talentsUsed == null) throw new ArgumentNullException("talentsUsed"); // Append stats given by talent levels ApplyCastleContext(talentsUsed, talentLevelDistribution); // Append stats given by special conditions (like native land) ApplyBattleContext(talentsUsed, battleContext); // Append all values to final result talentsUsed .ToList() .ForEach(x => { calculationResult.Might += x.Might; x.Stats.ForEach(y => applyStatValue(y.Type, y.Value, calculationResult)); }); }
/// <summary> /// Get value of main stat from calculation result /// </summary> /// <param name="calculationResult">Current calculation result</param> /// <param name="mainStat">Main stat type</param> /// <returns>Main stat value</returns> private double GetMainStatValue(CalculationResult calculationResult, StatTypeEnum mainStat) { if (calculationResult == null) throw new ArgumentNullException("calculationResult"); switch (mainStat) { case StatTypeEnum.Strength: return calculationResult.Strength; case StatTypeEnum.Intelligence: return calculationResult.Intelligence; default: throw new CalculationException(string.Format("Unsupported mainstat type found: {0}", mainStat.ToString())); } }