Exemple #1
0
 // Check if a point is inside the hand countour box
 public bool isPointInsideContainerBox(PointFT p)
 {
     if (p.X < rightDownCorner.X && p.X > leftUpperCorner.X
         && p.Y > leftUpperCorner.Y && p.Y < rightDownCorner.Y)
     {
         return true;
     }
     else
     {
         return false;
     }
 }
Exemple #2
0
        public Hand()
        {
            palm = new PointFT(-1, -1);
            
            fingertips = new List<PointFT>(5);
            fingertips3D = new List<Vector3FT>(5);

            contour = new List<PointFT>(2000);
            inside = new List<PointFT>(6000);

            leftUpperCorner = new PointFT(int.MaxValue, int.MaxValue);
            rightDownCorner = new PointFT(int.MinValue, int.MinValue);
        }
Exemple #3
0
        public bool isCircleInsideContainerBox(PointFT p, float r)
        {
            if (leftUpperCorner.X > p.X - r)
            {
                return false;
            }
            if (rightDownCorner.X < p.X + r)
            {
                return false;
            }
            if (leftUpperCorner.Y > p.Y - r)
            {
                return false;
            }
            if (rightDownCorner.Y < p.Y + r)
            {
                return false;
            }

            return true;
        }
        /// <summary>
        /// create depoly points for troops and spells
        /// </summary>
        private void CreateDeployPoints()
        {
            float getOutRedArea = 0.25f;

            // don't include corners in case build huts are there
            float maxRedPointX = (GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Max(point => point.X) + 1 ?? GameGrid.RedZoneExtents.MaxX) + getOutRedArea;
            float minRedPointX = (GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Min(point => point.X) - 1 ?? GameGrid.RedZoneExtents.MinX) - getOutRedArea;
            float maxRedPointY = (GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Max(point => point.Y) + 1 ?? GameGrid.RedZoneExtents.MaxY) + getOutRedArea;
            float minRedPointY = (GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Min(point => point.Y) - 1 ?? GameGrid.RedZoneExtents.MinY) - getOutRedArea;
            // build a box around the base
            PointFT left   = new PointFT(minRedPointX, maxRedPointY);
            PointFT top    = new PointFT(maxRedPointX, maxRedPointY);
            PointFT right  = new PointFT(maxRedPointX, minRedPointY);
            PointFT bottom = new PointFT(minRedPointX, minRedPointY);


            // border around the base
            _border = new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY));

            // core is center of the box
            _core = _border.GetCenter();

            PointFT[] orginPoints = new[]
            {
                new PointFT(maxRedPointX, _core.Y),
                new PointFT(minRedPointX, _core.Y),
                new PointFT(_core.X, maxRedPointY),
                new PointFT(_core.X, minRedPointY)
            };

            _orgin = new Container <PointFT> {
                Item = orginPoints.OrderBy(point => point.DistanceSq(_target)).First()
            };
            #region top right
            if (_orgin.Item.X > _core.X)
            {
                Log.Info("[Goblin Knife] Attacking from the top right");

                _attackLine = new Tuple <PointFT, PointFT>(top, right);

                _earthQuakePoint = new PointFT(_target.X + 5.5f, _core.Y);
                _jumpPoint       = new PointFT(_target.X + 5f, _core.Y);
                _healPoint       = new PointFT(_orgin.Item.X - 13f, _core.Y);
                _ragePoint       = new PointFT(_orgin.Item.X - 9f, _core.Y);
            }
            #endregion

            #region bottom left
            else if (_orgin.Item.X < _core.X)
            {
                Log.Info("[Goblin Knife] Attacking from the bottom left");

                _attackLine = new Tuple <PointFT, PointFT>(bottom, left);

                _earthQuakePoint = new PointFT(_target.X - 5.5f, _core.Y);
                _jumpPoint       = new PointFT(_target.X - 5f, _core.Y);
                _healPoint       = new PointFT(_orgin.Item.X + 13f, _core.Y);
                _ragePoint       = new PointFT(_orgin.Item.X + 9f, _core.Y);
            }
            #endregion

            #region top left
            else if (_orgin.Item.Y > _core.Y)
            {
                Log.Info("[Goblin Knife] Attacking from the top left");

                _attackLine = new Tuple <PointFT, PointFT>(left, top);

                _earthQuakePoint = new PointFT(_core.X, _target.Y + 5.5f);
                _jumpPoint       = new PointFT(_core.X, _target.Y + 5f);
                _healPoint       = new PointFT(_core.X, _orgin.Item.Y - 13f);
                _ragePoint       = new PointFT(_core.X, _orgin.Item.Y - 9f);
            }
            #endregion

            #region bottom right
            else // (orgin.Y < core.Y)
            {
                Log.Info("[Goblin Knife] Attacking from the bottom right");

                _attackLine = new Tuple <PointFT, PointFT>(right, bottom);

                _earthQuakePoint = new PointFT(_core.X, _target.Y - 5.5f);
                _jumpPoint       = new PointFT(_core.X, _target.Y - 5f);
                _healPoint       = new PointFT(_core.X, _orgin.Item.Y + 13f);
                _ragePoint       = new PointFT(_core.X, _orgin.Item.Y + 9f);
            }
            #endregion
        }
        private List<PointFT> CalculateFrontier(ref bool[][] valid, PointFT start, ref bool[][] contour)
        {
            List<PointFT> list = new List<PointFT>();
            PointFT last = new PointFT(-1, -1);
            PointFT current = new PointFT(start);
            int dir = 0;

            do
            {
                if (valid[current.X][current.Y])
                {
                    dir = (dir + 1) % 4;
                    if (current != last)
                    {
                        list.Add(new PointFT(current.X, current.Y));
                        last = new PointFT(current);
                        contour[current.X][current.Y] = false;
                    }
                }
                else
                {
                    dir = (dir + 4 - 1) % 4;
                }

                switch (dir)
                {
                    case 0: current.X += 1; break;
                    case 1: current.Y += 1; break;
                    case 2: current.X -= 1; break;
                    case 3: current.Y -= 1; break;
                }
            } while (current != start);

            return list;
        }
 public Line(PointFT start, PointFT end)
 {
     Start = start.ToScreenAbsolute();
     End   = end.ToScreenAbsolute();
 }
