public static void Attack(Fighter attacker, Fighter target, bool doAnimations) { IsBattling = true; int spd1 = StatsCalc.AttackSpeed(attacker.Unit.stats.speed, attacker.Weapon.weight, attacker.Unit.stats.constitution); int spd2 = StatsCalc.AttackSpeed(target.Unit.stats.speed, target.Weapon.weight, target.Unit.stats.constitution); bool repeated = StatsCalc.RepeatedAttack(spd1, spd2); bool repeatedCounter = StatsCalc.RepeatedAttack(spd2, spd1); bool counter = false; Cell[] counterArea = Map.GetExtendedArea(new Cell[1] { Map.UnitTile(target) }, target.Weapon.range, target.Weapon.rangedClosedSet, target.Weapon.closedSetMin); foreach (Cell c in counterArea) { if (c == Map.UnitTile(attacker)) { counter = true; break; } } Offensive atk1 = new Offensive(attacker, target); Offensive cnt1 = null; Offensive atk2 = null; Offensive cnt2 = null; if (counter) { cnt1 = new Offensive(target, attacker) { IsCounter = true }; } if (repeated) { atk2 = new Offensive(attacker, target, true); } if (repeatedCounter) { cnt2 = new Offensive(target, attacker, true); cnt1.IsCounter = true; } instance.StartCoroutine(DoAttacks( new Offensive[4] { atk1, cnt1, atk2, cnt2 } )); }
public Offensive(Fighter attacker, Fighter defender, bool repeated = false) { Attacker = attacker; Defender = defender; Seed = StatsCalc.Seed(new Vector2Int[2] { attacker.Position(), defender.Position() }); Rand = new System.Random(Seed); IsPhysical = Attacker.Weapon.isPhysical; AtkStat = IsPhysical ? Attacker.Unit.stats.strength : Attacker.Unit.stats.magic; DefStat = IsPhysical ? Defender.Unit.stats.defense : Defender.Unit.stats.resistance; Cell = Map.UnitTile(Attacker); Support1 = StatsCalc.SupportBonus(Attacker); Support2 = StatsCalc.SupportBonus(Defender); TriangleBonus = StatsCalc.TriangleBonus(Attacker, Defender); TerrainBonus1 = StatsCalc.TerrainBonus(Map.UnitTile(Attacker)); TerrainBonus2 = StatsCalc.TerrainBonus(Map.UnitTile(Defender)); Speed1 = Attacker.Unit.stats.speed; Speed2 = Defender.Unit.stats.speed; Wgt1 = Attacker.Weapon.weight; Wgt2 = Defender.Weapon.weight; Con1 = Attacker.Unit.stats.constitution; Con2 = Defender.Unit.stats.constitution; Attack = AtkStat; Defense = DefStat; Spd1 = StatsCalc.AttackSpeed(Speed1, Wgt1, Con1); Spd2 = StatsCalc.AttackSpeed(Speed2, Wgt2, Con2); Atk = StatsCalc.PhysicalAttack(Attack, Attacker.Weapon.might, TriangleBonus, StatsCalc.WeaponEffectiveness(Attacker.Weapon, Defender), Support1, false); Def = StatsCalc.PhysicalDefense(TerrainBonus2, Defense, Support2); HitRate = StatsCalc.HitRate(Attacker.Weapon.hit, Attacker.Unit.stats.skill, Attacker.Unit.stats.luck, Support1); Avoid = StatsCalc.Avoid(Speed2, Defender.Unit.stats.luck, TerrainBonus2, Support2); Acc = StatsCalc.Accuracy(HitRate, Avoid, TriangleBonus); CritRate = StatsCalc.CriticalRate(Attacker.Weapon.crit, Attacker.Unit.stats.skill, Support1, StatsCalc.ClassCrit(Attacker.Unit.unitClass)); CritEvade = StatsCalc.CriticalEvade(Defender.Unit.stats.luck, Support2); CritChance = StatsCalc.CriticalChance(CritRate, CritEvade); if (StatsCalc.ClassCriticalModifier.ContainsKey(Attacker.Unit.unitClass)) { CritChance += StatsCalc.ClassCriticalModifier[Attacker.Unit.unitClass]; } if (repeated) { CritChance += Attacker.Unit.stats.pursuitCriticalCoefficient; } Hit = Rand.Next(0, 100) <= Acc; Crit = Rand.Next(0, 100) <= CritChance; Damage = Crit ? StatsCalc.CriticalDamage(StatsCalc.Damage(Atk, Def)) : StatsCalc.Damage(Atk, Def); if (Attacker.LastTarget == Defender) { Attacker.RepeatedTarget++; } else { Attacker.LastTarget = Defender; Attacker.RepeatedTarget = 0; } }