Esempio n. 1
0
 private static PredictionOutput GetDashingPrediction(this PredictionInput input)
 {
     var dashData = input.Unit.GetDashInfo();
     var result = new PredictionOutput { Input = input };
     if (!dashData.IsBlink)
     {
         var endP = dashData.Path.Last();
         var dashPred = input.GetPositionOnPath(
             new List<Vector2> { input.Unit.ServerPosition.ToVector2(), endP },
             dashData.Speed);
         if (dashPred.Hitchance >= HitChance.High
             && dashPred.UnitPosition.ToVector2().Distance(input.Unit.Position.ToVector2(), endP, true) < 200)
         {
             dashPred.CastPosition = dashPred.UnitPosition;
             dashPred.Hitchance = HitChance.Dashing;
             return dashPred;
         }
         if (dashData.Path.PathLength() > 200)
         {
             var timeToPoint = input.Delay / 2 + input.From.ToVector2().Distance(endP) / input.Speed - 0.25f;
             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;
     }
     return result;
 }
Esempio n. 2
0
 private static void WayPointAnalysis(this PredictionInput input, PredictionOutput result)
 {
     var totalDelay = input.Delay
                      + (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon
                             ? 0
                             : input.Unit.Distance(input.From) / input.Speed);
     var lastWaypoint = input.Unit.GetWaypoints().Last().ToVector3();
     var totalMoveSpeed = input.Unit.MoveSpeed * totalDelay;
     var minPath = 400;
     var moveAngle = 30 + input.Radius / 10;
     var fixRange = totalMoveSpeed * 0.6;
     if (Path.PathTracker.GetCurrentPath(input.Unit).Time < 0.1)
     {
         minPath = 500;
         moveAngle += 10;
         fixRange = totalMoveSpeed * 0.4;
     }
     if (input.Type == SkillshotType.SkillshotCircle)
     {
         fixRange -= input.Radius / 2;
     }
     switch (input.Type)
     {
         case SkillshotType.SkillshotLine:
             if (input.Unit.Path.Count() > 0)
             {
                 result.Hitchance = input.Unit.Path.Count() > 1
                                        ? HitChance.Medium
                                        : (input.From.GetAngle(input.Unit) < moveAngle
                                               ? HitChance.VeryHigh
                                               : HitChance.High);
             }
             break;
         case SkillshotType.SkillshotCircle:
             if (totalDelay < 0.7 && AutoAttackDetection.GetLastAutoAttackTime(input.Unit) < 0.1)
             {
                 result.Hitchance = HitChance.VeryHigh;
             }
             if (totalDelay < 1.1 && Path.PathTracker.GetCurrentPath(input.Unit).Time < 0.1)
             {
                 result.Hitchance = HitChance.VeryHigh;
             }
             break;
     }
     if (input.Unit.MoveSpeed < 250)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     if (input.Unit.Distance(lastWaypoint) > minPath)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     if (totalDelay < 0.7 + input.Radius / 500 && AutoAttackDetection.GetLastAutoAttackTime(input.Unit) < 0.1)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     if (input.Unit.Path.Count() == 0 && input.Unit.Position == input.Unit.ServerPosition
         && !input.Unit.IsWindingUp)
     {
         result.Hitchance = input.Unit.Distance(input.From) > input.Range - fixRange
                                ? HitChance.High
                                : HitChance.VeryHigh;
         return;
     }
     if (lastWaypoint.Distance(input.From) <= input.Unit.Distance(input.From)
         && input.Unit.Distance(input.From) > input.Range - fixRange)
     {
         result.Hitchance = HitChance.High;
     }
     if (input.Unit.Path.Count() > 0 && input.Unit.Distance(lastWaypoint) < totalMoveSpeed
         && Path.PathTracker.GetCurrentPath(input.Unit).Time > 0.1)
     {
         result.Hitchance = HitChance.Medium;
     }
     if (totalDelay > 0.7 + input.Radius / 500 && input.Unit.IsWindingUp)
     {
         result.Hitchance = HitChance.Medium;
     }
     if (input.Unit.Distance(input.From) < 300 || lastWaypoint.Distance(input.From) < 250
         || input.Unit.MoveSpeed < 200)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
 }
Esempio n. 3
0
 private static void WayPointAnalysis(PredictionOutput result, PredictionInput input)
 {
     var totalDelay = input.Delay
                      + (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon
                             ? 0
                             : input.Unit.Distance(input.From) / input.Speed);
     var fixRange = (input.Unit.MoveSpeed * totalDelay) / 2;
     var lastWaypiont = input.Unit.GetWaypoints().Last().ToVector3();
     if (input.Type == SkillshotType.SkillshotCircle)
     {
         fixRange -= input.Radius / 2;
     }
     switch (input.Type)
     {
         case SkillshotType.SkillshotLine:
             if (input.Unit.Path.Count() > 0)
             {
                 result.Hitchance = GetAngle(input.From, input.Unit) < 36 ? HitChance.VeryHigh : HitChance.High;
             }
             break;
         case SkillshotType.SkillshotCircle:
             if (totalDelay < 1.1
                 && ((totalDelay < 0.7 && OnProcessSpellDetection.GetLastAutoAttackTime(input.Unit) < 0.1d)
                     || Path.PathTracker.GetCurrentPath(input.Unit).Time < 0.1d))
             {
                 result.Hitchance = HitChance.VeryHigh;
             }
             break;
     }
     if (input.Unit.HasBuffOfType(BuffType.Slow) || input.Unit.Distance(input.From) < 300
         || lastWaypiont.Distance(input.From) < 250 || input.Unit.Distance(lastWaypiont) > 800)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     if (input.Unit.Path.Count() == 0 && input.Unit.Position == input.Unit.ServerPosition
         && !input.Unit.IsWindingUp)
     {
         result.Hitchance = input.Unit.Distance(input.From) > input.Range - fixRange
                                ? HitChance.High
                                : HitChance.VeryHigh;
         return;
     }
     if (lastWaypiont.Distance(input.From) <= input.Unit.Distance(input.From)
         && input.Unit.Distance(input.From) > input.Range - fixRange)
     {
         result.Hitchance = HitChance.High;
     }
     if ((input.Unit.Path.Count() > 0 && input.Unit.Distance(lastWaypiont) < input.Unit.MoveSpeed * totalDelay)
         || (totalDelay > 0.7
             && (input.Unit.IsWindingUp || OnProcessSpellDetection.GetLastAutoAttackTime(input.Unit) < 0.1d))
         || (input.Unit.Path.Count() > 1 && input.Type == SkillshotType.SkillshotLine))
     {
         result.Hitchance = HitChance.Medium;
     }
     if (input.Unit.Distance(input.From) < 300 || lastWaypiont.Distance(input.From) < 250)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
 }
Esempio n. 4
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 };
            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.ToVector2().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;
        }