Exemple #7
0
        /// <summary>
        /// Prepares some stuff (baseBorder, orth from AirDefenses, intersectionPoint) which helps to calculate the actual deploypoints.
        /// </summary>
        /// <param name="airDefenses">Found AirDefenses after possible ZapQuake</param>
        /// <param name="visuals">VisualObjects for drawing information (deploypoints, orth and so on) into bmp</param>
        /// <returns></returns>
        DeployCalculationInformation PrepareDeployCalculation(AirDefense[] airDefenses, List <VisualObject> visuals)
        {
            var maxRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Max(point => point.X) + 1 ?? GameGrid.RedZoneExtents.MaxX;
            var minRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Min(point => point.X) - 1 ?? GameGrid.RedZoneExtents.MinX;
            var maxRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Max(point => point.Y) + 1 ?? GameGrid.RedZoneExtents.MaxY;
            var minRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Min(point => point.Y) - 1 ?? GameGrid.RedZoneExtents.MinY;

            // border around the base
            var baseBorder = new List <RectangleT>();

            baseBorder.Add(new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY)));

            // Add baseborder as visual
            visuals.Add(new RectangleObject("BaseBorder", Color.FromArgb(100, Color.Maroon), baseBorder, new Pen(Color.Maroon)));

            // Find nearest deploy points for two airdefenses
            var airDefensesOrderedByDeployPointDistance = airDefenses.OrderByDescending(x => SmartAirDeployHelpers.DistanceSqToClosestDeploypoint(x.Location.GetCenter()));
            var closestAirDefense    = airDefensesOrderedByDeployPointDistance.FirstOrDefault();
            var remainingAirDefenses = airDefensesOrderedByDeployPointDistance.Skip(1).ToList();
            var orderedList          = OrderByDistance(closestAirDefense, remainingAirDefenses).Take(2).ToList();

            PointF  intersectionPointF;
            PointFT intersectionPointFt;

            // 1. convert all corners into vectors
            var    left         = new PointFT(minRedPointX, maxRedPointY).ToScreenAbsolute();
            var    top          = new PointFT(maxRedPointX, maxRedPointY).ToScreenAbsolute();
            var    right        = new PointFT(maxRedPointX, minRedPointY).ToScreenAbsolute();
            var    bottom       = new PointFT(minRedPointX, minRedPointY).ToScreenAbsolute();
            Vector vLeftPoint   = new Vector(left.X, left.Y);
            Vector vTopPoint    = new Vector(top.X, top.Y);
            Vector vRightPoint  = new Vector(right.X, right.Y);
            Vector vBottomPoint = new Vector(bottom.X, bottom.Y);

            // 2. create the 4 combinations of the 4 points to get all 4 edges (topleft, topright, ...)
            var baseBorderSides = new List <Tuple <Vector, Vector> >();

            baseBorderSides.Add(Tuple.Create(vTopPoint, vLeftPoint));     // Topleft
            baseBorderSides.Add(Tuple.Create(vTopPoint, vRightPoint));    // Topright
            baseBorderSides.Add(Tuple.Create(vLeftPoint, vBottomPoint));  // BottomLeft
            baseBorderSides.Add(Tuple.Create(vRightPoint, vBottomPoint)); // BottomRight

            if (orderedList?.Count() == 2)
            {
                var start = orderedList.First().Location.GetCenter();
                var end   = orderedList.Last().Location.GetCenter();
                var airDefenseConnection = new Line(start, end);
                visuals.Add(new LinesObject("AirDefenseConnection", Color.FromArgb(180, Color.OrangeRed), new[] { airDefenseConnection }));


                Point screenStart = start.ToScreenAbsolute();
                Point screenEnd   = end.ToScreenAbsolute();

                Vector vStart = new Vector(screenStart.X, screenStart.Y);
                Vector vEnd   = new Vector(screenEnd.X, screenEnd.Y);

                Vector vStartEnd = vEnd - vStart;
                Vector vDir      = vStartEnd;
                vDir.Normalize();

                Vector vOrthDir = new Vector(vDir.Y, -vDir.X);

                Vector vOrthMidPoint = vStart + vStartEnd * 0.5;

                Point midPoint = new Point((int)vOrthMidPoint.X, (int)vOrthMidPoint.Y);

                // We have two lines (mid -> airDef1) and (mid -> airDef2)
                // We want to know what line points "away" from the townhall (center of the map)
                var    mapCenterAbsolute = new PointFT(0f, 0f).ToScreenAbsolute();
                Vector vMapCenter        = new Vector(mapCenterAbsolute.X, mapCenterAbsolute.Y);


                Vector dirTest1 = vOrthMidPoint + vOrthDir * +0.1;
                Vector dirTest2 = vOrthMidPoint + vOrthDir * -0.1;

                Vector dirAwayFromCenter = (vMapCenter - dirTest1).LengthSquared < (vMapCenter - dirTest2).LengthSquared
                    ? -vOrthDir
                    : vOrthDir;

                Vector vAirDefOrthLineEnd   = vOrthMidPoint + dirAwayFromCenter * 3000;
                Point  airDefLineEndCorrect = new Point((int)vAirDefOrthLineEnd.X, (int)vAirDefOrthLineEnd.Y);

                var orthLine = new Line(new PointF((float)vOrthMidPoint.X, (float)vOrthMidPoint.Y), new PointF(airDefLineEndCorrect.X, airDefLineEndCorrect.Y));
                visuals.Add(new LinesObject("AirDefenseOrth", new Pen(Color.OrangeRed, 3), new[] { orthLine }));

                // Now we want to find the intersection of our line, with the outer rectangle.
                // We know that our line starts inside the rect, and ends outside of it, that means there must be exactly one intersection point



                // 3. use those for the following intersection calculation:
                Vector vOrthLineStartPoint = vOrthMidPoint;
                Vector vOrthLineEndPoint   = vAirDefOrthLineEnd;
                Vector vOrth = vOrthLineStartPoint + vOrthLineEndPoint;

                // 4. test this line for intersections against all 4 sides, only (and exactly) one of them will have an intersection
                Vector vInterSectionPoint = default(Vector);
                foreach (var side in baseBorderSides)
                {
                    if (SmartAirDeployHelpers.LineSegementsIntersect(side.Item1, side.Item2, vOrthLineStartPoint, vOrthLineEndPoint, out vInterSectionPoint))
                    {
                        break;
                    }
                }
                intersectionPointF  = new PointF((float)vInterSectionPoint.X, (float)vInterSectionPoint.Y);
                intersectionPointFt = new PointFT((int)intersectionPointF.X, (int)intersectionPointF.Y);
            }
            else if (orderedList?.Count == 1)
            {
                // It's not necessary to build an orth between two AirDefenses in that case, so just find the closest deploy point to the only left AirDefense
                var start = orderedList.First().Location.GetCenter();
                var deployPointsOrderedByDistance = GameGrid.RedPoints.OrderBy(x => x.DistanceSq(start));
                intersectionPointFt = deployPointsOrderedByDistance.First();
                intersectionPointF  = intersectionPointFt.ToScreenAbsolute();
            }
            else
            {
                // No Airdefense left anymore? Then just use a random Redpoint
                intersectionPointFt = GameGrid.RedPoints.First();
                intersectionPointF  = intersectionPointFt.ToScreenAbsolute();
            }

            // 5. add that point to "visuals"
            visuals.Add(new PointsObject("IntersectionPoint", Color.FromArgb(200, Color.Cyan), new[] { intersectionPointF }));

            // 6. Chop baseborder line into points so we can determine proper deploypoints
            var baseBorderPoints = new List <PointFT>();

            foreach (var side in baseBorderSides)
            {
                baseBorderPoints.AddRange(SmartAirDeployHelpers.ChopLine(side.Item1, side.Item2));
            }


            // deployPoints = all Points within radius x
            var deployPoints = baseBorderPoints.Where(x => x.DistanceSq(intersectionPointFt) < 450).ToList();

            deployPoints = deployPoints.Select(x => x.TransformPositionAlongAxis(1)).ToList();
            deployPoints = deployPoints.Select(x => x.Constrain()).ToList();

            return(new DeployCalculationInformation(intersectionPointFt, intersectionPointF, deployPoints));
        }
