Beispiel #1
0
        /// <summary>
        ///     Returns the possible targets of a prediction input source.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PossibleTarget" /> list.</returns>
        internal static List<PossibleTarget> GetPossibleTargets(PredictionInput input)
        {
            var result = new List<PossibleTarget>();

            foreach (var enemy in
                GameObjects.EnemyHeroes.Where(
                    h =>
                    !h.Compare(input.Unit)
                    && h.LSIsValidTarget(input.Range + 200 + input.RealRadius, true, input.RangeCheckFrom)))
            {
                var inputs = input.Clone() as PredictionInput;

                if (inputs == null)
                {
                    continue;
                }

                inputs.Unit = enemy;
                var prediction = Movement.GetPrediction(inputs, false, true);

                if (prediction.Hitchance >= HitChance.High)
                {
                    result.Add(new PossibleTarget { Position = prediction.UnitPosition.ToVector2(), Unit = enemy });
                }
            }

            return result;
        }
Beispiel #2
0
        /// <summary>
        ///     Returns an Area of Effect Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns>
        ///     <see cref="PredictionOutput" /> output
        /// </returns>
        public static PredictionOutput GetAoEPrediction(PredictionInput input)
        {
            switch (input.Type)
            {
                case SkillshotType.SkillshotCircle:
                    return Circle.GetCirclePrediction(input);
                case SkillshotType.SkillshotCone:
                    return Cone.GetConePrediction(input);
                case SkillshotType.SkillshotLine:
                    return Line.GetLinePrediction(input);
            }

            return new PredictionOutput();
        }
        /// <summary>
        ///     Returns the possible targets of a prediction input source.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PossibleTarget" /> list.</returns>
        internal static List<PossibleTarget> GetPossibleTargets(PredictionInput input)
        {
            var result = new List<PossibleTarget>();
            var originalUnit = input.Unit;
            foreach (var enemy in
                GameObjects.EnemyHeroes.Where(
                    h =>
                    h.NetworkId != originalUnit.NetworkId
                    && h.IsValidTarget(input.Range + 200 + input.RealRadius, true, input.RangeCheckFrom)))
            {
                input.Unit = enemy;
                var prediction = Movement.GetPrediction(input, false, false);
                if (prediction.Hitchance >= HitChance.High)
                {
                    result.Add(new PossibleTarget { Position = prediction.UnitPosition.ToVector2(), Unit = enemy });
                }
            }

            return result;
        }
Beispiel #4
0
        /// <summary>
        ///     Returns Immobile Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="remainingImmobileT">Remaining Immobile Time</param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetImmobilePrediction(PredictionInput input, double remainingImmobileT)
        {
            var result = new PredictionOutput
            {
                Input = input,
                CastPosition = input.Unit.ServerPosition,
                UnitPosition = input.Unit.ServerPosition,
                Hitchance = HitChance.High
            };
            var timeToReachTargetPosition = input.Delay
                                            + (Math.Abs(input.Speed - float.MaxValue) > float.Epsilon
                                                   ? input.Unit.Distance(input.From) / input.Speed
                                                   : 0);

            if (timeToReachTargetPosition <= remainingImmobileT + input.RealRadius / input.Unit.MoveSpeed)
            {
                result.UnitPosition = input.Unit.Position;
                result.Hitchance = HitChance.Immobile;
            }

            return result;
        }
