Beispiel #1
0
 public PredictionOutput GetPrediction(PredictionInput input)
 {
     return(this.GetPrediction(input, true, input.Collision));
 }
Beispiel #2
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>
        public PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision)
        {
            PredictionOutput result = null;

            if (!input.Unit.IsValidTarget())
            {
                return(new PredictionOutput());
            }

            input.From = input.From - (input.Unit.ServerPosition - input.From).Normalized()
                         * ObjectManager.GetLocalPlayer().BoundingRadius;

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

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

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

            if (input.Unit.IsDashing())
            {
                result = GetDashingPrediction(input);
            }
            else
            {
                var remainingImmobileT = UnitIsImmobileUntil(input.Unit);
                if (remainingImmobileT >= 0d)
                {
                    result = GetImmobilePrediction(input, remainingImmobileT);
                }
            }

            if (result == null)
            {
                result = GetStandardPrediction(input);
            }

            if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon)
            {
                if (result.HitChance >= HitChance.High && input.RangeCheckFrom.DistanceSqr(input.Unit.Position)
                    > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2))
                {
                    result.HitChance = HitChance.Medium;
                }

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

                if (input.RangeCheckFrom.DistanceSqr(result.CastPosition) > Math.Pow(input.Range, 2))
                {
                    if (result.HitChance != HitChance.OutOfRange)
                    {
                        result.CastPosition = input.RangeCheckFrom + input.Range
                                              * (result.UnitPosition - input.RangeCheckFrom).To2D().Normalized().To3D();
                    }
                    else
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }
                }
            }

            if (!checkCollision || !input.Collision)
            {
                return(result);
            }

            var positions = new List <Vector3> {
                result.UnitPosition, result.CastPosition, input.Unit.Position
            };
            var originalUnit = input.Unit;

            result.CollisionObjects = Collision.GetCollision(positions, input);
            result.CollisionObjects.RemoveAll(x => x.NetworkId == originalUnit.NetworkId);
            result.HitChance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.HitChance;

            return(result);
        }
Beispiel #3
0
        internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1)
        {
            speed = Math.Abs(speed) < 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.GetPathLength();

            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.To3D(),
                            UnitPosition = p.To3D(),
                            HitChance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d
                                ? HitChance.VeryHigh
                                : HitChance.High
                        });
                    }

                    tDistance -= d;
                }
            }
            if (pLength >= input.Delay * speed - input.RealRadius &&
                Math.Abs(input.Speed - float.MaxValue) > float.Epsilon)
            {
                var d = input.Delay * speed - input.RealRadius;
                if (input.Type == SkillshotType.Line || input.Type == SkillshotType.Cone)
                {
                    if (input.From.DistanceSquared(input.Unit.ServerPosition) < 200 * 200)
                    {
                        d = input.Delay * speed;
                    }
                }

                path = path.CutPath(d);
                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 = Geometry.VectorMovementCollision(a, b, speed, input.From.To2D(), input.Speed, tT);
                    var t   = sol.Time;
                    var pos = sol.Position;

                    if (!pos.IsZero && t >= tT && t <= tT + tB)
                    {
                        if (pos.DistanceSquared(b) < 20)
                        {
                            break;
                        }

                        var p = pos + input.RealRadius * direction;

                        return(new PredictionOutput
                        {
                            Input = input,
                            CastPosition = pos.To3D(),
                            UnitPosition = p.To3D(),
                            HitChance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1
                                ? HitChance.VeryHigh
                                : HitChance.High
                        });
                    }
                    tT += tB;
                }
            }

            var position = path.Last();

            return(new PredictionOutput
            {
                Input = input,
                CastPosition = position.To3D(),
                UnitPosition = position.To3D(),
                HitChance = HitChance.Medium
            });
        }