Esempio n. 5
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)
        {
            PredictionOutput result = null;

            if (!input.Unit.IsValidTarget(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
                });
            }

            // 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 = GetAdvancedPrediction(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))
                {
                    if (result.Hitchance != HitChance.OutOfRange)
                    {
                        result.CastPosition = input.RangeCheckFrom
                                              + input.Range
                                              * (result.UnitPosition - input.RangeCheckFrom).Normalized().SetZ();
                    }
                    else
                    {
                        result.Hitchance = HitChance.OutOfRange;
                    }
                }
            }

            // Check for collision
            if (checkCollision && input.Collision)
            {
                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);
        }
Esempio n. 6
0
 private static PredictionOutput WayPointAnalysis(this PredictionInput input, PredictionOutput result)
 {
     if (!(input.Unit is Obj_AI_Hero))
     {
         result.Hitchance = HitChance.VeryHigh;
         return result;
     }
     if (UnitTracker.GetLastSpecialSpellTime(input.Unit) > 0)
     {
         result.Hitchance = HitChance.VeryHigh;
         return result;
     }
     result.Hitchance = HitChance.High;
     var lastWaypoint = input.Unit.GetWaypoints().Last().ToVector3();
     var distUnitToWaypoint = input.Unit.Distance(lastWaypoint);
     var distUnitToFrom = input.Unit.Distance(input.From);
     var distFromToWaypoint = input.From.Distance(lastWaypoint);
     var totalDelay = input.Delay
                      + (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon
                             ? 0
                             : distUnitToFrom / input.Speed);
     var moveArea = input.Unit.MoveSpeed * totalDelay;
     var fixRange = moveArea * 0.7f;
     var moveAngle = 30 + input.Radius / 10 - input.Delay * 5;
     var backToFront = moveArea * 1.5f;
     var minPath = 700 + backToFront;
     if (UnitTracker.CanCalcWaypoints(input.Unit))
     {
         result.Hitchance = distUnitToFrom < input.Range - fixRange ? HitChance.VeryHigh : HitChance.High;
         return result;
     }
     if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1)
     {
         fixRange = moveArea * (0.2f + input.Delay);
         backToFront = moveArea;
     }
     if (input.Type == SkillshotType.SkillshotCircle)
     {
         fixRange -= input.Radius / 2;
     }
     if (distUnitToWaypoint > minPath)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     else if (input.Type == SkillshotType.SkillshotLine)
     {
         if (input.Unit.Path.Length > 0)
         {
             if (input.From.GetAngle(input.Unit) < moveAngle)
             {
                 result.Hitchance = HitChance.VeryHigh;
             }
             else if (UnitTracker.GetLastNewPathTime(input.Unit) > 0.1)
             {
                 result.Hitchance = HitChance.High;
             }
         }
     }
     if (input.Unit.Path.Length == 0 && input.Unit.Position == input.Unit.ServerPosition)
     {
         if (UnitTracker.GetLastStopMoveTime(input.Unit) < 0.5)
         {
             result.Hitchance = HitChance.High;
         }
         else
         {
             result.Hitchance = distUnitToFrom > input.Range - fixRange ? HitChance.Medium : HitChance.VeryHigh;
         }
     }
     else if (distFromToWaypoint <= input.Unit.Distance(input.From) && distUnitToFrom > input.Range - fixRange)
     {
         result.Hitchance = HitChance.Medium;
     }
     if (UnitTracker.GetLastAttackTime(input.Unit) < 0.1)
     {
         result.Hitchance = (input.Type == SkillshotType.SkillshotLine && totalDelay < 0.8 + input.Radius * 0.001)
                            || (input.Type == SkillshotType.SkillshotCircle
                                && totalDelay < 0.6 + input.Radius * 0.001)
                                ? HitChance.VeryHigh
                                : HitChance.Medium;
     }
     if (input.Type == SkillshotType.SkillshotCircle)
     {
         if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1)
         {
             result.Hitchance = HitChance.VeryHigh;
         }
         else if (distUnitToFrom < input.Range - fixRange)
         {
             result.Hitchance = HitChance.VeryHigh;
         }
     }
     if (result.Hitchance != HitChance.Medium)
     {
         if (input.Unit.IsWindingUp && UnitTracker.GetLastAttackTime(input.Unit) > 0.1)
         {
             result.Hitchance = HitChance.Medium;
         }
         else if (input.Unit.Path.Length == 0 && input.Unit.Position != input.Unit.ServerPosition)
         {
             result.Hitchance = HitChance.Medium;
         }
         else if (input.Unit.Path.Length > 0 && distUnitToWaypoint < backToFront)
         {
             result.Hitchance = HitChance.Medium;
         }
         else if (input.Unit.Path.Length > 1)
         {
             result.Hitchance = HitChance.Medium;
         }
         else if (UnitTracker.GetLastVisableTime(input.Unit) < 0.05)
         {
             result.Hitchance = HitChance.Medium;
         }
     }
     if (distFromToWaypoint > input.Unit.Distance(input.From) && input.From.GetAngle(input.Unit) > moveAngle)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     if (input.Unit.Distance(input.From) < 400 || distFromToWaypoint < 300 || input.Unit.MoveSpeed < 200)
     {
         result.Hitchance = HitChance.VeryHigh;
     }
     return result;
 }