Beispiel #5
0
        /// <summary>
        ///     Returns the list of the units that the skill-shot will hit before reaching the set positions.
        /// </summary>
        /// <param name="positions">
        ///     The positions.
        /// </param>
        /// <param name="input">
        ///     The input.
        /// </param>
        /// <returns>
        ///     A list of <c>Obj_AI_Base</c>s which the input collides with.
        /// </returns>
        public static List <Obj_AI_Base> GetCollision(List <Vector3> positions, PredictionInput input)
        {
            var result = new List <Obj_AI_Base>();

            foreach (var position in positions)
            {
                if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
                {
                    result.AddRange(
                        GameObjects.EnemyMinions.Where(i => i.IsMinion() || i.IsPet())
                        .Concat(GameObjects.Jungle)
                        .Where(
                            minion =>
                            minion.IsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom) && IsHitCollision(minion, input, position, 20)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
                {
                    result.AddRange(
                        GameObjects.EnemyHeroes.Where(
                            hero =>
                            hero.IsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom) && IsHitCollision(hero, input, position, 50)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls))
                {
                    var step = position.Distance(input.From) / 20;
                    for (var i = 0; i < 20; i++)
                    {
                        if (input.From.ToVector2().Extend(position, step * i).IsWall())
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall))
                {
                    if (yasuoWallLeft == null || yasuoWallRight == null)
                    {
                        continue;
                    }

                    yasuoWallPoly = new RectanglePoly(yasuoWallLeft.Position, yasuoWallRight.Position, 75);

                    var intersections = new List <Vector2>();
                    for (var i = 0; i < yasuoWallPoly.Points.Count; i++)
                    {
                        var inter =
                            yasuoWallPoly.Points[i].Intersection(
                                yasuoWallPoly.Points[i != yasuoWallPoly.Points.Count - 1 ? i + 1 : 0],
                                input.From.ToVector2(),
                                position.ToVector2());

                        if (inter.Intersects)
                        {
                            intersections.Add(inter.Point);
                        }
                    }

                    if (intersections.Count > 0)
                    {
                        result.Add(GameObjects.Player);
                    }
                }
            }

            return(result.Distinct().ToList());
        }
Beispiel #6
0
        private static HitChance GetHitChance(PredictionInput input)
        {
            var hero = input.Unit as AIHeroClient;

            if (hero == null || !hero.IsValid || input.Radius <= 1f)
            {
                return(HitChance.VeryHigh);
            }

            if (hero.IsCastingInterruptableSpell(true) || hero.LSIsRecalling() ||
                (UnitTracker.GetLastStopTick(hero) < 0.1d && hero.IsRooted))
            {
                return(HitChance.VeryHigh);
            }

            var wayPoints          = hero.GetWaypoints();
            var lastWaypoint       = wayPoints.Last();
            var heroServerPos      = hero.ServerPosition.ToVector2();
            var heroPos            = hero.Position;
            var distHeroToWaypoint = heroServerPos.Distance(lastWaypoint);
            var distHeroToFrom     = heroServerPos.Distance(input.From);
            var distFromToWaypoint = input.From.Distance(lastWaypoint);
            var angle = (lastWaypoint - heroPos.ToVector2()).AngleBetween(input.From - heroPos);
            var delay = input.Delay
                        + (Math.Abs(input.Speed - float.MaxValue) > float.Epsilon ? distHeroToFrom / input.Speed : 0);
            var moveArea = hero.MoveSpeed * delay;
            var fixRange = moveArea * 0.35f;
            var minPath  = 800 + moveArea;

            if (input.Type == SkillshotType.SkillshotCircle)
            {
                fixRange -= input.Radius / 2;
            }

            if (distFromToWaypoint <= distHeroToFrom && distHeroToFrom > input.Range - fixRange)
            {
                return(HitChance.Medium);
            }

            if (distHeroToWaypoint > 0 && distHeroToWaypoint < 50)
            {
                return(HitChance.Medium);
            }

            if (wayPoints.Count == 1)
            {
                return(hero.Spellbook.IsAutoAttacking || UnitTracker.GetLastStopTick(hero) < 0.8d
                           ? HitChance.High
                           : HitChance.VeryHigh);
            }

            if (UnitTracker.IsSpamSamePos(hero))
            {
                return(HitChance.VeryHigh);
            }

            if (distHeroToFrom < 250 || hero.MoveSpeed < 250 || distFromToWaypoint < 250)
            {
                return(HitChance.VeryHigh);
            }

            if (distHeroToWaypoint > minPath)
            {
                return(HitChance.VeryHigh);
            }

            if (hero.HealthPercent < 20 || GameObjects.Player.HealthPercent < 20)
            {
                return(HitChance.VeryHigh);
            }

            if (input.Type == SkillshotType.SkillshotCircle && GamePath.PathTracker.GetCurrentPath(hero).Time < 0.1d &&
                distHeroToWaypoint > fixRange)
            {
                return(HitChance.VeryHigh);
            }

            if (distHeroToWaypoint > 0)
            {
                if (angle < 20 || angle > 150)
                {
                    return(HitChance.VeryHigh);
                }

                var wallPoints = new List <Vector2>();

                for (var i = 1; i <= 15; i++)
                {
                    var circleAngle = i * 2 * Math.PI / 15;
                    var point       = new Vector2(
                        heroPos.X + 450 * (float)Math.Cos(circleAngle),
                        heroPos.Y + 450 * (float)Math.Sin(circleAngle));

                    if (point.IsWall())
                    {
                        wallPoints.Add(point);
                    }
                }

                if (wallPoints.Count > 2 && !wallPoints.Any(i => heroPos.Distance(i) > lastWaypoint.Distance(i)))
                {
                    return(HitChance.VeryHigh);
                }
            }

            return(HitChance.Medium);
        }
Beispiel #7
0
        /// <summary>
        ///     Get Position on Unit's Path.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="path">Path in Vector2 List</param>
        /// <param name="speed">Unit Speed</param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1)
        {
            speed = Math.Abs(speed - -1) < float.Epsilon ? input.Unit.MoveSpeed : speed;

            if (path.Count <= 1)
            {
                return(new PredictionOutput
                {
                    Input = input,
                    UnitPosition = input.Unit.ServerPosition,
                    CastPosition = input.Unit.ServerPosition,
                    Hitchance = HitChance.High
                });
            }

            var pLength = path.PathLength();
            var dist    = input.Delay * speed - input.RealRadius;

            // Skillshots with only a delay
            if (pLength >= dist && Math.Abs(input.Speed - float.MaxValue) < float.Epsilon)
            {
                var tDistance = dist;

                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a = path[i];
                    var b = path[i + 1];
                    var d = a.Distance(b);

                    if (d >= tDistance)
                    {
                        var direction = (b - a).LSNormalized();
                        var cp        = a + direction * tDistance;
                        var p         = a
                                        + direction
                                        * (i == path.Count - 2
                                       ? Math.Min(tDistance + input.RealRadius, d)
                                       : tDistance + input.RealRadius);

                        return(new PredictionOutput
                        {
                            Input = input,
                            CastPosition = cp.ToVector3(),
                            UnitPosition = p.ToVector3(),
                            Hitchance = HitChance.High
                        });
                    }

                    tDistance -= d;
                }
            }

            // Skillshot with a delay and speed.
            if (pLength >= dist && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var tDistance = dist;

                if ((input.Type == SkillshotType.SkillshotLine || input.Type == SkillshotType.SkillshotCone) &&
                    input.Unit.DistanceSquared(input.From) < 200 * 200)
                {
                    tDistance = dist - input.RealRadius;
                }

                path = path.CutPath(tDistance);
                var tT = 0f;

                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a         = path[i];
                    var b         = path[i + 1];
                    var tB        = a.Distance(b) / speed;
                    var direction = (b - a).LSNormalized();
                    a = a - speed * tT * direction;
                    var sol = a.VectorMovementCollision(b, speed, input.From.ToVector2(), input.Speed, tT);
                    var t   = (float)sol[0];
                    var pos = (Vector2)sol[1];

                    if (pos.IsValid() && t >= tT && t <= tT + tB)
                    {
                        if (pos.LSDistanceSquared(b) < 20)
                        {
                            break;
                        }

                        var p = pos + input.RealRadius * direction;

                        /*if (input.Type == SkillshotType.SkillshotLine)
                         * {
                         *  var alpha = (input.From.ToVector2() - p).AngleBetween(a - b);
                         *
                         *  if (alpha > 30 && alpha < 180 - 30)
                         *  {
                         *      var beta = (float)Math.Asin(input.RealRadius / p.Distance(input.From));
                         *      var cp1 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(beta);
                         *      var cp2 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(-beta);
                         *
                         *      pos = cp1.DistanceSquared(pos) < cp2.DistanceSquared(pos) ? cp1 : cp2;
                         *  }
                         * }*/

                        return(new PredictionOutput
                        {
                            Input = input,
                            CastPosition = pos.ToVector3(),
                            UnitPosition = p.ToVector3(),
                            Hitchance = HitChance.High
                        });
                    }

                    tT += tB;
                }
            }

            var position = path.Last().ToVector3();

            return(new PredictionOutput
            {
                Input = input, CastPosition = position, UnitPosition = position, Hitchance = HitChance.Medium
            });
        }
        /// <summary>
        ///     Get Position on Unit's Path.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="path">Path in Vector2 List</param>
        /// <param name="speed">Unit Speed</param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetPositionOnPath(PredictionInput input, List<Vector2> path, float speed = -1)
        {
            speed = (Math.Abs(speed - (-1)) < float.Epsilon) ? input.Unit.MoveSpeed : speed;

            if (path.Count <= 1)
            {
                return new PredictionOutput
                           {
                               Input = input, UnitPosition = input.Unit.ServerPosition,
                               CastPosition = input.Unit.ServerPosition, Hitchance = HitChance.VeryHigh
                           };
            }

            var pLength = path.PathLength();

            // Skillshots with only a delay
            if (pLength >= (input.Delay * speed) - input.RealRadius
                && Math.Abs(input.Speed - float.MaxValue) < float.Epsilon)
            {
                var tDistance = (input.Delay * speed) - input.RealRadius;

                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a = path[i];
                    var b = path[i + 1];
                    var d = a.Distance(b);

                    if (d >= tDistance)
                    {
                        var direction = (b - a).Normalized();

                        var cp = a + (direction * tDistance);
                        var p = a
                                + (direction
                                   * ((i == path.Count - 2)
                                          ? Math.Min(tDistance + input.RealRadius, d)
                                          : (tDistance + input.RealRadius)));

                        return new PredictionOutput
                                   {
                                       Input = input, CastPosition = cp.ToVector3(), UnitPosition = p.ToVector3(),
                                       Hitchance =
                                           GamePath.PathTracker.GetCurrentPath(input.Unit).Time < 0.1d
                                               ? HitChance.VeryHigh
                                               : HitChance.High
                                   };
                    }

                    tDistance -= d;
                }
            }

            // Skillshot with a delay and speed.
            if (pLength >= (input.Delay * speed) - input.RealRadius
                && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                path = path.CutPath(Math.Max(0, (input.Delay * speed) - input.RealRadius));
                var tT = 0f;
                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a = path[i];
                    var b = path[i + 1];
                    var tB = a.Distance(b) / speed;
                    var direction = (b - a).Normalized();
                    a = a - (speed * tT * direction);
                    var sol = a.VectorMovementCollision(b, speed, input.From.ToVector2(), input.Speed, tT);
                    var t = (float)sol[0];
                    var pos = (Vector2)sol[1];

                    if (pos.IsValid() && t >= tT && t <= tT + tB)
                    {
                        var p = pos + (input.RealRadius * direction);

                        if (input.Type == SkillshotType.SkillshotLine)
                        {
                            var alpha = (input.From.ToVector2() - p).AngleBetween(a - b);
                            if (alpha > 30 && alpha < 180 - 30)
                            {
                                var beta = (float)Math.Asin(input.RealRadius / p.Distance(input.From));
                                var cp1 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(beta);
                                var cp2 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(-beta);

                                pos = cp1.DistanceSquared(pos) < cp2.DistanceSquared(pos) ? cp1 : cp2;
                            }
                        }

                        return new PredictionOutput
                                   {
                                       Input = input, CastPosition = pos.ToVector3(), UnitPosition = p.ToVector3(),
                                       Hitchance =
                                           GamePath.PathTracker.GetCurrentPath(input.Unit).Time < 0.1d
                                               ? HitChance.VeryHigh
                                               : HitChance.High
                                   };
                    }

                    tT += tB;
                }
            }

            var position = path.Last();
            return new PredictionOutput
                       {
                           Input = input, CastPosition = position.ToVector3(), UnitPosition = position.ToVector3(),
                           Hitchance = HitChance.Medium
                       };
        }
        /// <summary>
        ///     Returns Dashing Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetDashingPrediction(PredictionInput input)
        {
            var dashData = input.Unit.GetDashInfo();
            var result = new PredictionOutput { Input = input };
            input.Delay += 0.1f;

            // Normal dashes.
            if (!dashData.IsBlink)
            {
                // Mid air:
                var dashPred = GetPositionOnPath(
                    input,
                    new List<Vector2> { input.Unit.ServerPosition.ToVector2(), dashData.Path.Last() },
                    dashData.Speed);
                if (dashPred.Hitchance >= HitChance.High)
                {
                    dashPred.CastPosition = dashPred.UnitPosition;
                    dashPred.Hitchance = HitChance.Dashing;
                    return dashPred;
                }

                // At the end of the dash:
                if (dashData.Path.PathLength() > 200)
                {
                    var endP = dashData.Path.Last();
                    var timeToPoint = input.Delay + (input.From.Distance(endP) / input.Speed);
                    if (timeToPoint
                        <= (input.Unit.Distance(endP) / dashData.Speed) + (input.RealRadius / input.Unit.MoveSpeed))
                    {
                        return new PredictionOutput
                                   {
                                       CastPosition = endP.ToVector3(), UnitPosition = endP.ToVector3(),
                                       Hitchance = HitChance.Dashing
                                   };
                    }
                }

                result.CastPosition = dashData.Path.Last().ToVector3();
                result.UnitPosition = result.CastPosition;

                // Figure out where the unit is going.
            }

            return result;
        }
        /// <summary>
        ///     Returns the list of the units that the skill-shot will hit before reaching the set positions.
        /// </summary>
        /// <param name="positions">
        ///     The positions.
        /// </param>
        /// <param name="input">
        ///     The input.
        /// </param>
        /// <returns>
        ///     A list of <c>Obj_AI_Base</c>s which the input collides with.
        /// </returns>
        public static List<Obj_AI_Base> GetCollision(List<Vector3> positions, PredictionInput input)
        {
            var result = new List<Obj_AI_Base>();

            foreach (var position in positions)
            {
                if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
                {
                    foreach (var minion in
                        GameObjects.EnemyMinions.Where(
                            minion =>
                            minion.IsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom)))
                    {
                        input.Unit = minion;
                        var minionPrediction = Movement.GetPrediction(input, false, false);
                        if (minionPrediction.UnitPosition.ToVector2()
                                .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                            <= Math.Pow(input.Radius + 15 + minion.BoundingRadius, 2))
                        {
                            result.Add(minion);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
                {
                    foreach (var hero in
                        GameObjects.EnemyHeroes.Where(
                            hero =>
                            hero.IsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom)))
                    {
                        input.Unit = hero;
                        var prediction = Movement.GetPrediction(input, false, false);
                        if (prediction.UnitPosition.ToVector2()
                                .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                            <= Math.Pow(input.Radius + 50 + hero.BoundingRadius, 2))
                        {
                            result.Add(hero);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls))
                {
                    var step = position.Distance(input.From) / 20;
                    for (var i = 0; i < 20; i++)
                    {
                        var p = input.From.ToVector2().Extend(position.ToVector2(), step * i);
                        if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall))
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall))
                {
                    if (Variables.TickCount - wallCastT > 4000)
                    {
                        continue;
                    }

                    GameObject wall = null;
                    foreach (var gameObject in
                        GameObjects.AllGameObjects.Where(
                            gameObject =>
                            gameObject.IsValid
                            && Regex.IsMatch(gameObject.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase)))
                    {
                        wall = gameObject;
                    }

                    if (wall == null)
                    {
                        break;
                    }

                    var level = wall.Name.Substring(wall.Name.Length - 6, 1);
                    var wallWidth = 300 + (50 * Convert.ToInt32(level));

                    var wallDirection = (wall.Position.ToVector2() - yasuoWallCastedPos).Normalized().Perpendicular();
                    var wallStart = wall.Position.ToVector2() + (wallWidth / 2f * wallDirection);
                    var wallEnd = wallStart - (wallWidth * wallDirection);

                    if (wallStart.Intersection(wallEnd, position.ToVector2(), input.From.ToVector2()).Intersects)
                    {
                        var t = Variables.TickCount
                                + (((wallStart.Intersection(wallEnd, position.ToVector2(), input.From.ToVector2())
                                         .Point.Distance(input.From) / input.Speed) + input.Delay) * 1000);
                        if (t < wallCastT + 4000)
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }
            }

            return result.Distinct().ToList();
        }
Beispiel #11
0
            /// <summary>
            ///     Returns an Area-of-Effect line prediction from a prediction input source.
            /// </summary>
            /// <param name="input">
            ///     <see cref="PredictionInput" /> input
            /// </param>
            /// <returns>
            ///     <see cref="PredictionOutput" /> output
            /// </returns>
            public static PredictionOutput GetLinePrediction(PredictionInput input)
            {
                var mainTargetPrediction = Movement.GetPrediction(input, false, true);
                var posibleTargets = new List<PossibleTarget>
                                         {
                                             new PossibleTarget
                                                 {
                                                     Position = mainTargetPrediction.UnitPosition.ToVector2(),
                                                     Unit = input.Unit
                                                 }
                                         };

                if (mainTargetPrediction.Hitchance >= HitChance.Medium)
                {
                    // Add the posible targets  in range:
                    posibleTargets.AddRange(GetPossibleTargets(input));
                }

                if (posibleTargets.Count > 1)
                {
                    var candidates = new List<Vector2>();
                    foreach (var targetCandidates in
                        posibleTargets.Select(
                            target => GetCandidates(input.From.ToVector2(), target.Position, input.Radius, input.Range))
                        )
                    {
                        candidates.AddRange(targetCandidates);
                    }

                    var bestCandidateHits = -1;
                    var bestCandidate = default(Vector2);
                    var bestCandidateHitPoints = new List<Vector2>();
                    var positionsList = posibleTargets.Select(t => t.Position).ToList();

                    foreach (var candidate in candidates)
                    {
                        if (
                            GetHits(
                                input.From.ToVector2(),
                                candidate,
                                input.Radius + (input.Unit.BoundingRadius / 3) - 10,
                                new List<Vector2> { posibleTargets[0].Position }).Count() == 1)
                        {
                            var hits = GetHits(input.From.ToVector2(), candidate, input.Radius, positionsList).ToList();
                            var hitsCount = hits.Count;

                            if (hitsCount >= bestCandidateHits)
                            {
                                bestCandidateHits = hitsCount;
                                bestCandidate = candidate;
                                bestCandidateHitPoints = hits.ToList();
                            }
                        }
                    }

                    if (bestCandidateHits > 1)
                    {
                        float maxDistance = -1;
                        Vector2 p1 = default(Vector2), p2 = default(Vector2);

                        // Center the position
                        for (var i = 0; i < bestCandidateHitPoints.Count; i++)
                        {
                            for (var j = 0; j < bestCandidateHitPoints.Count; j++)
                            {
                                var startP = input.From.ToVector2();
                                var endP = bestCandidate;
                                var proj1 = positionsList[i].LSProjectOn(startP, endP);
                                var proj2 = positionsList[j].LSProjectOn(startP, endP);
                                var dist = bestCandidateHitPoints[i].LSDistanceSquared(proj1.LinePoint)
                                           + bestCandidateHitPoints[j].LSDistanceSquared(proj2.LinePoint);

                                if (dist >= maxDistance
                                    && (proj1.LinePoint - positionsList[i]).AngleBetween(
                                        proj2.LinePoint - positionsList[j]) > 90)
                                {
                                    maxDistance = dist;
                                    p1 = positionsList[i];
                                    p2 = positionsList[j];
                                }
                            }
                        }

                        return new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance,
                            AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = ((p1 + p2) * 0.5f).ToVector3(),
                            Input = input
                        };
                    }
                }

                return mainTargetPrediction;
            }
