private BattleResult GetBattleResult(Unit Attacker, Squad AttackerSquad, float DamageModifier, int TargetPlayerIndex, int TargetSquadIndex, int TargetUnitIndex, bool ActivateSkills, bool CalculateCritical) { Squad DefenderSquad = ListPlayer[TargetPlayerIndex].ListSquad[TargetSquadIndex]; Unit Defender = DefenderSquad[TargetUnitIndex]; ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.BeforeAttackRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.BeforeGettingAttackedRequirementName, AttackerSquad, Attacker); BattleResult Result; int BaseHitRate; BaseHitRate = CalculateHitRate(Attacker, AttackerSquad, Defender, DefenderSquad, Defender.BattleDefenseChoice); bool AttackHit = RandomHelper.RandomActivationCheck(BaseHitRate); if (AttackHit) { if (ActivateSkills) { ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.BeforeHitRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.BeforeGettingHitRequirementName, AttackerSquad, Attacker); } Result = DamageFormula(Attacker, AttackerSquad, DamageModifier, TargetPlayerIndex, TargetSquadIndex, TargetUnitIndex, Defender.BattleDefenseChoice, CalculateCritical); } else { if (ActivateSkills) { ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.BeforeMissRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.BeforeGettingMissedRequirementName, AttackerSquad, Attacker); } Result = new BattleResult(); Result.AttackDamage = 0; Result.AttackMissed = true; Result.SetTarget(TargetPlayerIndex, TargetSquadIndex, TargetUnitIndex, Defender); } Result.Accuracy = BaseHitRate; //Remove EN from the weapon cost. if (Attacker.CurrentAttack.ENCost > 0) { Result.AttackAttackerFinalEN = Math.Max(0, Attacker.EN - (Attacker.CurrentAttack.ENCost + Attacker.Boosts.ENCostModifier)); } else { Result.AttackAttackerFinalEN = Attacker.EN; } GlobalBattleContext.Result = Result; if (ActivateSkills) { Attacker.UpdateSkillsLifetime(SkillEffect.LifetimeTypeOnAttack); Defender.UpdateSkillsLifetime(SkillEffect.LifetimeTypeOnEnemyAttack); if (AttackHit) { Attacker.UpdateSkillsLifetime(SkillEffect.LifetimeTypeOnHit); Defender.UpdateSkillsLifetime(SkillEffect.LifetimeTypeOnEnemyHit); ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.AfterHitRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.AfterGettingHitRequirementName, AttackerSquad, Attacker); } else { ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.AfterMissRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.AfterGettingMissedRequirementName, AttackerSquad, Attacker); } ActivateAutomaticSkills(AttackerSquad, Attacker, DeathmatchSkillRequirement.AfterAttackRequirementName, DefenderSquad, Defender); ActivateAutomaticSkills(DefenderSquad, Defender, DeathmatchSkillRequirement.AfterGettingAttackedRequirementName, AttackerSquad, Attacker); } return(Result); }
public BattleResult DamageFormula(Unit Attacker, float DamageModifier, int Attack, int TargetPlayerIndex, int TargetSquadIndex, int TargetUnitIndex, Unit Defender, Unit.BattleDefenseChoices DefenseChoice, bool NullifyAttack, int Defense, bool CalculateCritical = false) { //FINAL DAMAGE = (((ATTACK - DEFENSE) * (ATTACKED AND DEFENDER SIZE COMPARISON)) + Additive Final Damage Bonuses) * Final Damage Multiplier Bonuses BattleResult Result = new BattleResult(); Result.SetTarget(TargetPlayerIndex, TargetSquadIndex, TargetUnitIndex, Defender); if (NullifyAttack) { Result.AttackDamage = 0; } else if (Defender.Boosts.FinalDamageTakenFixedModifier > 0) { Result.AttackDamage = Defender.Boosts.FinalDamageTakenFixedModifier; } else { Result.AttackWasCritical = false; int AttackerSize = Attacker.SizeValue; int DefenderSize = Defender.SizeValue; int AttackerSizeComparison = AttackerSize - DefenderSize; float Damage = Math.Max(0, (int)(((Attack - Defense) * (1 + AttackerSizeComparison / 100f) + Attacker.Boosts.BaseDamageModifier) * (Attacker.Boosts.BaseDamageMultiplier * Defender.Boosts.BaseDamageTakenReductionMultiplier))); if (CalculateCritical && !Attacker.Boosts.CriticalAlwaysFail) { //(((Attacker Skill Stat - Defender Skill Stat) + Weapon Critical Hit Rate) + Additive effect) * Multiplying effec int Critical = (Attacker.PilotSKL - Defender.PilotSKL) + Attacker.CurrentAttack.Critical + Attacker.Boosts.CriticalHitRateModifier; //Don't calculate critical if there is a damage multiplier. if (Attacker.Boosts.BaseDamageMultiplier == 1) { if (Attacker.Boosts.CriticalAlwaysSucceed) { Critical = 100; } } if (RandomHelper.Next(101) <= Critical) { float CriticalDamageMultiplier = 1.2f; CriticalDamageMultiplier += Attacker.Boosts.CriticalBaseDamageMultiplier; Damage += Attacker.Boosts.CriticalBaseDamageModifier; Damage *= CriticalDamageMultiplier; Damage *= Attacker.Boosts.CriticalFinalDamageMultiplier; Damage += Attacker.Boosts.CriticalFinalDamageModifier; Result.AttackWasCritical = true; } } if (DefenseChoice == Unit.BattleDefenseChoices.Defend) { Damage *= 0.5f; } Result.AttackDamage = (int)(Damage * DamageModifier) + Attacker.Boosts.FinalDamageModifier; Result.AttackDamage = (int)(Result.AttackDamage * Attacker.Boosts.FinalDamageMultiplier); } Result.AttackMissed = false; #region Sword Cut if (Result.AttackDamage > 0 && (Attacker.CurrentAttack.Sec & WeaponSecondaryProperty.SwordCut) == WeaponSecondaryProperty.SwordCut) { bool PilotSwordCut = false; bool UnitSwordCut = Defender.Boosts.SwordCutModifier; if (UnitSwordCut) { foreach (KeyValuePair <string, List <BaseEffect> > ActiveListEffect in Defender.Pilot.Effects.GetEffects()) { if (Defender.ListIgnoreSkill.Contains(ActiveListEffect.Key)) { continue; } for (int E = ActiveListEffect.Value.Count - 1; E >= 0 && !PilotSwordCut; --E) { if (ActiveListEffect.Value[E] is SwordCutEffect) { PilotSwordCut = true; } } } if (PilotSwordCut) { int SwordCutActivation = (Defender.PilotSKL - Attacker.PilotSKL) + 10; bool SwordCutActivated = RandomHelper.RandomActivationCheck(SwordCutActivation); if (SwordCutActivated) { Result.AttackMissed = true; Result.AttackSwordCut = true; } } } } #endregion #region Shoot Down if (Result.AttackDamage > 0 && (Attacker.CurrentAttack.Sec & WeaponSecondaryProperty.ShootDown) == WeaponSecondaryProperty.ShootDown) { bool PilotShootDown = false; bool UnitShootDown = Defender.Boosts.ShootDownModifier; if (UnitShootDown) { foreach (KeyValuePair <string, List <BaseEffect> > ActiveListEffect in Defender.Pilot.Effects.GetEffects()) { if (Defender.ListIgnoreSkill.Contains(ActiveListEffect.Key)) { continue; } for (int E = ActiveListEffect.Value.Count - 1; E >= 0 && !PilotShootDown; --E) { if (ActiveListEffect.Value[E] is ShootDownEffect) { PilotShootDown = true; } } } if (PilotShootDown) { int ShootDownActivation = (Defender.PilotSKL - Attacker.PilotSKL) + 10; bool ShootDownActivated = RandomHelper.RandomActivationCheck(ShootDownActivation); if (ShootDownActivated) { Result.AttackMissed = true; Result.AttackShootDown = true; } } } } #endregion #region Shield if (Result.AttackDamage > 0) { bool PilotShield = false; bool UnitShield = Defender.Boosts.ShieldModifier; if (UnitShield) { foreach (KeyValuePair <string, List <BaseEffect> > ActiveListEffect in Defender.Pilot.Effects.GetEffects()) { if (Defender.ListIgnoreSkill.Contains(ActiveListEffect.Key)) { continue; } for (int E = ActiveListEffect.Value.Count - 1; E >= 0 && !PilotShield; --E) { if (ActiveListEffect.Value[E] is ShieldEffect) { PilotShield = true; } } } if (PilotShield) { int ShieldActivation = (Defender.PilotSKL - Attacker.PilotSKL) + 10; bool ShieldActivated = RandomHelper.RandomActivationCheck(ShieldActivation); if (ShieldActivated) { Result.Shield = true; if (DefenseChoice == Unit.BattleDefenseChoices.Defend) { Result.AttackDamage = (int)(Result.AttackDamage * 0.25f); } else { Result.AttackDamage = (int)(Result.AttackDamage * 0.5f); } } } } } #endregion #region Barrier if (Result.AttackDamage > 0) { bool IsBarrierBreak = false; bool IsBarrierActive = false; for (int C = Defender.ArrayCharacterActive.Length - 1; C >= 0 && !IsBarrierBreak && !IsBarrierActive; --C) { foreach (KeyValuePair <string, List <BaseEffect> > ActiveListEffect in Defender.ArrayCharacterActive[C].Effects.GetEffects()) { if (Defender.ListIgnoreSkill.Contains(ActiveListEffect.Key)) { continue; } if (IsBarrierActive) { break; } for (int E = ActiveListEffect.Value.Count - 1; E >= 0 && !IsBarrierBreak && !IsBarrierActive; --E) { BarrierEffect ActiveBarrierEffect = ActiveListEffect.Value[E] as BarrierEffect; if (ActiveBarrierEffect != null) { int ENCost = int.Parse(ActiveParser.Evaluate(ActiveBarrierEffect.ENCost), CultureInfo.InvariantCulture); if (Result.AttackAttackerFinalEN > ENCost) { Result.AttackAttackerFinalEN -= ENCost; int BreakingDamage = int.Parse(ActiveParser.Evaluate(ActiveBarrierEffect.BreakingDamage), CultureInfo.InvariantCulture); //Look for weapon breaker or damage breaker or if the Barrier can protect against that Attack. if ((ActiveBarrierEffect.EffectiveAttacks.Count > 0 && !ActiveBarrierEffect.EffectiveAttacks.Contains(Attacker.CurrentAttack.RelativePath)) || ActiveBarrierEffect.BreakingAttacks.Contains(Attacker.CurrentAttack.RelativePath) || Result.AttackDamage >= BreakingDamage) { IsBarrierBreak = true; } else {//Look for Skill breaker. for (int C2 = Attacker.ArrayCharacterActive.Length - 1; C2 >= 0 && !IsBarrierBreak; --C2) { foreach (KeyValuePair <string, List <BaseEffect> > AttackerListEffect in Attacker.ArrayCharacterActive[C2].Effects.GetEffects()) { if (ActiveBarrierEffect.BreakingAttacks.Contains(AttackerListEffect.Key)) { IsBarrierBreak = true; break; } } } } if (!IsBarrierBreak) { IsBarrierActive = true; Result.Barrier = ActiveListEffect.Key; if (Result.AttackDamage <= 10) { if (ActiveBarrierEffect.BarrierType == BarrierEffect.BarrierTypes.Dodge) { Result.AttackMissed = true; } else if (ActiveBarrierEffect.BarrierType == BarrierEffect.BarrierTypes.Defend) { Result.AttackDamage = 0; } } else { if (ActiveBarrierEffect.BarrierType == BarrierEffect.BarrierTypes.Dodge) { Result.AttackMissed = true; } else if (ActiveBarrierEffect.BarrierType == BarrierEffect.BarrierTypes.Defend) { float DamageReduction = float.Parse(ActiveParser.Evaluate(ActiveBarrierEffect.DamageReduction), CultureInfo.InvariantCulture); if (ActiveBarrierEffect.NumberType == Operators.NumberTypes.Absolute) { Result.AttackDamage = Math.Max(0, Result.AttackDamage - (int)DamageReduction); } else if (ActiveBarrierEffect.NumberType == Operators.NumberTypes.Relative) { Result.AttackDamage = (int)(Result.AttackDamage * DamageReduction); } } } } } } } } } } #endregion return(Result); }