private static MyLivingUnit[] GetAllyUnitsInRangeOfNuclearStrike() { var nsRadius = GlobalHelper.Game.TacticalNuclearStrikeRadius; var allyUnitsInEnemyNs = UnitHelper.UnitsAlly .Where(x => GeometryHelper.PointIsWithinCircle(LastEnemyNuclearStrikeX, LastEnemyNuclearStrikeY, nsRadius, x.X, x.Y)) .ToArray(); return(allyUnitsInEnemyNs); }
public static HasTargetToNuclearAttackResult HasTargetToNuclearAttack(MyLivingUnit[] selectedUnits) { var allEnemiesCanBeAttacked = new Dictionary <long, List <MyLivingUnit> >(); foreach (var selectedUnit in selectedUnits) { var enemyUnitsInRange = UnitHelper.UnitsEnemy .Where(x => { var visionRange = GetVisionRangeByWeather(selectedUnit); return(GeometryHelper.PointIsWithinCircle(selectedUnit.X, selectedUnit.Y, visionRange, x.X, x.Y)); }).ToArray(); foreach (var enemyUnitInRange in enemyUnitsInRange) { var enemyId = enemyUnitInRange.Id; if (!allEnemiesCanBeAttacked.ContainsKey(enemyId)) { allEnemiesCanBeAttacked[enemyId] = new List <MyLivingUnit>(); } allEnemiesCanBeAttacked[enemyId].Add(selectedUnit); } } if (allEnemiesCanBeAttacked.Count == 0) { return(new HasTargetToNuclearAttackResult() { Success = false }); } var enemiesCanBeAttacked = allEnemiesCanBeAttacked.Select(x => UnitHelper.Units[x.Key]).ToList(); var nsRange = GlobalHelper.Game.TacticalNuclearStrikeRadius; var maxNsDamage = GlobalHelper.Game.MaxTacticalNuclearStrikeDamage; var enemiesWithDamage = new List <Tuple <MyLivingUnit, double> >(allEnemiesCanBeAttacked.Count); var minEnemiesToAttack = GetMinEnemiesToAttackNuclearStrike(); foreach (var enemyCanBeAttacked in enemiesCanBeAttacked) { var allEnemiesFromEnemyRange = UnitHelper.UnitsEnemy .Where(x => GeometryHelper.PointIsWithinCircle(enemyCanBeAttacked.X, enemyCanBeAttacked.Y, nsRange, x.X, x.Y)).ToArray(); if (allEnemiesFromEnemyRange.Length < minEnemiesToAttack) { continue; } double totalDamage = 0; foreach (var enemyFromEnemyRange in allEnemiesFromEnemyRange) { var distance = PotentialFieldsHelper.GetDistanceTo(enemyCanBeAttacked.X, enemyCanBeAttacked.Y, enemyFromEnemyRange.X, enemyFromEnemyRange.Y); //Урон - это расстояние от эпиценра * урон var damage = ((nsRange - distance) / nsRange) * maxNsDamage; var speedDamageCoef = GetDamageCoefficientByVehicleTypeSpeed(enemyFromEnemyRange.Type); damage *= speedDamageCoef; if (damage > enemyFromEnemyRange.Durability) { totalDamage += maxNsDamage; } else { totalDamage += damage; } } var allAlliesFromEnemyRange = UnitHelper.UnitsAlly .Where(x => GeometryHelper.PointIsWithinCircle(enemyCanBeAttacked.X, enemyCanBeAttacked.Y, nsRange, x.X, x.Y)).ToArray(); foreach (var allyFromEnemyRange in allAlliesFromEnemyRange) { var distance = PotentialFieldsHelper.GetDistanceTo(enemyCanBeAttacked.X, enemyCanBeAttacked.Y, allyFromEnemyRange.X, allyFromEnemyRange.Y); //Урон - это расстояние от эпиценра * урон var damage = ((nsRange - distance) / nsRange) * maxNsDamage; if (damage > allyFromEnemyRange.Durability) { totalDamage -= 100; } else { totalDamage -= damage; } } enemiesWithDamage.Add(new Tuple <MyLivingUnit, double>(enemyCanBeAttacked, totalDamage)); } if (enemiesWithDamage.Count == 0) { return(new HasTargetToNuclearAttackResult() { Success = false }); } var maxTotalDamage = enemiesWithDamage.Select(x => x.Item2).Max(); //Выгода по урону не в пользу нас, не планируем удар if (maxTotalDamage < 0) { return(new HasTargetToNuclearAttackResult() { Success = false }); } var enemyUnitWithMaxDamage = enemiesWithDamage.First(x => Math.Abs(x.Item2 - maxTotalDamage) < 0.00000001).Item1; #if DEBUG RewindClient.RewindClient.Instance.Circle(enemyUnitWithMaxDamage.X, enemyUnitWithMaxDamage.Y, enemyUnitWithMaxDamage.Radius * 3, Color.Red); #endif var alliesCanAttackEnemyWithMaxDamage = allEnemiesCanBeAttacked[enemyUnitWithMaxDamage.Id]; var alliesWithRange = alliesCanAttackEnemyWithMaxDamage.Select(x => new { Ally = x, Range = GeometryHelper.GetDistancePower2To(x.X, x.Y, enemyUnitWithMaxDamage.X, enemyUnitWithMaxDamage.Y) }).ToList(); var maxRange = alliesWithRange.Select(x => x.Range).Max(); var ally = alliesWithRange.First(x => Math.Abs(x.Range - maxRange) < 0.00000001).Ally; #if DEBUG RewindClient.RewindClient.Instance.Circle(ally.X, ally.Y, ally.Radius * 3, Color.Purple); var vr = GetVisionRangeByWeather(ally); RewindClient.RewindClient.Instance.Circle(ally.X, ally.Y, vr, Color.FromArgb(100, 255, 0, 200)); #endif return(new HasTargetToNuclearAttackResult() { Success = true, SelectedUnitRes = ally, EnemyRes = enemyUnitWithMaxDamage }); }