Beispiel #12
0
            /// <summary>
            ///     Returns an Area-of-Effect cone prediction from a prediction input source.
            /// </summary>
            /// <param name="input">
            ///     <see cref="PredictionInput" /> input
            /// </param>
            /// <returns>
            ///     <see cref="PredictionOutput" /> output
            /// </returns>
            public static PredictionOutput GetConePrediction(PredictionInput input)
            {
                var mainTargetPrediction = Movement.GetPrediction(input, false, true);
                var posibleTargets = new List<PossibleTarget>
                                         {
                                             new PossibleTarget
                                                 {
                                                     Position = mainTargetPrediction.UnitPosition.ToVector2(),
                                                     Unit = input.Unit
                                                 }
                                         };

                if (mainTargetPrediction.Hitchance >= HitChance.Medium)
                {
                    // Add the posible targets  in range:
                    posibleTargets.AddRange(GetPossibleTargets(input));
                }

                if (posibleTargets.Count > 1)
                {
                    var candidates = new List<Vector2>();

                    foreach (var target in posibleTargets)
                    {
                        target.Position = target.Position - input.From.ToVector2();
                    }

                    for (var i = 0; i < posibleTargets.Count; i++)
                    {
                        for (var j = 0; j < posibleTargets.Count; j++)
                        {
                            if (i != j)
                            {
                                var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f;

                                if (!candidates.Contains(p))
                                {
                                    candidates.Add(p);
                                }
                            }
                        }
                    }

                    var bestCandidateHits = -1;
                    var bestCandidate = default(Vector2);
                    var positionsList = posibleTargets.Select(t => t.Position).ToList();

                    foreach (var candidate in candidates)
                    {
                        var hits = GetHits(candidate, input.Range, input.Radius, positionsList);

                        if (hits > bestCandidateHits)
                        {
                            bestCandidate = candidate;
                            bestCandidateHits = hits;
                        }
                    }

                    if (bestCandidateHits > 1 && input.From.LSDistanceSquared(bestCandidate) > 50 * 50)
                    {
                        return new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance,
                            AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = bestCandidate.ToVector3(),
                            Input = input
                        };
                    }
                }

                return mainTargetPrediction;
            }
Beispiel #13
0
 private static bool IsDead(PredictionInput input, Obj_AI_Base minion, float distance)
 {
     var delay = (distance / input.Speed) + input.Delay;
     if (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon)
     {
         delay = input.Delay;
     }
     var convert = (int)(delay * 1000);
     return Health.GetPrediction(minion, convert, 0, HealthPredictionType.Simulated) <= 0;
 }
Beispiel #14
0
        /// <summary>
        ///     Returns Calculated Prediction based off given data values.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="ft">Add Delay</param>
        /// <param name="checkCollision">Check Collision</param>
        /// <returns>
        ///     <see cref="PredictionOutput" /> output
        /// </returns>
        internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision)
        {
            if (!input.Unit.IsValidTarget(float.MaxValue, false))
            {
                return(new PredictionOutput());
            }

            if (ft)
            {
                input.Delay += Game.Ping / 2000f + 0.05f;

                if (input.AoE)
                {
                    return(Cluster.GetAoEPrediction(input));
                }
            }

            // Target too far away.
            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon &&
                input.Unit.DistanceSquared(input.RangeCheckFrom) > Math.Pow(input.Range * 1.5, 2))
            {
                return(new PredictionOutput {
                    Input = input
                });
            }

            PredictionOutput result = null;

            // Unit is dashing.
            if (input.Unit.IsDashing())
            {
                result = GetDashingPrediction(input);
            }
            else
            {
                // Unit is immobile.
                var remainingImmobileT = UnitIsImmobileUntil(input.Unit);

                if (remainingImmobileT >= 0d)
                {
                    result = GetImmobilePrediction(input, remainingImmobileT);
                }
            }

            // Normal prediction
            if (result == null)
            {
                result = GetStandardPrediction(input);
            }

            if (!((Player.Instance).Distance(input.Unit, true) < input.Range * input.Range))
            {
                result.Hitchance = HitChance.OutOfRange;
            }

            // Check for collision
            if (checkCollision && input.Collision && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var positions = new List <Vector3> {
                    result.UnitPosition, input.Unit.Position
                };
                result.CollisionObjects = Collision.GetCollision(positions, input);
                result.CollisionObjects.RemoveAll(x => x.Compare(input.Unit));

                if (result.CollisionObjects.Count > 0)
                {
                    result.Hitchance = HitChance.Collision;
                }
            }

            // Calc hitchance again
            if (result.Hitchance == HitChance.High)
            {
                result.Hitchance = GetHitChance(input);
            }

            return(result);
        }
