Пример #1
0
        public static void DrawNuclearStrikes(Player me, Player enemy, Game game, RewindClient.RewindClient rewindClient)
        {
            if (me.NextNuclearStrikeTickIndex > 0)
            {
                var nx = me.NextNuclearStrikeX;
                var ny = me.NextNuclearStrikeY;
                var nr = game.TacticalNuclearStrikeRadius;

                var nunit = UnitHelper.Units[me.NextNuclearStrikeVehicleId];

                rewindClient.Circle(nx, ny, nr, Color.FromArgb(150, 225, 0, 0));
                rewindClient.Circle(nunit.X, nunit.Y, nunit.Radius * 2, Color.Black);
                rewindClient.Line(nunit.X, nunit.Y, nx, ny, Color.Black);

                var nsRange = PotentialFieldsHelper.GetDistanceTo(nunit.X, nunit.Y, nx, ny);
                rewindClient.Message($"NuclearStrikeDistanse: {nsRange}");
            }
            if (enemy.NextNuclearStrikeTickIndex > 0)
            {
                //Врага наводчика может быть не видно
                if (UnitHelper.Units.ContainsKey(enemy.NextNuclearStrikeVehicleId))
                {
                    var nx = enemy.NextNuclearStrikeX;
                    var ny = enemy.NextNuclearStrikeY;
                    var nr = game.TacticalNuclearStrikeRadius;

                    var nunit = UnitHelper.Units[enemy.NextNuclearStrikeVehicleId];
                    rewindClient.Circle(nx, ny, nr, Color.FromArgb(150, 225, 0, 0));
                    rewindClient.Circle(nunit.X, nunit.Y, nunit.Radius * 2, Color.Black);
                }
            }
        }
Пример #2
0
        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
            });
        }