Exemple #8
0
        IEnumerable <int> DeployLeftoverSpells()
        {
            var lightningSpells = deployElements.FirstOrDefault(u => u.ElementType == DeployElementType.Spell && u.Id == DeployId.Lightning);
            List <DeployElement> earthquakeSpells = deployElements.Where(u => u.ElementType == DeployElementType.Spell && u.Id == DeployId.Earthquake).ToList();
            List <DeployElement> skeletonSpells   = deployElements.Where(u => u.ElementType == DeployElementType.Spell && u.Id == DeployId.Skeleton).ToList();

            List <DeployElement> leftoverSpells = new List <DeployElement>();

            //To Prevent errors, perform a recount on all these.
            leftoverSpells.RecountAndAddIfAny(skeletonSpells);
            leftoverSpells.RecountAndAddIfAny(earthquakeSpells);
            leftoverSpells.RecountAndAddIfAny(lightningSpells);

            //Now if any Skeleton Spells exist, drop them ALL on the last air-D to Distract/Destroy.
            if (leftoverSpells.Count > 0)
            {
                yield return(Rand.Int(4000, 6000)); // pause a while longer... Dragons should be getting close to this one now...

                var adToDistract = 0;
                if (zapped1)
                {
                    adToDistract = 1;
                }
                if (zapped2)
                {
                    adToDistract = 2;
                }

                PointFT dropPoint    = new PointFT();
                string  locationDesc = string.Empty;

                if (airDefenses.Length < adToDistract + 1)
                {
                    //Only two Air Defenses were found? No Third to use spells on... drop them on A DE Collector.

                    //Put them on any Elixir Collector still up.
                    var deDrill = DarkElixirDrill.Find(CacheBehavior.ForceScan);

                    if (deDrill.Any())
                    {
                        dropPoint    = deDrill[0].Location.GetCenter();
                        locationDesc = "Dark Elixir Drill";
                    }
                    else
                    {
                        //Give up and just drop them in the middle of the map to get rid of them.
                        dropPoint    = HumanLikeAlgorithms.Origin;
                        locationDesc = "Center of map - (no other air Defenses or DE Drills Could be found)";
                    }
                }
                else
                {
                    //There were aditional air defenses found... drop them on the next one.
                    dropPoint    = airDefenses[adToDistract].Location.GetCenter();
                    locationDesc = $"Air Defense #{adToDistract + 1}";
                }

                foreach (var spell in leftoverSpells)
                {
                    Log.Info($"{Tag} Deploying {spell.Count} left over {spell.PrettyName} Spell(s) to {locationDesc}...");
                    foreach (var t in Deploy.AtPoint(spell, dropPoint, spell.Count))
                    {
                        yield return(t);
                    }
                }
            }
            else
            {
                Log.Info($"{Tag} All Spells Successfully Deployed...");
            }
        }
        private void CreateDeployPoints(bool qw)
        {
            var target = TownHall.Find()?.Location.GetCenter() ??
                         DarkElixirStorage.Find().FirstOrDefault()?.Location.GetCenter() ??
                         new PointFT(0, 0);

            // don't include corners in case build huts are there
            var maxRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Max(point => point.X) + 1 ?? GameGrid.RedZoneExtents.MaxX;
            var minRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Min(point => point.X) - 1 ?? GameGrid.RedZoneExtents.MinX;
            var maxRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Max(point => point.Y) + 1 ?? GameGrid.RedZoneExtents.MaxY;
            var minRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Min(point => point.Y) - 1 ?? GameGrid.RedZoneExtents.MinY;

            // build a box around the base
            var left   = new PointFT(minRedPointX, maxRedPointY);
            var top    = new PointFT(maxRedPointX, maxRedPointY);
            var right  = new PointFT(maxRedPointX, minRedPointY);
            var bottom = new PointFT(minRedPointX, minRedPointY);

            // border around the base
            _border = new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY));

            // core is center of the box
            _core = _border.GetCenter();

            var orginPoints = new[]
            {
                new PointFT(maxRedPointX, _core.Y),
                new PointFT(minRedPointX, _core.Y),
                new PointFT(_core.X, maxRedPointY),
                new PointFT(_core.X, minRedPointY)
            };

            _orgin = new Container <PointFT> {
                Item = orginPoints.OrderBy(point => point.DistanceSq(target)).First()
            };

            if (_orgin.Item.X > _core.X)
            {
                Log.Info("[Breakthrough] Attacking from the top right");

                var redLinePoint = GameGrid.RedPoints
                                   .Where(point => point.Y > -10 && point.Y < 10)?
                                   .Max(point => point.X) ?? GameGrid.RedZoneExtents.MaxX;

                if (qw)
                {
                    _qwPoint        = right;
                    _queenRagePoint = new PointFT(right.X - 5, right.Y + 5);
                    _healerPoint    = new PointFT(24f, -24f);
                    _attackLine     = new Tuple <PointFT, PointFT>(top, _orgin.Item.Midpoint(right));
                }
                else
                {
                    _attackLine  = new Tuple <PointFT, PointFT>(top, right);
                    _healerPoint = new PointFT(24f, _core.Y);
                }
                _healPoint = new PointFT(redLinePoint - 12f, _core.Y);
                _ragePoint = new PointFT(redLinePoint - 9f, _core.Y);
            }
            else if (_orgin.Item.X < _core.X)
            {
                Log.Info("[Breakthrough] Attacking from the bottom left");

                var redLinePoint = GameGrid.RedPoints
                                   .Where(point => point.Y > -10 && point.Y < 10)?
                                   .Min(point => point.X) ?? GameGrid.RedZoneExtents.MinX;

                if (qw)
                {
                    _qwPoint        = left;
                    _queenRagePoint = new PointFT(left.X + 5, left.Y - 5);
                    _healerPoint    = new PointFT(-24f, 24f);
                    _attackLine     = new Tuple <PointFT, PointFT>(bottom, _orgin.Item.Midpoint(left));
                }
                else
                {
                    _healerPoint = new PointFT(-24f, _core.Y);
                    _attackLine  = new Tuple <PointFT, PointFT>(bottom, left);
                }
                _healPoint = new PointFT(redLinePoint + 12, _core.Y);
                _ragePoint = new PointFT(redLinePoint + 9, _core.Y);
            }
            else if (_orgin.Item.Y > _core.Y)
            {
                Log.Info("[Breakthrough] Attacking from the top left");

                var redLinePoint = GameGrid.RedPoints
                                   .Where(point => point.X > -10 && point.X < 10)?
                                   .Max(point => point.Y) ?? GameGrid.RedZoneExtents.MaxY;

                if (qw)
                {
                    _qwPoint        = left;
                    _queenRagePoint = new PointFT(left.X + 5f, left.Y - 5f);
                    _healerPoint    = new PointFT(-24f, 24f);
                    _attackLine     = new Tuple <PointFT, PointFT>(top, _orgin.Item.Midpoint(left));
                }
                else
                {
                    _healerPoint = new PointFT(_core.X, 24f);
                    _attackLine  = new Tuple <PointFT, PointFT>(left, top);
                }
                _healPoint = new PointFT(_core.X, redLinePoint - 12f);
                _ragePoint = new PointFT(_core.X, redLinePoint - 9f);
            }
            else // (orgin.Y < core.Y)
            {
                Log.Info("[Breakthrough] Attacking from the bottom right");

                var redLinePoint = GameGrid.RedPoints
                                   .Where(point => point.X > -10 && point.X < 10)?
                                   .Min(point => point.Y) ?? GameGrid.RedZoneExtents.MinY;

                if (qw)
                {
                    _qwPoint        = right;
                    _queenRagePoint = new PointFT(right.X - 5, right.Y + 5);
                    _healerPoint    = new PointFT(24f, -24f);
                    _attackLine     = new Tuple <PointFT, PointFT>(bottom, _orgin.Item.Midpoint(right));
                }
                else
                {
                    _healerPoint = new PointFT(_core.X, -24f);
                    _attackLine  = new Tuple <PointFT, PointFT>(right, bottom);
                }
                _healPoint = new PointFT(_core.X, redLinePoint + 12);
                _ragePoint = new PointFT(_core.X, redLinePoint + 9);
            }
        }
        List <PointFT> CreateLavaHoundDeployPoints(AirDefense[] airDefenses, List <VisualObject> visuals)
        {
            // don't include corners in case build huts are there
            var maxRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Max(point => point.X) + 1 ?? GameGrid.RedZoneExtents.MaxX;
            var minRedPointX = GameGrid.RedPoints.Where(p => - 18 < p.Y && p.Y < 18)?.Min(point => point.X) - 1 ?? GameGrid.RedZoneExtents.MinX;
            var maxRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Max(point => point.Y) + 1 ?? GameGrid.RedZoneExtents.MaxY;
            var minRedPointY = GameGrid.RedPoints.Where(p => - 18 < p.X && p.X < 18)?.Min(point => point.Y) - 1 ?? GameGrid.RedZoneExtents.MinY;

            // border around the base
            var baseBorder = new List <RectangleT>();

            baseBorder.Add(new RectangleT((int)minRedPointX, (int)maxRedPointY, (int)(maxRedPointX - minRedPointX), (int)(minRedPointY - maxRedPointY)));

            // Add baseborder as visual
            visuals.Add(new RectangleObject("BaseBorder", Color.FromArgb(100, Color.Maroon), baseBorder, new Pen(Color.Maroon)));

            // Find nearest deploy points for two airdefenses
            List <PointFT> resultPoints       = new List <PointFT>();
            var            closestAirDefenses = airDefenses.OrderBy(x => SmartAirDeployHelpers.DistanceSqToClosestDeploypoint(x.Location.GetCenter())).Take(2);

            if (closestAirDefenses?.Count() == 2)
            {
                var start = closestAirDefenses.First().Location.GetCenter();
                var end   = closestAirDefenses.Last().Location.GetCenter();
                var airDefenseConnection = new Line(start, end);
                visuals.Add(new LinesObject("AirDefenseConnection", Color.FromArgb(180, Color.OrangeRed), new[] { airDefenseConnection }));


                Point screenStart = start.ToScreenAbsolute();
                Point screenEnd   = end.ToScreenAbsolute();

                Vector vStart = new Vector(screenStart.X, screenStart.Y);
                Vector vEnd   = new Vector(screenEnd.X, screenEnd.Y);

                Vector vStartEnd = vEnd - vStart;
                Vector vDir      = vStartEnd;
                vDir.Normalize();

                Vector vOrthDir = new Vector(vDir.Y, -vDir.X);

                Vector vOrthMidPoint = vStart + vStartEnd * 0.5;

                Point midPoint = new Point((int)vOrthMidPoint.X, (int)vOrthMidPoint.Y);

                // We have two lines (mid -> airDef1) and (mid -> airDef2)
                // We want to know what line points "away" from the townhall (center of the map)
                var    mapCenterAbsolute = new PointFT(0f, 0f).ToScreenAbsolute();
                Vector vMapCenter        = new Vector(mapCenterAbsolute.X, mapCenterAbsolute.Y);


                Vector dirTest1 = vOrthMidPoint + vOrthDir * +0.1;
                Vector dirTest2 = vOrthMidPoint + vOrthDir * -0.1;

                Vector dirAwayFromCenter = (vMapCenter - dirTest1).LengthSquared < (vMapCenter - dirTest2).LengthSquared
                    ? -vOrthDir
                    : vOrthDir;

                Vector vAirDefOrthLineEnd   = vOrthMidPoint + dirAwayFromCenter * 3000;
                Point  airDefLineEndCorrect = new Point((int)vAirDefOrthLineEnd.X, (int)vAirDefOrthLineEnd.Y);

                var orthLine = new Line(new PointF((float)vOrthMidPoint.X, (float)vOrthMidPoint.Y), new PointF(airDefLineEndCorrect.X, airDefLineEndCorrect.Y));
                Log.Error($"[Smart Air] Start: ({orthLine.Start.X} , {orthLine.Start.Y}), End ({orthLine.End.X}, {orthLine.End.Y})");
                visuals.Add(new LinesObject("AirDefenseOrth", new Pen(Color.OrangeRed, 3), new[] { orthLine }));

                // Now we want to find the intersection of our line, with the outer rectangle.
                // We know that our line starts inside the rect, and ends outside of it, that means there must be exactly one intersection point

                // 1. convert all corners into vectors
                var    left         = new PointFT(minRedPointX, maxRedPointY).ToScreenAbsolute();
                var    top          = new PointFT(maxRedPointX, maxRedPointY).ToScreenAbsolute();
                var    right        = new PointFT(maxRedPointX, minRedPointY).ToScreenAbsolute();
                var    bottom       = new PointFT(minRedPointX, minRedPointY).ToScreenAbsolute();
                Vector vLeftPoint   = new Vector(left.X, left.Y);
                Vector vTopPoint    = new Vector(top.X, top.Y);
                Vector vRightPoint  = new Vector(right.X, right.Y);
                Vector vBottomPoint = new Vector(bottom.X, bottom.Y);

                // 2. create the 4 combinations of the 4 points to get all 4 edges (topleft, topright, ...)
                var sidesToCheckForIntersections = new List <Tuple <Vector, Vector> >();
                sidesToCheckForIntersections.Add(Tuple.Create(vTopPoint, vLeftPoint));     // Topleft
                sidesToCheckForIntersections.Add(Tuple.Create(vTopPoint, vRightPoint));    // Topright
                sidesToCheckForIntersections.Add(Tuple.Create(vLeftPoint, vBottomPoint));  // BottomLeft
                sidesToCheckForIntersections.Add(Tuple.Create(vRightPoint, vBottomPoint)); // BottomRight

                // 3. use those for the following intersection calculation:
                Vector vOrthLineStartPoint = vOrthMidPoint;
                Vector vOrthLineEndPoint   = vAirDefOrthLineEnd;
                Vector vOrth = vOrthLineStartPoint + vOrthLineEndPoint;

                // 4. test this line for intersections against all 4 sides, only (and exactly) one of them will have an intersection
                Vector vInterSectionPoint = default(Vector);
                foreach (var side in sidesToCheckForIntersections)
                {
                    if (SmartAirDeployHelpers.LineSegementsIntersect(side.Item1, side.Item2, vOrthLineStartPoint, vOrthLineEndPoint, out vInterSectionPoint))
                    {
                        break;
                    }
                }
                var intersectionPointF  = new PointF((float)vInterSectionPoint.X, (float)vInterSectionPoint.Y);
                var intersectionPointFt = new PointFT((int)intersectionPointF.X, (int)intersectionPointF.Y);


                // 5. add that point to "visuals"
                visuals.Add(new PointsObject("IntersectionPoint", Color.FromArgb(200, Color.Cyan), new[] { intersectionPointF }));

                // deployPoints = all Points within radius x
                var deployPoints = GameGrid.RedPoints.Where(x => x.DistanceSq(intersectionPointFt) < 220).ToList();
                deployPoints = deployPoints.Select(x => x.TransformPositionAlongAxis(5)).ToList();

                // FurthestDeployPoint 1 = Furthest Point to intersectionPoint which is still inside of the radius
                var furthestDeployPoint1 = deployPoints.OrderByDescending(x => x.DistanceSq(intersectionPointFt)).First();
                // FurthestDeployPoint 2 = Furthest Point to intersectionPoint which is still inside of the radius
                var furthestDeployPoint2 = deployPoints.OrderByDescending(x => x.DistanceSq(furthestDeployPoint1)).First();

                var lavaHoundDeployPoints = new List <PointFT>();
                lavaHoundDeployPoints.Add(furthestDeployPoint1);
                lavaHoundDeployPoints.Add(furthestDeployPoint2);

                visuals.Add(new PointsObject("LavaHoundDeployPoints", Color.FromArgb(200, Color.Pink), lavaHoundDeployPoints));
                visuals.Add(new PointsObject("AttackUnitDeployPoints", Color.FromArgb(110, Color.Black), deployPoints));
            }

            return(resultPoints);
        }