Beispiel #15
0
        /// <summary>
        ///     Returns Calculated Prediction based off given data values.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="ft">Add Delay</param>
        /// <param name="checkCollision">Check Collision</param>
        /// <returns>
        ///     <see cref="PredictionOutput" /> output
        /// </returns>
        internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision)
        {
            if (!input.Unit.LSIsValidTarget(float.MaxValue, false))
            {
                return new PredictionOutput();
            }

            if (ft)
            {
                // Increase the delay due to the latency and server tick:
                input.Delay += Game.Ping / 2000f + 0.06f;

                if (input.AoE)
                {
                    return Cluster.GetAoEPrediction(input);
                }
            }

            // Target too far away.
            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon
                && input.Unit.LSDistanceSquared(input.RangeCheckFrom) > Math.Pow(input.Range * 1.5, 2))
            {
                return new PredictionOutput { Input = input };
            }

            PredictionOutput result = null;

            // Unit is dashing.
            if (input.Unit.IsDashing())
            {
                result = GetDashingPrediction(input);
            }
            else
            {
                // Unit is immobile.
                var remainingImmobileT = UnitIsImmobileUntil(input.Unit);

                if (remainingImmobileT >= 0d)
                {
                    result = GetImmobilePrediction(input, remainingImmobileT);
                }
            }

            // Normal prediction
            if (result == null)
            {
                result = GetStandardPrediction(input);
            }

            // Check if the unit position is in range
            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon)
            {
                if (result.Hitchance >= HitChance.High
                    && input.RangeCheckFrom.LSDistanceSquared(input.Unit.Position)
                    > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2))
                {
                    result.Hitchance = HitChance.Medium;
                }

                if (input.RangeCheckFrom.LSDistanceSquared(result.UnitPosition)
                    > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2))
                {
                    result.Hitchance = HitChance.OutOfRange;
                }

                if (input.RangeCheckFrom.LSDistanceSquared(result.CastPosition) > Math.Pow(input.Range, 2)
                    && result.Hitchance != HitChance.OutOfRange)
                {
                    result.CastPosition = input.RangeCheckFrom
                                          + input.Range
                                          * (result.UnitPosition - input.RangeCheckFrom).ToVector2()
                                                .LSNormalized()
                                                .ToVector3();
                }
            }

            // Check for collision
            if (checkCollision && input.Collision && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var positions = new List<Vector3> { result.UnitPosition, input.Unit.Position };
                result.CollisionObjects = Collision.GetCollision(positions, input);
                result.CollisionObjects.RemoveAll(x => x.Compare(input.Unit));

                if (result.CollisionObjects.Count > 0)
                {
                    result.Hitchance = HitChance.Collision;
                }
            }

            // Calc hitchance again
            if (result.Hitchance == HitChance.High)
            {
                result.Hitchance = GetHitChance(input);
            }

            return result;
        }
Beispiel #16
0
        /// <summary>
        ///     Returns the list of the units that the skill-shot will hit before reaching the set positions.
        /// </summary>
        /// <param name="positions">
        ///     The positions.
        /// </param>
        /// <param name="input">
        ///     The input.
        /// </param>
        /// <returns>
        ///     A list of <c>Obj_AI_Base</c>s which the input collides with.
        /// </returns>
        ///

        public static List <Obj_AI_Base> GetCollision(List <Vector3> positions, PredictionInput input)
        {
            var result = new List <Obj_AI_Base>();

            foreach (var position in positions)
            {
                if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
                {
                    result.AddRange(
                        EntityManager.MinionsAndMonsters.EnemyMinions.Where(i => i.IsMinion || i.Pet != null)
                        .Concat(GameObjects.Jungle)
                        .Where(
                            minion =>
                            minion.IsValidTarget(Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom) && IsHitCollision(minion, input, position, 20)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
                {
                    result.AddRange(
                        GameObjects.EnemyHeroes.Where(
                            hero =>
                            hero.IsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom) && IsHitCollision(hero, input, position, 50)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls))
                {
                    var step = position.Distance(input.From) / 20;
                    for (var i = 0; i < 20; i++)
                    {
                        if (input.From.ToVector2().Extend(position, step * i).IsWall())
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall))
                {
                    /*if (Variables.TickCount - wallCastT > 4000)
                     * {
                     *  continue;
                     * }*/

                    var wall =
                        GameObjects.AllGameObjects.FirstOrDefault(
                            gameObject =>
                            gameObject.IsValid &&
                            Regex.IsMatch(gameObject.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase));

                    if (wall == null)
                    {
                        continue;
                    }
                    Chat.Print(wall.Name + " => " + wall.Type + " | " + wall.Team);

                    var level     = wall.Name.Substring(wall.Name.Length - 6, 1);
                    var wallWidth = 300 + (50 * Convert.ToInt32(level));

                    var wallDirection = (wall.Position.ToVector2() - yasuoWallCastedPos).LSNormalized().Perpendicular();
                    var wallStart     = wall.Position.ToVector2() + (wallWidth / 2f * wallDirection);
                    var wallEnd       = wallStart - (wallWidth * wallDirection);


                    var wallPolygon   = new RectanglePoly(wallStart, wallEnd, 75);
                    var intersections = new List <Vector2>();
                    for (var i = 0; i < wallPolygon.Points.Count; i++)
                    {
                        var inter =
                            wallPolygon.Points[i].Intersection(
                                wallPolygon.Points[i != wallPolygon.Points.Count - 1 ? i + 1 : 0],
                                input.From.ToVector2(),
                                position.ToVector2());

                        if (inter.Intersects)
                        {
                            intersections.Add(inter.Point);
                        }
                    }
                    wallPolygon.Draw(Color.Red);

                    if (intersections.Count > 0)
                    {
                        result.Add(GameObjects.Player);
                    }
                }
            }

            return(result.Distinct().ToList());
        }
Beispiel #17
0
        private static HitChance GetHitChance(PredictionInput input)
        {
            var hero = input.Unit as AIHeroClient;

            if (hero == null || !hero.IsValid || input.Radius <= 1f)
            {
                return HitChance.VeryHigh;
            }

            if (hero.IsCastingInterruptableSpell(true) || hero.LSIsRecalling()
                || (UnitTracker.GetLastStopTick(hero) < 0.1d && hero.IsRooted))
            {
                return HitChance.VeryHigh;
            }

            var wayPoints = hero.GetWaypoints();
            var lastWaypoint = wayPoints.Last();
            var heroPos = hero.Position;
            var heroServerPos = hero.ServerPosition.ToVector2();
            var distHeroToWaypoint = heroServerPos.Distance(lastWaypoint);
            var distHeroToFrom = heroServerPos.Distance(input.From);
            var distFromToWaypoint = input.From.Distance(lastWaypoint);
            var angle = (lastWaypoint - heroPos.ToVector2()).AngleBetween(input.From - heroPos);
            var delay = input.Delay
                        + (Math.Abs(input.Speed - float.MaxValue) > float.Epsilon ? distHeroToFrom / input.Speed : 0);
            var moveArea = hero.MoveSpeed * delay;
            var fixRange = moveArea * 0.35f;
            var minPath = 1000;

            if (input.Type == SkillshotType.SkillshotCircle)
            {
                fixRange -= input.Radius / 2;
            }

            if (distFromToWaypoint <= distHeroToFrom && distHeroToFrom > input.Range - fixRange)
            {
                return HitChance.Medium;
            }

            if (distHeroToWaypoint > 0)
            {
                if (angle < 20 || angle > 160 || (angle > 130 && distHeroToWaypoint > 400))
                {
                    return HitChance.VeryHigh;
                }

                var wallPoints = new List<Vector2>();

                for (var i = 1; i <= 15; i++)
                {
                    var circleAngle = i * 2 * Math.PI / 15;
                    var point = new Vector2(
                        heroPos.X + 350 * (float)Math.Cos(circleAngle),
                        heroPos.Y + 350 * (float)Math.Sin(circleAngle));

                    if (point.IsWall())
                    {
                        wallPoints.Add(point);
                    }
                }

                if (wallPoints.Count > 2 && !wallPoints.Any(i => heroPos.Distance(i) > lastWaypoint.Distance(i)))
                {
                    return HitChance.VeryHigh;
                }
            }

            if (distHeroToWaypoint > 0 && distHeroToWaypoint < 100)
            {
                return HitChance.Medium;
            }

            if (wayPoints.Count == 1)
            {
                return hero.Spellbook.IsAutoAttacking || UnitTracker.GetLastStopTick(hero) < 0.8d
                           ? HitChance.High
                           : HitChance.VeryHigh;
            }

            if (UnitTracker.IsSpamSamePos(hero))
            {
                return HitChance.VeryHigh;
            }

            if (distHeroToFrom < 250 || hero.MoveSpeed < 250 || distFromToWaypoint < 250)
            {
                return HitChance.VeryHigh;
            }

            if (GamePath.PathTracker.GetCurrentPath(hero).Time > 0.25d)
            {
                return HitChance.VeryHigh;
            }

            if (distHeroToWaypoint > minPath)
            {
                return HitChance.VeryHigh;
            }

            if (hero.HealthPercent < 20 || GameObjects.Player.HealthPercent < 20)
            {
                return HitChance.VeryHigh;
            }

            if (input.Type == SkillshotType.SkillshotCircle && GamePath.PathTracker.GetCurrentPath(hero).Time < 0.1d
                && distHeroToWaypoint > fixRange)
            {
                return HitChance.VeryHigh;
            }

            return HitChance.Medium;
        }
Beispiel #18
0
        private static HitChance GetHitChance(PredictionInput input)
        {
            var hero = input.Unit as AIHeroClient;

            if (hero == null || input.Radius <= 1f)
            {
                return(HitChance.VeryHigh);
            }

            if (hero.IsCastingInterruptableSpell(true) || hero.LSIsRecalling())
            {
                return(HitChance.VeryHigh);
            }

            if (hero.Path.Length > 0 != hero.IsMoving)
            {
                return(HitChance.Medium);
            }

            var wayPoint = input.Unit.GetWaypoints().Last();
            var delay    = input.Delay
                           + (Math.Abs(input.Speed - float.MaxValue) > float.Epsilon
                               ? hero.Distance(input.From) / input.Speed
                               : 0);
            var moveArea  = hero.MoveSpeed * delay;
            var fixRange  = moveArea * 0.4f;
            var minPath   = 900 + moveArea;
            var moveAngle = 31d;

            if (input.Radius > 70)
            {
                moveAngle++;
            }
            else if (input.Radius <= 60)
            {
                moveAngle--;
            }

            if (input.Delay < 0.3)
            {
                moveAngle++;
            }

            if (GamePath.PathTracker.GetCurrentPath(input.Unit).Time < 0.1d)
            {
                fixRange   = moveArea * 0.3f;
                minPath    = 700 + moveArea;
                moveAngle += 1.5;
            }

            if (input.Type == SkillshotType.SkillshotCircle)
            {
                fixRange -= input.Radius / 2;
            }

            if (input.From.Distance(wayPoint) <= hero.Distance(input.From))
            {
                if (hero.Distance(input.From) > input.Range - fixRange)
                {
                    return(HitChance.Medium);
                }
            }
            else if (hero.Distance(wayPoint) > 350)
            {
                moveAngle += 1.5;
            }

            if (hero.Distance(input.From) < 250 || hero.MoveSpeed < 250 || input.From.Distance(wayPoint) < 250)
            {
                return(HitChance.VeryHigh);
            }

            if (hero.Distance(wayPoint) > minPath)
            {
                return(HitChance.VeryHigh);
            }

            if (hero.HealthPercent < 20 || GameObjects.Player.HealthPercent < 20)
            {
                return(HitChance.VeryHigh);
            }

            if (GetAngle(input.From.ToVector2(), hero.ServerPosition.ToVector2(), wayPoint) < moveAngle &&
                hero.Distance(wayPoint) > 260)
            {
                return(HitChance.VeryHigh);
            }

            if (input.Type == SkillshotType.SkillshotCircle &&
                GamePath.PathTracker.GetCurrentPath(input.Unit).Time < 0.1d && hero.Distance(wayPoint) > fixRange)
            {
                return(HitChance.VeryHigh);
            }

            return(HitChance.High);
        }
        /// <summary>
        ///     Calculates the position to cast a spell according to unit movement.
        /// </summary>
        /// <param name="input">PredictionInput type</param>
        /// <param name="additionalSpeed">Additional Speed (Multiplicative)</param>
        /// <returns>The <see cref="PredictionOutput" /></returns>
        internal static PredictionOutput GetAdvancedPrediction(PredictionInput input, float additionalSpeed = 0)
        {
            var speed = Math.Abs(additionalSpeed) < float.Epsilon ? input.Speed : input.Speed * additionalSpeed;

            if (Math.Abs(speed - int.MaxValue) < float.Epsilon)
            {
                speed = 90000;
            }

            var unit = input.Unit;
            var position = PositionAfter(unit, 1, unit.MoveSpeed - 100);
            var prediction = position + (speed * (input.Delay / 1000));

            return new PredictionOutput()
                       {
                           UnitPosition = new Vector3(position.X, position.Y, unit.ServerPosition.Z),
                           CastPosition = new Vector3(prediction.X, prediction.Y, unit.ServerPosition.Z),
                           Hitchance = HitChance.High
                       };
        }
Beispiel #20
0
        /// <summary>
        ///     Returns the list of the units that the skill-shot will hit before reaching the set positions.
        /// </summary>
        /// <param name="positions">
        ///     The positions.
        /// </param>
        /// <param name="input">
        ///     The input.
        /// </param>
        /// <returns>
        ///     A list of <c>Obj_AI_Base</c>s which the input collides with.
        /// </returns>
        public static List<Obj_AI_Base> GetCollision(List<Vector3> positions, PredictionInput input)
        {
            var result = new List<Obj_AI_Base>();

            foreach (var position in positions)
            {
                if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
                {
                    result.AddRange(
                        GameObjects.EnemyMinions.Where(i => i.IsMinion() || i.IsPet())
                            .Concat(GameObjects.Jungle)
                            .Where(
                                minion =>
                                minion.LSIsValidTarget(
                                    Math.Min(input.Range + input.Radius + 100, 2000),
                                    true,
                                    input.RangeCheckFrom) && IsHitCollision(minion, input, position, 15)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
                {
                    result.AddRange(
                        GameObjects.EnemyHeroes.Where(
                            hero =>
                            hero.LSIsValidTarget(
                                Math.Min(input.Range + input.Radius + 100, 2000),
                                true,
                                input.RangeCheckFrom) && IsHitCollision(hero, input, position, 50)));
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls))
                {
                    var step = position.Distance(input.From) / 20;
                    for (var i = 0; i < 20; i++)
                    {
                        if (input.From.ToVector2().Extend(position, step * i).IsWall())
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall))
                {
                    if (yasuoWallLeft == null || yasuoWallRight == null)
                    {
                        continue;
                    }

                    yasuoWallPoly = new RectanglePoly(yasuoWallLeft.Position, yasuoWallRight.Position, 75);

                    var intersections = new List<Vector2>();
                    for (var i = 0; i < yasuoWallPoly.Points.Count; i++)
                    {
                        var inter =
                            yasuoWallPoly.Points[i].LSIntersection(
                                yasuoWallPoly.Points[i != yasuoWallPoly.Points.Count - 1 ? i + 1 : 0],
                                input.From.ToVector2(),
                                position.ToVector2());

                        if (inter.Intersects)
                        {
                            intersections.Add(inter.Point);
                        }
                    }

                    if (intersections.Count > 0)
                    {
                        result.Add(GameObjects.Player);
                    }
                }
            }

            return result.Distinct().ToList();
        }
        /// <summary>
        ///     Returns Immobile Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="remainingImmobileT">Remaining Immobile Time</param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetImmobilePrediction(PredictionInput input, double remainingImmobileT)
        {
            var timeToReachTargetPosition = input.Delay + (input.Unit.Distance(input.From) / input.Speed);

            if (timeToReachTargetPosition <= remainingImmobileT + (input.RealRadius / input.Unit.MoveSpeed))
            {
                return new PredictionOutput
                           {
                               CastPosition = input.Unit.ServerPosition, UnitPosition = input.Unit.Position,
                               Hitchance = HitChance.Immobile
                           };
            }

            return new PredictionOutput
                       {
                           Input = input, CastPosition = input.Unit.ServerPosition,
                           UnitPosition = input.Unit.ServerPosition, Hitchance = HitChance.High
                       };
        }
Beispiel #22
0
 internal static List<Obj_AI_Base> GetCollision(List<Vector3> positions, PredictionInput input)
 {
     var result = new List<Obj_AI_Base>();
     foreach (var position in positions)
     {
         if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
         {
             GameObjects.EnemyMinions.Where(i => i.IsMinion() || i.IsPet())
                 .Concat(GameObjects.Jungle)
                 .Where(
                     i =>
                     i.IsValidTarget(
                         Math.Min(input.Range + input.Radius + 100, 2000),
                         true,
                         input.RangeCheckFrom) && !result.Any(a => a.Compare(i)))
                 .ForEach(
                     i =>
                         {
                             input.Unit = i;
                             if (
                                 input.GetPrediction(false, false)
                                     .UnitPosition.ToVector2()
                                     .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                                 <= Math.Pow(input.Radius + 20 + i.BoundingRadius, 2))
                             {
                                 result.Add(i);
                             }
                         });
         }
         if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
         {
             GameObjects.EnemyHeroes.Where(
                 i =>
                 i.IsValidTarget(
                     Math.Min(input.Range + input.Radius + 100, 2000),
                     true,
                     input.RangeCheckFrom) && !result.Any(a => a.Compare(i))).ForEach(
                         i =>
                             {
                                 input.Unit = i;
                                 if (
                                     input.GetPrediction(false, false)
                                         .UnitPosition.ToVector2()
                                         .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                                     <= Math.Pow(input.Radius + 50 + i.BoundingRadius, 2))
                                 {
                                     result.Add(i);
                                 }
                             });
         }
         if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls) && !result.Any(i => i.IsMe))
         {
             var step = position.Distance(input.From) / 20;
             for (var i = 0; i < 20; i++)
             {
                 if (input.From.Extend(position, step * i).IsWall())
                 {
                     result.Add(ObjectManager.Player);
                     break;
                 }
             }
         }
         if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall) && !result.Any(i => i.IsMe)
             && Variables.TickCount - yasuoWallCastT <= 4000)
         {
             var wall =
                 GameObjects.AllGameObjects.FirstOrDefault(
                     i =>
                     i.IsValid
                     && Regex.IsMatch(i.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase));
             if (wall == null)
             {
                 continue;
             }
             var wallWidth = 300 + 50 * Convert.ToInt32(wall.Name.Substring(wall.Name.Length - 6, 1));
             var wallDirection = (yasuoWallCastPos - wall.Position.ToVector2()).Normalized().Perpendicular();
             var wallStart = wall.Position.ToVector2() + wallWidth / 2f * wallDirection;
             var wallEnd = wallStart - wallWidth * wallDirection;
             var wallIntersect = wallStart.Intersection(
                 wallEnd,
                 position.ToVector2(),
                 input.From.ToVector2());
             if (wallIntersect.Intersects)
             {
                 var t = Variables.TickCount
                         + (wallIntersect.Point.Distance(input.From) / input.Speed + input.Delay) * 1000;
                 if (t < yasuoWallCastT + 4000)
                 {
                     result.Add(ObjectManager.Player);
                 }
             }
         }
     }
     return result.Distinct().ToList();
 }
        /// <summary>
        ///     Returns Standard Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetStandardPrediction(PredictionInput input)
        {
            var speed = input.Unit.MoveSpeed;

            if (input.Unit.DistanceSquared(input.From) < 200 * 200)
            {
                // input.Delay /= 2;
                speed /= 1.5f;
            }

            var result = GetPositionOnPath(input, input.Unit.GetWaypoints(), speed);

            if (result.Hitchance >= HitChance.High && input.Unit is Obj_AI_Hero)
            {
            }

            return result;
        }
Beispiel #24
0
 private static List<PossibleTarget> GetPossibleTargets(PredictionInput input)
 {
     var result = new List<PossibleTarget>();
     var originalUnit = input.Unit;
     GameObjects.EnemyHeroes.Where(
         i =>
         i.NetworkId != originalUnit.NetworkId
         && i.IsValidTarget(input.Range + 200 + input.RealRadius, true, input.RangeCheckFrom)).ForEach(
             i =>
                 {
                     input.Unit = i;
                     var prediction = input.GetPrediction(false, false);
                     if (prediction.Hitchance >= HitChance.High)
                     {
                         result.Add(
                             new PossibleTarget { Position = prediction.UnitPosition.ToVector2(), Unit = i });
                     }
                 });
     return result;
 }
Beispiel #25
0
        /// <summary>
        ///     Returns Calculated Prediction based off given data values.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="ft">Add Delay</param>
        /// <param name="checkCollision">Check Collision</param>
        /// <returns>
        ///     <see cref="PredictionOutput" /> output
        /// </returns>
        internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision)
        {
            if (!input.Unit.LSIsValidTarget(float.MaxValue, false))
            {
                return(new PredictionOutput());
            }

            if (ft)
            {
                // Increase the delay due to the latency and server tick:
                input.Delay += Game.Ping / 2000f + 0.06f;

                if (input.AoE)
                {
                    return(Cluster.GetAoEPrediction(input));
                }
            }

            // Target too far away.
            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon &&
                input.Unit.DistanceSquared(input.RangeCheckFrom) > Math.Pow(input.Range * 1.5, 2))
            {
                return(new PredictionOutput {
                    Input = input
                });
            }

            PredictionOutput result = null;

            // Unit is dashing.
            if (input.Unit.IsDashing())
            {
                result = GetDashingPrediction(input);
            }
            else
            {
                // Unit is immobile.
                var remainingImmobileT = UnitIsImmobileUntil(input.Unit);

                if (remainingImmobileT >= 0d)
                {
                    result = GetImmobilePrediction(input, remainingImmobileT);
                }
            }

            // Normal prediction
            if (result == null)
            {
                result = GetStandardPrediction(input);
            }

            // Check if the unit position is in range
            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon)
            {
                if (result.Hitchance >= HitChance.High &&
                    input.RangeCheckFrom.DistanceSquared(input.Unit.Position)
                    > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2))
                {
                    result.Hitchance = HitChance.Medium;
                }

                if (input.RangeCheckFrom.DistanceSquared(result.UnitPosition)
                    > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2))
                {
                    result.Hitchance = HitChance.OutOfRange;
                }

                if (input.RangeCheckFrom.DistanceSquared(result.CastPosition) > Math.Pow(input.Range, 2) &&
                    result.Hitchance != HitChance.OutOfRange)
                {
                    result.CastPosition = input.RangeCheckFrom
                                          + input.Range
                                          * (result.UnitPosition - input.RangeCheckFrom).ToVector2()
                                          .LSNormalized()
                                          .ToVector3();
                }
            }

            // Check for collision
            if (checkCollision && input.Collision && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var positions = new List <Vector3> {
                    result.UnitPosition, input.Unit.Position
                };
                result.CollisionObjects = Collision.GetCollision(positions, input);
                result.CollisionObjects.RemoveAll(x => x.Compare(input.Unit));

                if (result.CollisionObjects.Count > 0)
                {
                    result.Hitchance = HitChance.Collision;
                }
            }

            // Calc hitchance again
            if (result.Hitchance == HitChance.High)
            {
                result.Hitchance = GetHitChance(input);
            }

            return(result);
        }