Exemple #11
0
        public override IEnumerable <int> AttackRoutine()
        {
            int waveLimit   = UserSettings.WaveSize;
            int waveDelay   = (int)(UserSettings.WaveDelay * 1000);
            int heroesIndex = -1;

            var core = new PointFT(-0.01f, 0.01f);

            // Points to draw lines in deploy extends area.
            var topLeft  = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY);
            var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2);

            var rightTop    = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2);
            var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY);

            // Move 8 tiles from bottom corner due to unitsbar.
            var bottomLeft  = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8);
            var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY);

            var leftTop    = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY);
            var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2);

            var linesPointsList = new List <PointFT>
            {
                topLeft, topRight,
                rightTop, rightBottom,
                bottomLeft, bottomRight,
                leftBottom, leftTop
            };

            // Main four lines of attack.
            var topRightLine    = new Tuple <PointFT, PointFT>(topRight, rightTop);
            var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom);
            var bottomLeftLine  = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom);
            var topLeftLine     = new Tuple <PointFT, PointFT>(topLeft, leftTop);

            // List of the four attack lines in clocwise order
            var attackLines = new List <Tuple <PointFT, PointFT> >
            {
                topLeftLine,
                topRightLine,
                bottomRightLine,
                bottomLeftLine
            };

            var deployHeroesAt = GetCurrentSetting("Deploy Heroes At");


            var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);

            var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault();
            var nearestLinePoint        = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault();

            heroesIndex = attackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y));

            var units  = Deploy.GetTroops();
            var heroes = units.Extract(x => x.IsHero);
            var cc     = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops);
            var spells = units.Extract(u => u.ElementType == DeployElementType.Spell);

            units.OrderForDeploy();

            // Set first attack line
            // Start from the next line to user defined to end with user defined line
            var line  = attackLines.NextOf(attackLines[heroesIndex]);
            var index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

            Log.Info($"{AttackName} {Version} starts");
            // Start troops deployment on four sides.
            for (var i = 4; i >= 1; i--)
            {
                foreach (var unit in units)
                {
                    if (unit?.Count > 0)
                    {
                        var count   = unit.Count / i;
                        var fingers = count % 4 <= 1 ? count : 4;
                        foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay))
                        {
                            yield return(t);
                        }
                    }
                }
                if (i != 1)
                {
                    line  = attackLines.NextOf(attackLines[index]);
                    index = attackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);
                }
            }

            if (cc?.Count > 0)
            {
                Log.Info($"{AttackName} Deploy Clan Castle troops");
                foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                {
                    yield return(t);
                }
            }

            if (heroes.Any())
            {
                Log.Info($"{AttackName} Deploy Heroes");
                foreach (var hero in heroes.Where(u => u.Count > 0))
                {
                    foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                    {
                        yield return(t);
                    }
                }
                Deploy.WatchHeroes(heroes, 5000);
            }


            var minDEDrillLevel = GetCurrentSetting("Min Drill Level");

            // start smart zap
            if (GetCurrentSetting("Smart Zap Drills") == 1)
            {
                var waitBeforeSmartZap = GetCurrentSetting("Start Zap Drills After ?(sec)") * 1000;
                var minDEAmount        = GetCurrentSetting("Min Dark Elixir per Zap");


                yield return(waitBeforeSmartZap);

                foreach (var t in SmartZapping.SmartZap(minDEAmount, minDEDrillLevel, spells))
                {
                    yield return(t);
                }
            }

            // start Use EarthQuake spell on drills
            if (GetCurrentSetting("Use EarthQuake spell on drills") == 1)
            {
                foreach (var t in SmartZapping.UseEQOnDrills(minDEDrillLevel, spells))
                {
                    yield return(t);
                }
            }

            // end battle
            var endBattleTime = GetCurrentSetting("End Battle after zap ?(sec)");

            foreach (var t in SmartZapping.EndBattle(endBattleTime))
            {
                yield return(t);
            }
        }
        public override IEnumerable <int> AttackRoutine()
        {
            // Set start battle time.
            startTime = DateTime.Now;

            int waveLimit   = UserSettings.WaveSize;
            int waveDelay   = (int)(UserSettings.WaveDelay * 1000);
            int heroesIndex = -1;

            // Set the core point of the base
            SmartFourFingersHelper.SetCore();

            if (!IsTargetsCalculated)
            {
                SmartFourFingersHelper.CalculateTargets();
            }


            // Points to draw lines in deploy extends area.
            var topLeft  = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY);
            var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2);

            var rightTop    = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2);
            var rightBottom = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MinY);

            // Move 8 tiles from bottom corner due to unitsbar.
            var bottomLeft  = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8);
            var bottomRight = new PointFT((float)GameGrid.MinX + 8, (float)GameGrid.DeployExtents.MinY);

            var leftTop    = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY);
            var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2);

            var linesPointsList = new List <PointFT>
            {
                topLeft, topRight,
                rightTop, rightBottom,
                bottomLeft, bottomRight,
                leftBottom, leftTop
            };

            // Main four lines of attack.
            var topRightLine    = new Tuple <PointFT, PointFT>(topRight, rightTop);
            var bottomRightLine = new Tuple <PointFT, PointFT>(bottomRight, rightBottom);
            var bottomLeftLine  = new Tuple <PointFT, PointFT>(bottomLeft, leftBottom);
            var topLeftLine     = new Tuple <PointFT, PointFT>(topLeft, leftTop);

            // List of the four attack lines in clocwise order
            AttackLines = new List <Tuple <PointFT, PointFT> >
            {
                topRightLine,
                bottomRightLine,
                bottomLeftLine,
                topLeftLine
            };



            var deployHeroesAt = GetCurrentSetting("Deploy Heroes At");


            var target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);

            // Search for target if not found for 3 more times
            if (target.X == 0f && target.Y == 0f)
            {
                for (var i = 1; i <= 3; i++)
                {
                    yield return(1000);

                    target = SmartFourFingersHelper.GetHeroesTarget(deployHeroesAt);
                    if (target.X != 0f || target.Y != 0f)
                    {
                        break;
                    }
                }
            }

            var nearestRedPointToTarget = GameGrid.RedPoints.OrderBy(p => p.DistanceSq(target)).FirstOrDefault();
            var nearestLinePoint        = linesPointsList.OrderBy(p => p.DistanceSq(nearestRedPointToTarget)).FirstOrDefault();

            heroesIndex = AttackLines.FindIndex(u => (u.Item1.X == nearestLinePoint.X && u.Item1.Y == nearestLinePoint.Y) || (u.Item2.X == nearestLinePoint.X && u.Item2.Y == nearestLinePoint.Y));

            var units  = Deploy.GetTroops();
            var heroes = units.Extract(x => x.IsHero);
            var cc     = units.ExtractOne(u => u.ElementType == DeployElementType.ClanTroops);
            var spells = units.Extract(u => u.ElementType == DeployElementType.Spell);

            units.OrderForDeploy();

            // Set first attack line
            // Start from the next line to user defined to end with user defined line
            var line  = AttackLines.NextOf(AttackLines[heroesIndex]);
            var index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

            var deploymentMode = GetCurrentSetting("Set Troops Deployment");

            if (deploymentMode == 2)
            {
                AddFakeTargets();
            }

            var targetsCount = TargetsAtLine[index];

            Log.Info($"{AttackName} {Version} starts");
            // Start troops deployment on four sides.
            for (var i = 4; i >= 1; i--)
            {
                Log.Info($"Targets at this side = {targetsCount} targets from total {TotalTargetsCount} targets");
                foreach (var unit in units)
                {
                    if (unit?.Count > 0)
                    {
                        var count   = deploymentMode == 0 ? unit.Count / i : (TotalTargetsCount > 0 ? unit.Count * targetsCount / TotalTargetsCount : 0);
                        var housing = unit.UnitData.HousingSpace;
                        var fingers = housing < 4 ? (count < 8 ? count : 4) : 1;

                        Log.Info($"{AttackName} Deploy {count}x {unit.PrettyName}");
                        foreach (var t in Deploy.AlongLine(unit, line.Item1, line.Item2, count, fingers, 0, waveDelay))
                        {
                            yield return(t);
                        }
                    }
                }

                if (i != 1)
                {
                    line  = AttackLines.NextOf(AttackLines[index]);
                    index = AttackLines.FindIndex(u => u.Item1.X == line.Item1.X && u.Item1.Y == line.Item1.Y);

                    TotalTargetsCount -= targetsCount;
                    targetsCount       = TargetsAtLine[index];
                }
            }

            if (cc?.Count > 0)
            {
                Log.Info($"{AttackName} Deploy Clan Castle troops");
                foreach (var t in Deploy.AlongLine(cc, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                {
                    yield return(t);
                }
            }

            if (heroes.Any())
            {
                Log.Info($"{AttackName} Deploy Heroes");
                foreach (var hero in heroes.Where(u => u.Count > 0))
                {
                    foreach (var t in Deploy.AlongLine(hero, line.Item1, line.Item2, 1, 1, 0, waveDelay))
                    {
                        yield return(t);
                    }
                }
                Deploy.WatchHeroes(heroes, 5000);
            }

            // Call FinalizeAttack and ForceZap at the same time
            var zapSpells = Deploy.GetTroops().Extract(u => u.ElementType == DeployElementType.Spell);

            if (spells.Extract(u => u.Id == DeployId.Lightning).Sum(u => u.Count) > 0 ||
                spells.Extract(u => u.Id == DeployId.Earthquake).Sum(u => u.Count) > 0)
            {
                var finalize = this.FinalizeAttack(units).GetEnumerator();
                var force    = ForceZap().GetEnumerator();

                var firstEnumMoreItems  = finalize.MoveNext();
                var secondEnumMoreItems = force.MoveNext();

                // Start both FinalizeAttack and ForceZap
                while (firstEnumMoreItems && secondEnumMoreItems)
                {
                    firstEnumMoreItems  = finalize.MoveNext();
                    secondEnumMoreItems = force.MoveNext();
                    yield return(200);
                }
                // Complete ForceZap if FinalizeAttack finished
                while (!firstEnumMoreItems && secondEnumMoreItems)
                {
                    secondEnumMoreItems = force.MoveNext();
                    yield return(200);
                }
                // Complete FinalizeAttack if ForceZap finished
                while (!secondEnumMoreItems && firstEnumMoreItems)
                {
                    firstEnumMoreItems = finalize.MoveNext();
                    yield return(200);
                }
            }
            else
            {
                yield break;
            }
        }
Exemple #13
0
        // Calculate the contour box of the hand if it possible
        public bool calculateContainerBox(float reduction = 0)
        {
            if (contour != null && contour.Count > 0)
            {
                for (int j = 0; j < contour.Count; ++j)
                {
                    if (leftUpperCorner.X > contour[j].X)
                        leftUpperCorner.X = contour[j].X;

                    if (rightDownCorner.X < contour[j].X)
                        rightDownCorner.X = contour[j].X;

                    if (leftUpperCorner.Y > contour[j].Y)
                        leftUpperCorner.Y = contour[j].Y;

                    if (rightDownCorner.Y < contour[j].Y)
                        rightDownCorner.Y = contour[j].Y;
                }

                int incX = (int)((rightDownCorner.X - leftUpperCorner.X) * (reduction / 2));
                int incY = (int)((rightDownCorner.Y - leftUpperCorner.Y) * (reduction / 2));
                PointFT inc = new PointFT(incX, incY);
                leftUpperCorner = leftUpperCorner + inc;
                rightDownCorner = rightDownCorner + inc;

                return true;
            }
            else
            {
                return false;
            }
        }
Exemple #14
0
 // Normalize in the interval [-1, 1] the given 3D point.
 // The Z value is in the inverval [-1, 0], being 0 the closest distance.
 private Vector3FT transformTo3DCoord(PointFT p, int width, int height, int distance)
 {
     Vector3FT v = new Vector3FT();
     v.X = p.Y / (width * 1.0f) * 2 - 1;
     v.Y = (1 - p.X / (height * 1.0f)) * 2 - 1;
     v.Z = (distance - 400) / -7600.0f;
     return v;
 }
Exemple #15
0
 /// <summary>
 /// Find the area of a triangle. This function uses the 1/2 determinant
 /// </summary>
 /// <param name="v1">triangle point1</param>
 /// <param name="v2">triangle point2</param>
 /// <param name="v3">triangle point3</param>
 /// <returns>triangle area</returns>
 public static float CalcTriArea(PointFT v1, PointFT v2, PointFT v3)
 {
     return(Math.Abs((v1.X * (v2.Y - v3.Y) + v2.X * (v3.Y - v1.Y) + v3.X * (v1.Y - v2.Y)) / 2f));
 }
 /// <summary>
 /// Returns the distance in tiles from the center of a building to a specific X,Y Coordiante Point.
 /// </summary>
 /// <param name="building"></param>
 /// <param name="x"></param>
 /// <param name="y"></param>
 /// <returns></returns>
 public static double DistanceFromPoint(this Building building, PointFT point)
 {
     return(DistanceFromPoint(building, point.X, point.Y));
 }
Exemple #17
0
        public static PointFT GetClosestPointToLine(this Tuple <PointFT, PointFT> line, PointFT P)
        {
            PointFT a_to_p = new PointFT
                             (
                P.X - line.Item1.X,
                P.Y - line.Item1.Y
                             ),
                    a_to_b = new PointFT
                             (
                line.Item2.X - line.Item1.X,
                line.Item2.Y - line.Item1.Y //     # Storing vector A->B
                             );

            float atb2        = a_to_b.X * a_to_b.X + a_to_b.Y * a_to_b.Y;
            float atp_dot_atb = a_to_p.X * a_to_b.X + a_to_p.Y * a_to_b.Y; // The dot product of a_to_p and a_to_b
            float t           = atp_dot_atb / atb2;                        //  # The normalized "distance" from a to the closest point

            return(new PointFT(line.Item1.X + a_to_b.X * t, line.Item1.Y + a_to_b.Y * t));
        }
Exemple #18
0
        /// <summary>
        /// Set deploy points for troops and spells
        /// </summary>
        public static void SetDeployPoints()
        {
            // Top right side
            var topRight = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MaxY - 2);
            var rightTop = new PointFT((float)GameGrid.DeployExtents.MaxX, (float)GameGrid.MinY + 2);

            // Bottom right side
            var rightBottom = new PointFT((float)GameGrid.MaxX - 5, (float)GameGrid.DeployExtents.MinY);
            var bottomRight = new PointFT((float)GameGrid.MinX + 10, (float)GameGrid.DeployExtents.MinY);

            // Bottom left side
            // Move 8 tiles from bottom corner due to unitsbar.
            var bottomLeft = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MinY + 8);
            var leftBottom = new PointFT((float)GameGrid.DeployExtents.MinX, (float)GameGrid.MaxY - 2);

            // Top Left side
            var leftTop = new PointFT((float)GameGrid.MinX + 2, (float)GameGrid.DeployExtents.MaxY);
            var topLeft = new PointFT((float)GameGrid.MaxX - 2, (float)GameGrid.DeployExtents.MaxY);

            var isJumpSpell = Deploy.GetTroops().ExtractOne(DeployId.Jump)?.Count > 0 ? true : false;


            if (AllInOnePushDeploy.Origin.X > AllInOnePushDeploy.Core.X)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] Attacking from the top right");

                AllInOnePushDeploy.AttackLine = new Tuple <PointFT, PointFT>(topRight, rightTop);

                var distance = Math.Abs(AllInOnePushDeploy.Origin.X) - Math.Abs(AllInOnePushDeploy.Target.X);
                var target   = distance >= AllInOnePushDeploy.MinDistace ? AllInOnePushDeploy.Target : AllInOnePushDeploy.Core;

                var firstWall = GetFirstWallForJump(AllInOnePushDeploy.Origin.Y, "Y");
                AllInOnePushDeploy.FirstJumpPoint = new PointFT(firstWall.X - 2.75f, AllInOnePushDeploy.Core.Y);

                var maxX  = isJumpSpell ? AllInOnePushDeploy.FirstJumpPoint.X - 5f : firstWall.X - 1.5f;
                var start = target.X + 4f;

                var earthQuakePoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Target.X + 6f, AllInOnePushDeploy.Core.Y)
                };
                var jumpPoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Target.X + 5.5f, AllInOnePushDeploy.Core.Y)
                };

                if (GetWallsInsideSpell(earthQuakePoints[0], 4f) < 8)
                {
                    while (maxX > start)
                    {
                        earthQuakePoints.Add(new PointFT(start, AllInOnePushDeploy.Core.Y));
                        jumpPoints.Add(new PointFT(start - 0.5f, AllInOnePushDeploy.Core.Y));
                        start += 0.25f;
                    }
                }

                AllInOnePushDeploy.EqPoint = earthQuakePoints.OrderByDescending(e => GetWallsInsideSpell(e)).FirstOrDefault();

                // Prevent overlaping EQ with jump
                if (isJumpSpell && AllInOnePushDeploy.FirstJumpPoint.X - AllInOnePushDeploy.EqPoint.X < 7f)
                {
                    AllInOnePushDeploy.EqPoint = new PointFT(AllInOnePushDeploy.FirstJumpPoint.X - 7f, AllInOnePushDeploy.FirstJumpPoint.Y);
                }
                AllInOnePushDeploy.SecondJumpPoint = new PointFT(AllInOnePushDeploy.EqPoint.X - 0.5f, AllInOnePushDeploy.EqPoint.Y);

                var shiftSpells = AllInOnePushDeploy.ShiftSpells;
                AllInOnePushDeploy.FirstRagePoint  = new PointFT(AllInOnePushDeploy.Origin.X - 11f - shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.FirstHealPoint  = new PointFT(AllInOnePushDeploy.Origin.X - 17f - shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.SecondRagePoint = new PointFT(AllInOnePushDeploy.Origin.X - 22f - shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.FirstHastePoint = new PointFT(AllInOnePushDeploy.Origin.X - 26f - shiftSpells, AllInOnePushDeploy.Core.Y);

                //try to find better funneling points
                var frac = 0.65f;

                AllInOnePushDeploy.FirstFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.X - AllInOnePushDeploy.Origin.X),
                                                                      AllInOnePushDeploy.Origin.Y + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.Y - AllInOnePushDeploy.Origin.Y));

                AllInOnePushDeploy.SecondFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                       (AllInOnePushDeploy.AttackLine.Item2.X - AllInOnePushDeploy.Origin.X),
                                                                       AllInOnePushDeploy.Origin.Y + frac *
                                                                       (AllInOnePushDeploy.AttackLine.Item2.Y - AllInOnePushDeploy.Origin.Y));

                AllInOnePushDeploy.FirstHasteLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X - 11f - shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X - 11f - shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                    );
                AllInOnePushDeploy.FirstRageLine = new Tuple <PointFT, PointFT>
                                                   (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X - 19f - shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X - 19f - shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                   );

                AllInOnePushDeploy.SecondHasteLine = new Tuple <PointFT, PointFT>
                                                     (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X - 24f - shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X - 24f - shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                     );
                AllInOnePushDeploy.SecondRageLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X - 24f - shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X - 24f - shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                    );

                AllInOnePushDeploy.QWHealer    = new PointFT(GameGrid.DeployExtents.MaxX, AllInOnePushDeploy.FirstFunnellingPoint.Y);
                AllInOnePushDeploy.QWRagePoint = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X - 2, AllInOnePushDeploy.FirstFunnellingPoint.Y);
            }

            else if (AllInOnePushDeploy.Origin.X < AllInOnePushDeploy.Core.X)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] Attacking from the bottom left");

                AllInOnePushDeploy.AttackLine = new Tuple <PointFT, PointFT>(leftBottom, bottomLeft);

                var distance = Math.Abs(AllInOnePushDeploy.Origin.X) - Math.Abs(AllInOnePushDeploy.Target.X);
                var target   = distance >= AllInOnePushDeploy.MinDistace ? AllInOnePushDeploy.Target : AllInOnePushDeploy.Core;

                var firstWall = GetFirstWallForJump(AllInOnePushDeploy.Origin.Y, "Y");
                AllInOnePushDeploy.FirstJumpPoint = new PointFT(firstWall.X + 2.75f, AllInOnePushDeploy.Core.Y);

                var maxX  = isJumpSpell ? AllInOnePushDeploy.FirstJumpPoint.X + 5f : firstWall.X + 1.5f;
                var start = target.X - 4f;

                var earthQuakePoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Target.X - 6f, AllInOnePushDeploy.Core.Y)
                };
                var jumpPoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Target.X - 5.5f, AllInOnePushDeploy.Core.Y)
                };

                if (GetWallsInsideSpell(earthQuakePoints[0], 4f) < 8)
                {
                    while (maxX < start)
                    {
                        earthQuakePoints.Add(new PointFT(start, AllInOnePushDeploy.Core.Y));
                        jumpPoints.Add(new PointFT(start + 0.5f, AllInOnePushDeploy.Core.Y));
                        start -= 0.25f;
                    }
                }

                AllInOnePushDeploy.EqPoint = earthQuakePoints.OrderByDescending(e => GetWallsInsideSpell(e)).FirstOrDefault();

                // Prevent overlaping EQ with jump
                if (isJumpSpell && Math.Abs(AllInOnePushDeploy.FirstJumpPoint.X - AllInOnePushDeploy.EqPoint.X) < 7f)
                {
                    AllInOnePushDeploy.EqPoint = new PointFT(AllInOnePushDeploy.FirstJumpPoint.X + 7f, AllInOnePushDeploy.FirstJumpPoint.Y);
                }

                AllInOnePushDeploy.SecondJumpPoint = new PointFT(AllInOnePushDeploy.EqPoint.X + 0.5f, AllInOnePushDeploy.EqPoint.Y);

                var shiftSpells = AllInOnePushDeploy.ShiftSpells;
                AllInOnePushDeploy.FirstRagePoint  = new PointFT(AllInOnePushDeploy.Origin.X + 11f + shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.FirstHealPoint  = new PointFT(AllInOnePushDeploy.Origin.X + 17f + shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.SecondRagePoint = new PointFT(AllInOnePushDeploy.Origin.X + 22f + shiftSpells, AllInOnePushDeploy.Core.Y);
                AllInOnePushDeploy.FirstHastePoint = new PointFT(AllInOnePushDeploy.Origin.X + 26f + shiftSpells, AllInOnePushDeploy.Core.Y);

                //try to find better funneling points
                var frac = 0.65f;

                AllInOnePushDeploy.FirstFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.X - AllInOnePushDeploy.Origin.X),
                                                                      AllInOnePushDeploy.Origin.Y + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.Y - AllInOnePushDeploy.Origin.Y));

                AllInOnePushDeploy.SecondFunnellingPoint = bottomLeft;

                AllInOnePushDeploy.FirstHasteLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X + 11f + shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X + 11f + shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                    );

                AllInOnePushDeploy.FirstRageLine = new Tuple <PointFT, PointFT>
                                                   (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X + 19f + shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X + 19f + shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                   );

                AllInOnePushDeploy.SecondHasteLine = new Tuple <PointFT, PointFT>
                                                     (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X + 24f + shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X + 24f + shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                     );

                AllInOnePushDeploy.SecondRageLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X + 24f + shiftSpells, AllInOnePushDeploy.FirstFunnellingPoint.Y),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X + 24f + shiftSpells, AllInOnePushDeploy.SecondFunnellingPoint.Y)
                                                    );

                AllInOnePushDeploy.QWHealer    = new PointFT(GameGrid.DeployExtents.MinX, AllInOnePushDeploy.FirstFunnellingPoint.Y);
                AllInOnePushDeploy.QWRagePoint = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X + 2, AllInOnePushDeploy.FirstFunnellingPoint.Y);
            }

            else if (AllInOnePushDeploy.Origin.Y > AllInOnePushDeploy.Core.Y)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] Attacking from the top left");

                AllInOnePushDeploy.AttackLine = new Tuple <PointFT, PointFT>(leftTop, topLeft);

                var distance = Math.Abs(AllInOnePushDeploy.Origin.Y) - Math.Abs(AllInOnePushDeploy.Target.Y);
                var target   = distance >= AllInOnePushDeploy.MinDistace ? AllInOnePushDeploy.Target : AllInOnePushDeploy.Core;

                var firstWall = GetFirstWallForJump(AllInOnePushDeploy.Origin.X, "X");
                AllInOnePushDeploy.FirstJumpPoint = new PointFT(AllInOnePushDeploy.Core.X, firstWall.Y - 2.75f);

                var maxX  = isJumpSpell ? AllInOnePushDeploy.FirstJumpPoint.Y - 5f : firstWall.Y - 1.5f;
                var start = target.Y + 4f;

                var earthQuakePoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Target.Y + 6f)
                };
                var jumpPoints = new List <PointFT> {
                    new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Target.Y + 5.5f)
                };

                if (GetWallsInsideSpell(earthQuakePoints[0], 4f) < 8)
                {
                    while (maxX > start)
                    {
                        earthQuakePoints.Add(new PointFT(AllInOnePushDeploy.Core.X, start));
                        jumpPoints.Add(new PointFT(AllInOnePushDeploy.Core.X, start - 0.5f));
                        start += 0.25f;
                    }
                }

                AllInOnePushDeploy.EqPoint = earthQuakePoints.OrderByDescending(e => GetWallsInsideSpell(e)).FirstOrDefault();

                // Prevent overlaping EQ with jump
                if (isJumpSpell && AllInOnePushDeploy.FirstJumpPoint.Y - AllInOnePushDeploy.EqPoint.Y < 7f)
                {
                    AllInOnePushDeploy.EqPoint = new PointFT(AllInOnePushDeploy.FirstJumpPoint.X, AllInOnePushDeploy.FirstJumpPoint.Y - 7f);
                }
                AllInOnePushDeploy.SecondJumpPoint = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.EqPoint.Y - 0.5f);

                var shiftSpells = AllInOnePushDeploy.ShiftSpells;
                AllInOnePushDeploy.FirstRagePoint  = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y - 11f - shiftSpells);
                AllInOnePushDeploy.FirstHealPoint  = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y - 17f - shiftSpells);
                AllInOnePushDeploy.SecondRagePoint = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y - 22f - shiftSpells);
                AllInOnePushDeploy.FirstHastePoint = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y - 26f - shiftSpells);

                //try to find better funneling points
                var frac = 0.65f;

                AllInOnePushDeploy.FirstFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.X - AllInOnePushDeploy.Origin.X),
                                                                      AllInOnePushDeploy.Origin.Y + frac *
                                                                      (AllInOnePushDeploy.AttackLine.Item1.Y - AllInOnePushDeploy.Origin.Y));

                AllInOnePushDeploy.SecondFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                       (AllInOnePushDeploy.AttackLine.Item2.X - AllInOnePushDeploy.Origin.X),
                                                                       AllInOnePushDeploy.Origin.Y + frac *
                                                                       (AllInOnePushDeploy.AttackLine.Item2.Y - AllInOnePushDeploy.Origin.Y));

                AllInOnePushDeploy.FirstHasteLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y - 11f - shiftSpells),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y - 11f - shiftSpells)
                                                    );

                AllInOnePushDeploy.FirstRageLine = new Tuple <PointFT, PointFT>
                                                   (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y - 19f - shiftSpells),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y - 19f - shiftSpells)
                                                   );

                AllInOnePushDeploy.SecondHasteLine = new Tuple <PointFT, PointFT>
                                                     (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y - 24f - shiftSpells),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y - 24f - shiftSpells)
                                                     );

                AllInOnePushDeploy.SecondRageLine = new Tuple <PointFT, PointFT>
                                                    (
                    new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y - 24f - shiftSpells),
                    new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y - 24f - shiftSpells)
                                                    );

                AllInOnePushDeploy.QWHealer    = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, GameGrid.DeployExtents.MaxY);
                AllInOnePushDeploy.QWRagePoint = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y - 2);
            }

            else // (orgin.Y < core.Y)
            {
                Log.Info($"[{AllInOnePushDeploy.AttackName}] Attacking from the bottom right");

                // Avoid bottom right side until fix zoom out on attack progress issue
                var avoidBottomRight = true;
                if (avoidBottomRight)
                {
                    var originPoints = new[]
                    {
                        new PointFT(GameGrid.DeployExtents.MaxX, AllInOnePushDeploy.Core.Y),
                        new PointFT(GameGrid.DeployExtents.MinX, AllInOnePushDeploy.Core.Y),
                        new PointFT(AllInOnePushDeploy.Core.X, GameGrid.DeployExtents.MaxY),
                        new PointFT(AllInOnePushDeploy.Core.X, GameGrid.DeployExtents.MinY)
                    };
                    AllInOnePushDeploy.Origin = originPoints.OrderBy(point => point.DistanceSq(AllInOnePushDeploy.Target)).ElementAt(1);
                    Log.Warning($"Avoid bottom right side set to true, We will attack from next closest side to the target");

                    SetDeployPoints();
                }
                else
                {
                    AllInOnePushDeploy.AttackLine = new Tuple <PointFT, PointFT>(rightBottom, bottomRight);

                    var distance = Math.Abs(AllInOnePushDeploy.Origin.Y) - Math.Abs(AllInOnePushDeploy.Target.Y);
                    var target   = distance >= AllInOnePushDeploy.MinDistace ? AllInOnePushDeploy.Target : AllInOnePushDeploy.Core;

                    var firstWall = GetFirstWallForJump(AllInOnePushDeploy.Origin.X, "X");
                    AllInOnePushDeploy.FirstJumpPoint = new PointFT(AllInOnePushDeploy.Core.X, firstWall.Y + 2.75f);

                    var maxX  = isJumpSpell ? AllInOnePushDeploy.FirstJumpPoint.Y + 5f : firstWall.Y + 1.5f;
                    var start = target.Y - 4f;

                    var earthQuakePoints = new List <PointFT> {
                        new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Target.Y - 6f)
                    };
                    var jumpPoints = new List <PointFT> {
                        new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Target.Y - 5.5f)
                    };

                    if (GetWallsInsideSpell(earthQuakePoints[0], 4f) < 8)
                    {
                        while (maxX < start)
                        {
                            earthQuakePoints.Add(new PointFT(AllInOnePushDeploy.Core.X, start));
                            jumpPoints.Add(new PointFT(AllInOnePushDeploy.Core.X, start + 0.5f));
                            start -= 0.25f;
                        }
                    }

                    AllInOnePushDeploy.EqPoint = earthQuakePoints.OrderByDescending(e => GetWallsInsideSpell(e)).FirstOrDefault();

                    // Prevent overlaping EQ with jump
                    if (isJumpSpell && Math.Abs(AllInOnePushDeploy.FirstJumpPoint.Y - AllInOnePushDeploy.EqPoint.Y) < 7f)
                    {
                        AllInOnePushDeploy.EqPoint = new PointFT(AllInOnePushDeploy.FirstJumpPoint.X, AllInOnePushDeploy.FirstJumpPoint.Y + 7f);
                    }
                    AllInOnePushDeploy.SecondJumpPoint = new PointFT(AllInOnePushDeploy.EqPoint.X, AllInOnePushDeploy.EqPoint.Y + 0.5f);

                    var shiftSpells = AllInOnePushDeploy.ShiftSpells;
                    AllInOnePushDeploy.FirstRagePoint  = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y + 11f + shiftSpells);
                    AllInOnePushDeploy.FirstHealPoint  = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y + 17f + shiftSpells);
                    AllInOnePushDeploy.SecondRagePoint = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y + 22f + shiftSpells);
                    AllInOnePushDeploy.FirstHastePoint = new PointFT(AllInOnePushDeploy.Core.X, AllInOnePushDeploy.Origin.Y + 26f + shiftSpells);

                    //try to find better funneling points
                    var frac = 0.65f;

                    AllInOnePushDeploy.FirstFunnellingPoint = new PointFT(AllInOnePushDeploy.Origin.X + frac *
                                                                          (AllInOnePushDeploy.AttackLine.Item1.X - AllInOnePushDeploy.Origin.X),
                                                                          AllInOnePushDeploy.Origin.Y + frac *
                                                                          (AllInOnePushDeploy.AttackLine.Item1.Y - AllInOnePushDeploy.Origin.Y));

                    AllInOnePushDeploy.SecondFunnellingPoint = bottomRight;

                    AllInOnePushDeploy.FirstHasteLine = new Tuple <PointFT, PointFT>
                                                        (
                        new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y + 11f + shiftSpells),
                        new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y + 11f + shiftSpells)
                                                        );

                    AllInOnePushDeploy.FirstRageLine = new Tuple <PointFT, PointFT>
                                                       (
                        new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y + 19f + shiftSpells),
                        new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y + 19f + shiftSpells)
                                                       );

                    AllInOnePushDeploy.SecondHasteLine = new Tuple <PointFT, PointFT>
                                                         (
                        new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y + 24f + shiftSpells),
                        new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y + 24f + shiftSpells)
                                                         );

                    AllInOnePushDeploy.SecondRageLine = new Tuple <PointFT, PointFT>
                                                        (
                        new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y + 24f + shiftSpells),
                        new PointFT(AllInOnePushDeploy.SecondFunnellingPoint.X, AllInOnePushDeploy.SecondFunnellingPoint.Y + 24f + shiftSpells)
                                                        );

                    AllInOnePushDeploy.QWHealer    = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, GameGrid.DeployExtents.MinY);
                    AllInOnePushDeploy.QWRagePoint = new PointFT(AllInOnePushDeploy.FirstFunnellingPoint.X, AllInOnePushDeploy.FirstFunnellingPoint.Y + 1);
                }
            }
        }