Beispiel #26
0
 internal static PredictionOutput GetCirclePrediction(PredictionInput input)
 {
     var mainTargetPrediction = input.GetPrediction(false, true);
     var posibleTargets = new List<PossibleTarget>
                              {
                                  new PossibleTarget
                                      {
                                          Position = mainTargetPrediction.UnitPosition.ToVector2(),
                                          Unit = input.Unit
                                      }
                              };
     if (mainTargetPrediction.Hitchance >= HitChance.Medium)
     {
         posibleTargets.AddRange(GetPossibleTargets(input));
     }
     while (posibleTargets.Count > 1)
     {
         var mecCircle = ConvexHull.GetMec(posibleTargets.Select(i => i.Position).ToList());
         if (mecCircle.Radius <= input.RealRadius - 10
             && mecCircle.Center.DistanceSquared(input.RangeCheckFrom) < input.Range * input.Range)
         {
             return new PredictionOutput
                        {
                            AoeTargetsHit = posibleTargets.Select(i => (Obj_AI_Hero)i.Unit).ToList(),
                            CastPosition = mecCircle.Center.ToVector3(),
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            Hitchance = mainTargetPrediction.Hitchance, Input = input,
                            AoeHitCount = posibleTargets.Count
                        };
         }
         float maxdist = -1;
         var maxdistindex = 1;
         for (var i = 1; i < posibleTargets.Count; i++)
         {
             var distance = posibleTargets[i].Position.DistanceSquared(posibleTargets[0].Position);
             if (distance > maxdist || maxdist.CompareTo(-1) == 0)
             {
                 maxdistindex = i;
                 maxdist = distance;
             }
         }
         posibleTargets.RemoveAt(maxdistindex);
     }
     return mainTargetPrediction;
 }
Beispiel #27
0
 /// <summary>
 ///     Returns Calculated Prediction based off given data values.
 /// </summary>
 /// <param name="input">
 ///     <see cref="PredictionInput" /> input
 /// </param>
 /// <returns>
 ///     <see cref="PredictionOutput" /> output
 /// </returns>
 public static PredictionOutput GetPrediction(PredictionInput input)
 {
     return(GetPrediction(input, true, true));
 }
Beispiel #28
0
 internal static PredictionOutput GetConePrediction(PredictionInput input)
 {
     var mainTargetPrediction = input.GetPrediction(false, true);
     var posibleTargets = new List<PossibleTarget>
                              {
                                  new PossibleTarget
                                      {
                                          Position = mainTargetPrediction.UnitPosition.ToVector2(),
                                          Unit = input.Unit
                                      }
                              };
     if (mainTargetPrediction.Hitchance >= HitChance.Medium)
     {
         posibleTargets.AddRange(GetPossibleTargets(input));
     }
     if (posibleTargets.Count > 1)
     {
         var candidates = new List<Vector2>();
         posibleTargets.ForEach(i => i.Position -= input.From.ToVector2());
         for (var i = 0; i < posibleTargets.Count; i++)
         {
             for (var j = 0; j < posibleTargets.Count; j++)
             {
                 if (i != j)
                 {
                     var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f;
                     if (!candidates.Contains(p))
                     {
                         candidates.Add(p);
                     }
                 }
             }
         }
         var bestCandidateHits = -1;
         var bestCandidate = new Vector2();
         var positionsList = posibleTargets.Select(i => i.Position).ToList();
         candidates.ForEach(
             i =>
                 {
                     var hits = GetHits(i, input.Range, input.Radius, positionsList);
                     if (hits > bestCandidateHits)
                     {
                         bestCandidate = i;
                         bestCandidateHits = hits;
                     }
                 });
         if (bestCandidateHits > 1 && input.From.DistanceSquared(bestCandidate) > 50 * 50)
         {
             return new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance, AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = bestCandidate.ToVector3(), Input = input
                        };
         }
     }
     return mainTargetPrediction;
 }
Beispiel #29
0
        /// <summary>
        ///     Returns Dashing Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetDashingPrediction(PredictionInput input)
        {
            var dashData = input.Unit.GetDashInfo();
            var result = new PredictionOutput { Input = input, Hitchance = HitChance.Medium };

            // Normal dashes.
            if (!dashData.IsBlink)
            {
                var endP = dashData.EndPos.ToVector3();

                // Mid air:
                var dashPred = GetPositionOnPath(
                    input,
                    new List<Vector3> { input.Unit.ServerPosition, endP }.ToVector2(),
                    dashData.Speed);

                if (dashPred.Hitchance >= HitChance.High
                    && dashPred.UnitPosition.ToVector2()
                           .Distance(input.Unit.Position.ToVector2(), endP.ToVector2(), true) < 200)
                {
                    dashPred.CastPosition = dashPred.UnitPosition;
                    dashPred.Hitchance = HitChance.Dashing;
                    return dashPred;
                }

                // At the end of the dash:
                if (dashData.Path.LSPathLength() > 200)
                {
                    var timeToPoint = input.Delay / 2f
                                      + (Math.Abs(input.Speed - float.MaxValue) > float.Epsilon
                                             ? input.From.Distance(endP) / input.Speed
                                             : 0) - 0.25f;

                    if (timeToPoint
                        <= input.Unit.Distance(endP) / dashData.Speed + input.RealRadius / input.Unit.MoveSpeed)
                    {
                        return new PredictionOutput
                        {
                            Input = input,
                            CastPosition = endP,
                            UnitPosition = endP,
                            Hitchance = HitChance.Dashing
                        };
                    }
                }

                result.CastPosition = endP;
                result.UnitPosition = result.CastPosition;

                // Figure out where the unit is going.
            }

            return result;
        }
Beispiel #30
0
 internal static PredictionOutput GetLinePrediction(PredictionInput input)
 {
     var mainTargetPrediction = input.GetPrediction(false, true);
     var posibleTargets = new List<PossibleTarget>
                              {
                                  new PossibleTarget
                                      {
                                          Position = mainTargetPrediction.UnitPosition.ToVector2(),
                                          Unit = input.Unit
                                      }
                              };
     if (mainTargetPrediction.Hitchance >= HitChance.Medium)
     {
         posibleTargets.AddRange(GetPossibleTargets(input));
     }
     if (posibleTargets.Count > 1)
     {
         var candidates = new List<Vector2>();
         posibleTargets.ForEach(
             i =>
             candidates.AddRange(
                 GetCandidates(input.From.ToVector2(), i.Position, input.Radius, input.Range)));
         var bestCandidateHits = -1;
         var bestCandidate = new Vector2();
         var bestCandidateHitPoints = new List<Vector2>();
         var positionsList = posibleTargets.Select(i => i.Position).ToList();
         foreach (var candidate in
             candidates.Where(
                 i =>
                 GetHits(
                     input.From.ToVector2(),
                     i,
                     input.Radius + input.Unit.BoundingRadius / 3 - 10,
                     new List<Vector2> { posibleTargets[0].Position }).Count == 1))
         {
             var hits = GetHits(input.From.ToVector2(), candidate, input.Radius, positionsList);
             var hitsCount = hits.Count;
             if (hitsCount >= bestCandidateHits)
             {
                 bestCandidateHits = hitsCount;
                 bestCandidate = candidate;
                 bestCandidateHitPoints = hits;
             }
         }
         if (bestCandidateHits > 1)
         {
             float maxDistance = -1;
             Vector2 p1 = new Vector2(), p2 = new Vector2();
             for (var i = 0; i < bestCandidateHitPoints.Count; i++)
             {
                 for (var j = 0; j < bestCandidateHitPoints.Count; j++)
                 {
                     var startP = input.From.ToVector2();
                     var endP = bestCandidate;
                     var proj1 = positionsList[i].ProjectOn(startP, endP);
                     var proj2 = positionsList[j].ProjectOn(startP, endP);
                     var dist = bestCandidateHitPoints[i].DistanceSquared(proj1.LinePoint)
                                + bestCandidateHitPoints[j].DistanceSquared(proj2.LinePoint);
                     if (dist >= maxDistance
                         && (proj1.LinePoint - positionsList[i]).AngleBetween(
                             proj2.LinePoint - positionsList[j]) > 90)
                     {
                         maxDistance = dist;
                         p1 = positionsList[i];
                         p2 = positionsList[j];
                     }
                 }
             }
             return new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance, AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = ((p1 + p2) * 0.5f).ToVector3(), Input = input
                        };
         }
     }
     return mainTargetPrediction;
 }
Beispiel #31
0
        /// <summary>
        ///     Get Position on Unit's Path.
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <param name="path">Path in Vector2 List</param>
        /// <param name="speed">Unit Speed</param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetPositionOnPath(PredictionInput input, List<Vector2> path, float speed = -1)
        {
            speed = Math.Abs(speed - -1) < float.Epsilon ? input.Unit.MoveSpeed : speed;

            if (path.Count <= 1)
            {
                return new PredictionOutput
                {
                    Input = input,
                    UnitPosition = input.Unit.ServerPosition,
                    CastPosition = input.Unit.ServerPosition,
                    Hitchance = HitChance.VeryHigh
                };
            }

            var pLength = path.LSPathLength();
            var dist = input.Delay * speed - input.RealRadius;

            // Skillshots with only a delay
            if (pLength >= dist && Math.Abs(input.Speed - float.MaxValue) < float.Epsilon)
            {
                var tDistance = dist;

                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a = path[i];
                    var b = path[i + 1];
                    var d = a.Distance(b);

                    if (d >= tDistance)
                    {
                        var direction = (b - a).LSNormalized();
                        var cp = a + direction * tDistance;
                        var p = a
                                + direction
                                * (i == path.Count - 2
                                       ? Math.Min(tDistance + input.RealRadius, d)
                                       : tDistance + input.RealRadius);

                        return new PredictionOutput
                        {
                            Input = input,
                            CastPosition = cp.ToVector3(),
                            UnitPosition = p.ToVector3(),
                            Hitchance = HitChance.High
                        };
                    }

                    tDistance -= d;
                }
            }

            // Skillshot with a delay and speed.
            if (pLength >= dist && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var tDistance = dist;

                if ((input.Type == SkillshotType.SkillshotLine || input.Type == SkillshotType.SkillshotCone)
                    && input.Unit.LSDistanceSquared(input.From) < 200 * 200)
                {
                    tDistance += input.RealRadius;
                }

                path = path.CutPath(tDistance);
                var tT = 0f;

                for (var i = 0; i < path.Count - 1; i++)
                {
                    var a = path[i];
                    var b = path[i + 1];
                    var tB = a.Distance(b) / speed;
                    var direction = (b - a).LSNormalized();
                    a = a - speed * tT * direction;
                    var sol = a.VectorMovementCollision(b, speed, input.From.ToVector2(), input.Speed, tT);
                    var t = (float)sol[0];
                    var pos = (Vector2)sol[1];

                    if (pos.IsValid() && t >= tT && t <= tT + tB)
                    {
                        if (pos.LSDistanceSquared(b) < 20)
                        {
                            break;
                        }

                        var p = pos + input.RealRadius * direction;

                        /*if (input.Type == SkillshotType.SkillshotLine)
                        {
                            var alpha = (input.From.ToVector2() - p).AngleBetween(a - b);

                            if (alpha > 30 && alpha < 180 - 30)
                            {
                                var beta = (float)Math.Asin(input.RealRadius / p.Distance(input.From));
                                var cp1 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(beta);
                                var cp2 = input.From.ToVector2() + (p - input.From.ToVector2()).Rotated(-beta);

                                pos = cp1.LSDistanceSquared(pos) < cp2.LSDistanceSquared(pos) ? cp1 : cp2;
                            }
                        }*/

                        return new PredictionOutput
                        {
                            Input = input,
                            CastPosition = pos.ToVector3(),
                            UnitPosition = p.ToVector3(),
                            Hitchance = HitChance.High
                        };
                    }

                    tT += tB;
                }
            }

            var position = path.Last().ToVector3();
            return new PredictionOutput
            { Input = input, CastPosition = position, UnitPosition = position, Hitchance = HitChance.Medium };
        }
Beispiel #32
0
            /// <summary>
            ///     Returns an Area-of-Effect cone prediction from a prediction input source.
            /// </summary>
            /// <param name="input">
            ///     <see cref="PredictionInput" /> input
            /// </param>
            /// <returns>
            ///     <see cref="PredictionOutput" /> output
            /// </returns>
            public static PredictionOutput GetConePrediction(PredictionInput input)
            {
                var mainTargetPrediction = Movement.GetPrediction(input, false, true);
                var posibleTargets       = new List <PossibleTarget>
                {
                    new PossibleTarget
                    {
                        Position = mainTargetPrediction.UnitPosition.ToVector2(),
                        Unit     = input.Unit
                    }
                };

                if (mainTargetPrediction.Hitchance >= HitChance.High)
                {
                    // Add the posible targets  in range:
                    posibleTargets.AddRange(GetPossibleTargets(input));
                }

                if (posibleTargets.Count > 1)
                {
                    var candidates = new List <Vector2>();

                    foreach (var target in posibleTargets)
                    {
                        target.Position = target.Position - input.From.ToVector2();
                    }

                    for (var i = 0; i < posibleTargets.Count; i++)
                    {
                        for (var j = 0; j < posibleTargets.Count; j++)
                        {
                            if (i == j)
                            {
                                continue;
                            }

                            var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f;

                            if (!candidates.Contains(p))
                            {
                                candidates.Add(p);
                            }
                        }
                    }

                    var bestCandidateHits = -1;
                    var bestCandidate     = default(Vector2);
                    var positionsList     = posibleTargets.Select(t => t.Position).ToList();

                    foreach (var candidate in candidates)
                    {
                        var hits = GetHits(candidate, input.Range, input.Radius, positionsList);

                        if (hits > bestCandidateHits)
                        {
                            bestCandidate     = candidate;
                            bestCandidateHits = hits;
                        }
                    }

                    if (bestCandidateHits > 1 && input.From.DistanceSquared(bestCandidate) > 50 * 50)
                    {
                        return(new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance, AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = bestCandidate.ToVector3(), Input = input
                        });
                    }
                }

                return(mainTargetPrediction);
            }
Beispiel #33
0
        /// <summary>
        ///     Returns Standard Prediction
        /// </summary>
        /// <param name="input">
        ///     <see cref="PredictionInput" /> input
        /// </param>
        /// <returns><see cref="PredictionOutput" /> output</returns>
        internal static PredictionOutput GetStandardPrediction(PredictionInput input)
        {
            var speed = input.Unit.MoveSpeed;

            if (input.Unit.LSDistanceSquared(input.From) < 200 * 200)
            {
                // input.Delay /= 2;
                speed /= 1.5f;
            }

            return GetPositionOnPath(input, input.Unit.GetWaypoints(), speed);
        }
Beispiel #34
0
            /// <summary>
            ///     Returns an Area-of-Effect line prediction from a prediction input source.
            /// </summary>
            /// <param name="input">
            ///     <see cref="PredictionInput" /> input
            /// </param>
            /// <returns>
            ///     <see cref="PredictionOutput" /> output
            /// </returns>
            public static PredictionOutput GetLinePrediction(PredictionInput input)
            {
                var mainTargetPrediction = Movement.GetPrediction(input, false, true);
                var posibleTargets       = new List <PossibleTarget>
                {
                    new PossibleTarget
                    {
                        Position = mainTargetPrediction.UnitPosition.ToVector2(),
                        Unit     = input.Unit
                    }
                };

                if (mainTargetPrediction.Hitchance >= HitChance.High)
                {
                    // Add the posible targets  in range:
                    posibleTargets.AddRange(GetPossibleTargets(input));
                }

                if (posibleTargets.Count > 1)
                {
                    var candidates = new List <Vector2>();
                    foreach (var targetCandidates in
                             posibleTargets.Select(
                                 target => GetCandidates(input.From.ToVector2(), target.Position, input.Radius, input.Range))
                             )
                    {
                        candidates.AddRange(targetCandidates);
                    }

                    var bestCandidateHits      = -1;
                    var bestCandidate          = default(Vector2);
                    var bestCandidateHitPoints = new List <Vector2>();
                    var positionsList          = posibleTargets.Select(t => t.Position).ToList();

                    foreach (var candidate in candidates)
                    {
                        if (
                            GetHits(
                                input.From.ToVector2(),
                                candidate,
                                input.Radius + /*(input.Unit.BoundingRadius / 3) -*/ 10,
                                new List <Vector2> {
                            posibleTargets[0].Position
                        }).Count() == 1)
                        {
                            var hits      = GetHits(input.From.ToVector2(), candidate, input.Radius, positionsList).ToList();
                            var hitsCount = hits.Count;

                            if (hitsCount >= bestCandidateHits)
                            {
                                bestCandidateHits      = hitsCount;
                                bestCandidate          = candidate;
                                bestCandidateHitPoints = hits.ToList();
                            }
                        }
                    }

                    if (bestCandidateHits > 1)
                    {
                        float   maxDistance = -1;
                        Vector2 p1 = default(Vector2), p2 = default(Vector2);

                        // Center the position
                        for (var i = 0; i < bestCandidateHitPoints.Count; i++)
                        {
                            for (var j = 0; j < bestCandidateHitPoints.Count; j++)
                            {
                                var startP = input.From.ToVector2();
                                var endP   = bestCandidate;
                                var proj1  = positionsList[i].ProjectOn(startP, endP);
                                var proj2  = positionsList[j].ProjectOn(startP, endP);
                                var dist   = bestCandidateHitPoints[i].DistanceSquared(proj1.LinePoint)
                                             + bestCandidateHitPoints[j].DistanceSquared(proj2.LinePoint);

                                if (dist >= maxDistance &&
                                    (proj1.LinePoint - positionsList[i]).AngleBetween(
                                        proj2.LinePoint - positionsList[j]) > 90)
                                {
                                    maxDistance = dist;
                                    p1          = positionsList[i];
                                    p2          = positionsList[j];
                                }
                            }
                        }

                        return(new PredictionOutput
                        {
                            Hitchance = mainTargetPrediction.Hitchance, AoeHitCount = bestCandidateHits,
                            UnitPosition = mainTargetPrediction.UnitPosition,
                            CastPosition = ((p1 + p2) * 0.5f).ToVector3(), Input = input
                        });
                    }
                }

                return(mainTargetPrediction);
            }
Beispiel #35
0
 /// <summary>
 ///     Returns Calculated Prediction based off given data values.
 /// </summary>
 /// <param name="input">
 ///     <see cref="PredictionInput" /> input
 /// </param>
 /// <returns>
 ///     <see cref="PredictionOutput" /> output
 /// </returns>
 public static PredictionOutput GetPrediction(PredictionInput input)
 {
     return GetPrediction(input, true, true);
 }
Beispiel #36
0
        /// <summary>
        ///     Returns the list of the units that the skill-shot will hit before reaching the set positions.
        /// </summary>
        /// <param name="positions">
        ///     The positions.
        /// </param>
        /// <param name="input">
        ///     The input.
        /// </param>
        /// <returns>
        ///     A list of <c>Obj_AI_Base</c>s which the input collides with.
        /// </returns>
        public static List <Obj_AI_Base> GetCollision(List <Vector3> positions, PredictionInput input)
        {
            var result = new List <Obj_AI_Base>();

            foreach (var position in positions)
            {
                if (input.CollisionObjects.HasFlag(CollisionableObjects.Minions))
                {
                    foreach (var minion in
                             GameObjects.EnemyMinions.Where(
                                 minion =>
                                 minion.IsValidTarget(
                                     Math.Min(input.Range + input.Radius + 100, 2000),
                                     true,
                                     input.RangeCheckFrom)))
                    {
                        input.Unit = minion;
                        var minionPrediction = Movement.GetPrediction(input, false, false);
                        if (minionPrediction.UnitPosition.ToVector2()
                            .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                            <= Math.Pow(input.Radius + 15 + minion.BoundingRadius, 2))
                        {
                            result.Add(minion);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Heroes))
                {
                    foreach (var hero in
                             GameObjects.EnemyHeroes.Where(
                                 hero =>
                                 hero.IsValidTarget(
                                     Math.Min(input.Range + input.Radius + 100, 2000),
                                     true,
                                     input.RangeCheckFrom)))
                    {
                        input.Unit = hero;
                        var prediction = Movement.GetPrediction(input, false, false);
                        if (prediction.UnitPosition.ToVector2()
                            .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true)
                            <= Math.Pow(input.Radius + 50 + hero.BoundingRadius, 2))
                        {
                            result.Add(hero);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.Walls))
                {
                    var step = position.Distance(input.From) / 20;
                    for (var i = 0; i < 20; i++)
                    {
                        var p = input.From.ToVector2().Extend(position.ToVector2(), step * i);
                        if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall))
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }

                if (input.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall))
                {
                    if (Variables.TickCount - wallCastT > 4000)
                    {
                        continue;
                    }

                    GameObject wall = null;
                    foreach (var gameObject in
                             GameObjects.AllGameObjects.Where(
                                 gameObject =>
                                 gameObject.IsValid &&
                                 Regex.IsMatch(gameObject.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase)))
                    {
                        wall = gameObject;
                    }

                    if (wall == null)
                    {
                        break;
                    }

                    var level     = wall.Name.Substring(wall.Name.Length - 6, 1);
                    var wallWidth = 300 + (50 * Convert.ToInt32(level));

                    var wallDirection = (wall.Position.ToVector2() - yasuoWallCastedPos).Normalized().Perpendicular();
                    var wallStart     = wall.Position.ToVector2() + (wallWidth / 2f * wallDirection);
                    var wallEnd       = wallStart - (wallWidth * wallDirection);

                    if (wallStart.Intersection(wallEnd, position.ToVector2(), input.From.ToVector2()).Intersects)
                    {
                        var t = Variables.TickCount
                                + (((wallStart.Intersection(wallEnd, position.ToVector2(), input.From.ToVector2())
                                     .Point.Distance(input.From) / input.Speed) + input.Delay) * 1000);
                        if (t < wallCastT + 4000)
                        {
                            result.Add(GameObjects.Player);
                        }
                    }
                }
            }

            return(result.Distinct().ToList());
        }