Beispiel #1
0
        /// <summary>
        /// Gets Aoe Prediction result
        /// </summary>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="missileSpeed">Spell missile speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="from">Spell casted position</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="Prediction.AoeResult"/></returns>
        public static Prediction.AoeResult GetAoePrediction(float width, float delay, float missileSpeed, float range, Vector2 from, Vector2 rangeCheckFrom)
        {
            var result  = new Prediction.AoeResult();
            var enemies = GameObjects.EnemyHeroes.Where(p => p.IsValidTarget() && Prediction.GetFastUnitPosition(p, delay, 0, from).Distance(rangeCheckFrom) < range);

            foreach (var enemy in enemies)
            {
                Prediction.Result prediction = GetPrediction(enemy, width, delay, missileSpeed, range, false, enemy.GetWaypoints(), enemy.AvgMovChangeTime(), enemy.LastMovChangeTime(), enemy.AvgPathLenght(), enemy.LastAngleDiff(), from, rangeCheckFrom);
                if (prediction.HitChance > HitChance.Medium)
                {
                    Vector2          to        = from + (prediction.CastPosition - from).Normalized() * range;
                    Collision.Result colResult = Collision.GetCollisions(from, to, range, width, delay, missileSpeed, false);
                    if (colResult.Objects.HasFlag(Collision.Flags.EnemyChampions))
                    {
                        int collisionCount = colResult.Units.Count(p => p.IsEnemy && p.Type == GameObjectType.AIHeroClient && p.IsValid);
                        if (collisionCount > result.HitCount)
                        {
                            result = prediction.ToAoeResult(collisionCount, colResult);
                        }
                    }
                }
            }
            return(result);
        }
Beispiel #2
0
 internal void Lock(bool checkDodge = true)
 {
     this.CollisionResult = Collision.GetCollisions(this.Input.From.LSTo2D(), this.CastPosition, this.Input.SpellRange, this.Input.SpellWidth, this.Input.SpellDelay, this.Input.SpellMissileSpeed);
     this.CheckCollisions();
     this.CheckOutofRange(checkDodge);
 }
Beispiel #3
0
        /// <summary>
        /// Gets prediction result
        /// </summary>
        /// <param name="target">Target</param>
        /// <param name="width">Vector width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="vectorSpeed">Vector speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="vectorLenght">Vector lenght</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="VectorResult"/></returns>
        public static VectorResult GetPrediction(AIBaseClient target, float width, float delay, float vectorSpeed, float range, float vectorLenght, List <Vector2> path, float avgt, float movt, float avgp, Vector2 rangeCheckFrom)
        {
            var result = new VectorResult();

            //auto aoe hit (2 hits with using one target as from position)
            if (target.Type == GameObjectType.AIHeroClient && target.IsValid)                                                                                                                                                                                                                                                                                                                     //do these calcs if champion kappa
            {
                if (ObjectManager.Player.CountEnemyHeroesInRange(range) > 0 && ObjectManager.Player.CountEnemyHeroesInRange(range + vectorLenght) > 1)                                                                                                                                                                                                                                            //if there is at least 1 enemy in range && at least 2 enemy which laser can hit
                {
                    var predPos1 = PredictionExtensions.GetFastUnitPosition(target, delay);                                                                                                                                                                                                                                                                                                       //get target unit position after delay
                    foreach (var enemy in GameObjects.EnemyHeroes)                                                                                                                                                                                                                                                                                                                                //loop all enemies
                    {
                        if (enemy.NetworkId != target.NetworkId && enemy.Distance(rangeCheckFrom) < range + vectorLenght)                                                                                                                                                                                                                                                                         //if enemy is not given target and enemy is hitable by laser
                        {
                            var predPos2 = PredictionExtensions.GetFastUnitPosition(enemy, delay);                                                                                                                                                                                                                                                                                                //get enemy unit position after delay
                            if (predPos1.Distance(rangeCheckFrom) < range)                                                                                                                                                                                                                                                                                                                        //if target is in range
                            {
                                var predRes = LinePrediction.GetLinePrediction(enemy, width, delay, vectorSpeed, vectorLenght, false, enemy.GetWaypoints(), enemy.AvgMovChangeTime(), enemy.LastMovChangeTime(), enemy.AvgPathLenght(), 360, predPos1 - (predPos1 - rangeCheckFrom).Normalized().Perpendicular() * 30, predPos1 - (predPos1 - rangeCheckFrom).Normalized().Perpendicular() * 30); //get enemy prediciton with from = target's position (a bit backward)
                                if (predRes.HitChance >= HitChance.Low)
                                {
                                    var f = predPos1 - (predPos1 - rangeCheckFrom).Normalized().Perpendicular() * 30;
                                    return(new VectorResult
                                    {
                                        CastSourcePosition = f,
                                        CastTargetPosition = predRes.CastPosition,
                                        UnitPosition = predRes.UnitPosition,
                                        HitChance = predRes.HitChance,
                                        CollisionResult = predRes.CollisionResult,
                                    });
                                }
                            }
                            else if (predPos2.Distance(rangeCheckFrom) < range)                                                                                                                                                                                                                                          //if enemy is in range
                            {
                                var predRes = LinePrediction.GetLinePrediction(target, width, delay, vectorSpeed, vectorLenght, false, path, avgt, movt, avgp, 360, predPos2 - (predPos2 - rangeCheckFrom).Normalized().Perpendicular() * 30, predPos2 - (predPos2 - rangeCheckFrom).Normalized().Perpendicular() * 30); //get target prediction with from = enemy's position (a bit backward)
                                if (predRes.HitChance >= HitChance.Low)
                                {
                                    var f = predPos2 - (predPos2 - rangeCheckFrom).Normalized().Perpendicular() * 30;
                                    return(new VectorResult
                                    {
                                        CastSourcePosition = f,
                                        CastTargetPosition = predRes.CastPosition,
                                        UnitPosition = predRes.UnitPosition,
                                        HitChance = predRes.HitChance,
                                        CollisionResult = predRes.CollisionResult,
                                    });
                                }
                            }
                        }
                    }
                }
            }

            var immobileFrom = rangeCheckFrom + (target.PreviousPosition.ToVector2() - rangeCheckFrom).Normalized() * range;

            if (path.Count <= 1) //if target is not moving, easy to hit
            {
                result.HitChance          = HitChance.VeryHigh;
                result.CastSourcePosition = immobileFrom;
                result.CastTargetPosition = target.PreviousPosition.ToVector2();
                result.UnitPosition       = result.CastTargetPosition;
                result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range, width, delay, vectorSpeed);

                if (immobileFrom.Distance(result.CastTargetPosition) > vectorLenght - PredictionExtensions.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * target.MoveSpeed)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }

            if (target is AIHeroClient hero)
            {
                if (hero.IsCastingImporantSpell())
                {
                    result.HitChance          = HitChance.VeryHigh;
                    result.CastSourcePosition = immobileFrom;
                    result.CastTargetPosition = hero.PreviousPosition.ToVector2();
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range, width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) > range - PredictionExtensions.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * hero.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }

                //to do: find a fuking logic
                if (avgp < 400 && movt < 100)
                {
                    result.HitChance          = HitChance.High;
                    result.CastTargetPosition = hero.PreviousPosition.ToVector2();
                    result.CastSourcePosition = immobileFrom;
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range, width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) > range - PredictionExtensions.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * hero.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }
            }

            if (target.IsDashing())
            {
                var dashPred = PredictionExtensions.GetDashingPrediction(target, width, delay, vectorSpeed, range, false, SpellType.Line, immobileFrom, rangeCheckFrom);
                return(new VectorResult
                {
                    CastSourcePosition = immobileFrom,
                    CastTargetPosition = dashPred.CastPosition,
                    UnitPosition = dashPred.UnitPosition,
                    HitChance = dashPred.HitChance,
                    CollisionResult = dashPred.CollisionResult,
                });
            }

            if (target.IsImmobileTarget())
            {
                var immoPred = PredictionExtensions.GetImmobilePrediction(target, width, delay, vectorSpeed, range, false, SpellType.Line, immobileFrom, rangeCheckFrom);
                return(new VectorResult
                {
                    CastSourcePosition = immobileFrom,
                    CastTargetPosition = immoPred.CastPosition,
                    UnitPosition = immoPred.UnitPosition,
                    HitChance = immoPred.HitChance,
                    CollisionResult = immoPred.CollisionResult,
                });
            }

            for (var i = 0; i < path.Count - 1; i++)
            {
                var point = Geometry.ClosestCirclePoint(rangeCheckFrom, range, path[i]);
                if (path[i].Distance(ObjectManager.Player.PreviousPosition) < range)
                {
                    point = path[i];
                }

                var res = PredictionExtensions.WaypointAnlysis(target, width, delay, vectorSpeed, vectorLenght, false, SpellType.Line, path, avgt, movt, avgp, 360, point);
                res.Input = new PredictionInput(target, delay, vectorSpeed, width, range, false, SpellType.Line, rangeCheckFrom.ToVector3World(), rangeCheckFrom.ToVector3World());
                res.Lock();
                if (res.HitChance >= HitChance.Low)
                {
                    return(new VectorResult
                    {
                        CastSourcePosition = point,
                        CastTargetPosition = res.CastPosition,
                        UnitPosition = res.UnitPosition,
                        HitChance = res.HitChance,
                        CollisionResult = res.CollisionResult,
                    });
                }
            }

            result.CastSourcePosition = immobileFrom;
            result.CastTargetPosition = target.PreviousPosition.ToVector2();
            result.HitChance          = HitChance.None;
            return(result);
        }
Beispiel #4
0
        /// <summary>
        /// Gets Aoe Prediction result
        /// </summary>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="vectorSpeed">Vector speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="vectorLenght">Vector lenght</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="SpellAoeResult"/></returns>
        public static VectorAoeResult GetAoePrediction(float width, float delay, float vectorSpeed, float range, float vectorLenght, Vector2 rangeCheckFrom)
        {
            var result  = new VectorAoeResult();
            var enemies = GameObjects.EnemyHeroes.Where(p => p.IsValidTarget() && PredictionExtensions.GetFastUnitPosition(p, delay, 0, rangeCheckFrom).Distance(rangeCheckFrom) < range);

            foreach (var enemy in enemies)
            {
                var path = enemy.GetWaypoints();
                if (path.Count <= 1)
                {
                    var from      = rangeCheckFrom + (enemy.PreviousPosition.ToVector2() - rangeCheckFrom).Normalized() * range;
                    var to        = from + (enemy.PreviousPosition.ToVector2() - from).Normalized() * vectorLenght;
                    var colResult = Collision.GetCollisions(from, to, range, width, delay, vectorSpeed);

                    if (colResult.Objects.HasFlag(CollisionFlags.EnemyChampions))
                    {
                        var collisionCount = colResult.Units.Count(p => p.IsEnemy && p.Type == GameObjectType.AIHeroClient && p.IsValid);
                        if (collisionCount > result.HitCount)
                        {
                            result = new VectorAoeResult
                            {
                                CastSourcePosition = from,
                                CastTargetPosition = enemy.PreviousPosition.ToVector2(),
                                HitCount           = collisionCount,
                                CollisionResult    = colResult
                            };
                        }
                    }
                }
                else
                {
                    if (!enemy.IsDashing())
                    {
                        for (var i = 0; i < path.Count - 1; i++)
                        {
                            var point      = Geometry.ClosestCirclePoint(rangeCheckFrom, range, path[i]);
                            var prediction = PredictionExtensions.GetPrediction(enemy, width, delay, vectorSpeed, vectorLenght, false, SpellType.Line, path, enemy.AvgMovChangeTime(), enemy.LastMovChangeTime(), enemy.AvgPathLenght(), enemy.LastAngleDiff(), point, rangeCheckFrom);
                            if (prediction.HitChance > HitChance.Medium)
                            {
                                var to        = point + (prediction.CastPosition - point).Normalized() * vectorLenght;
                                var colResult = Collision.GetCollisions(point, to, range, width, delay, vectorSpeed);
                                if (colResult.Objects.HasFlag(CollisionFlags.EnemyChampions))
                                {
                                    var collisionCount = colResult.Units.Count(p => p.IsEnemy && p.Type == GameObjectType.AIHeroClient && p.IsValid);
                                    if (collisionCount > result.HitCount)
                                    {
                                        result = new VectorAoeResult
                                        {
                                            CastSourcePosition = point,
                                            CastTargetPosition = prediction.CastPosition,
                                            HitCount           = collisionCount,
                                            CollisionResult    = colResult
                                        };
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(result);
        }
Beispiel #5
0
        /// <summary>
        ///     Gets prediction result
        /// </summary>
        /// <param name="target">Target</param>
        /// <param name="width">Vector width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="vectorSpeed">Vector speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="vectorLenght">Vector lenght</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="Prediction.Vector.Result" /></returns>
        public static Result GetPrediction(Obj_AI_Base target, float width, float delay, float vectorSpeed, float range,
                                           float vectorLenght, List <Vector2> path, float avgt, float movt, float avgp, Vector2 rangeCheckFrom)
        {
            Prediction.AssertInitializationMode();

            var result = new Result();

            //auto aoe hit (2 hits with using one target as from position)
            if (target.IsChampion()) //do these calcs if champion kappa
            {
                if (ObjectManager.Player.CountEnemiesInRange(range) > 0 &&
                    ObjectManager.Player.CountEnemiesInRange(range + vectorLenght) > 1)
                //if there is at least 1 enemy in range && at least 2 enemy which laser can hit
                {
                    var predPos1 = Prediction.GetFastUnitPosition(target, delay); //get target unit position after delay
                    foreach (var enemy in HeroManager.Enemies)                    //loop all enemies
                    {
                        if (enemy.NetworkId != target.NetworkId && enemy.Distance(rangeCheckFrom) < range + vectorLenght)
                        //if enemy is not given target and enemy is hitable by laser
                        {
                            var predPos2 = Prediction.GetFastUnitPosition(enemy, delay);
                            //get enemy unit position after delay
                            if (predPos1.Distance(rangeCheckFrom) < range) //if target is in range
                            {
                                var predRes = LinePrediction.GetPrediction(enemy, width, delay, vectorSpeed,
                                                                           vectorLenght, false, enemy.GetWaypoints(), enemy.AvgMovChangeTime(),
                                                                           enemy.LastMovChangeTime(), enemy.AvgPathLenght(), 360,
                                                                           predPos1 - (predPos1 - rangeCheckFrom).Normalized().Perpendicular() * 30,
                                                                           predPos1 - (predPos1 - rangeCheckFrom).Normalized().Perpendicular() * 30);
                                //get enemy prediciton with from = target's position (a bit backward)
                                if (predRes.HitChance >= HitChance.Low)
                                {
                                    return
                                        (predRes.AsVectorResult(predPos1 -
                                                                (predPos1 - rangeCheckFrom).Normalized().Perpendicular() *
                                                                30));
                                }
                            }
                            else if (predPos2.Distance(rangeCheckFrom) < range) //if enemy is in range
                            {
                                var predRes = LinePrediction.GetPrediction(target, width, delay, vectorSpeed,
                                                                           vectorLenght, false, path, avgt, movt, avgp, 360,
                                                                           predPos2 - (predPos2 - rangeCheckFrom).Normalized().Perpendicular() * 30,
                                                                           predPos2 - (predPos2 - rangeCheckFrom).Normalized().Perpendicular() * 30);
                                //get target prediction with from = enemy's position (a bit backward)
                                if (predRes.HitChance >= HitChance.Low)
                                {
                                    return
                                        (predRes.AsVectorResult(predPos2 -
                                                                (predPos2 - rangeCheckFrom).Normalized().Perpendicular() *
                                                                30));
                                }
                            }
                        }
                    }
                }
            }

            var immobileFrom = rangeCheckFrom + (target.ServerPosition.To2D() - rangeCheckFrom).Normalized() * range;

            if (path.Count <= 1) //if target is not moving, easy to hit
            {
                result.HitChance          = HitChance.VeryHigh;
                result.CastSourcePosition = immobileFrom;
                result.CastTargetPosition = target.ServerPosition.To2D();
                result.UnitPosition       = result.CastTargetPosition;
                result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range, width,
                                                                    delay, vectorSpeed);

                if (immobileFrom.Distance(result.CastTargetPosition) >
                    vectorLenght -
                    Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) *
                    target.MoveSpeed)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }

            if (target is AIHeroClient)
            {
                if (((AIHeroClient)target).IsChannelingImportantSpell())
                {
                    result.HitChance          = HitChance.VeryHigh;
                    result.CastSourcePosition = immobileFrom;
                    result.CastTargetPosition = target.ServerPosition.To2D();
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range,
                                                                        width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) >
                        range -
                        Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) *
                        target.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }

                //to do: find a fuking logic
                if (avgp < 400 && movt < 100)
                {
                    result.HitChance          = HitChance.High;
                    result.CastTargetPosition = target.ServerPosition.To2D();
                    result.CastSourcePosition = immobileFrom;
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, range,
                                                                        width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) >
                        range -
                        Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) *
                        target.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }
            }

            if (target.IsDashing())
            {
                return
                    (Prediction.GetDashingPrediction(target, width, delay, vectorSpeed, range, false,
                                                     SkillshotType.SkillshotLine, immobileFrom, rangeCheckFrom).AsVectorResult(immobileFrom));
            }

            if (Utility.IsImmobileTarget(target))
            {
                return
                    (Prediction.GetImmobilePrediction(target, width, delay, vectorSpeed, range, false,
                                                      SkillshotType.SkillshotLine, immobileFrom, rangeCheckFrom).AsVectorResult(immobileFrom));
            }

            for (var i = 0; i < path.Count - 1; i++)
            {
                var point = Vector2.Zero;
                point = path[i].Distance(ObjectManager.Player.ServerPosition) < range ? path[i] : Geometry.ClosestCirclePoint(rangeCheckFrom, range, path[i]);

                var res = Prediction.WaypointAnlysis(target, width, delay, vectorSpeed, vectorLenght, false,
                                                     SkillshotType.SkillshotLine, path, avgt, movt, avgp, 360, point);
                res.Lock();
                if (res.HitChance >= HitChance.Low)
                {
                    return(res.AsVectorResult(point));
                }
            }

            result.CastSourcePosition = immobileFrom;
            result.CastTargetPosition = target.ServerPosition.To2D();
            result.HitChance          = HitChance.Impossible;
            return(result);
        }
        /// <summary>
        /// Gets prediction result
        /// </summary>
        /// <param name="target">Target</param>
        /// <param name="width">Vector width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="vectorSpeed">Vector speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="vectorLenght">Vector lenght</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="Prediction.Vector.Result"/></returns>
        public static Result GetPrediction(Obj_AI_Base target, float width, float delay, float vectorSpeed, float range, float vectorLenght, List <Vector2> path, float avgt, float movt, float avgp, Vector2 rangeCheckFrom)
        {
            Prediction.AssertInitializationMode();

            Result result = new Result();

            Vector2 immobileFrom = rangeCheckFrom + (target.ServerPosition.To2D() - rangeCheckFrom).Normalized() * range;

            if (path.Count <= 1) //if target is not moving, easy to hit
            {
                result.HitChance          = HitChance.VeryHigh;
                result.CastTargetPosition = target.ServerPosition.To2D();
                result.UnitPosition       = result.CastTargetPosition;
                result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, width, delay, vectorSpeed);


                if (immobileFrom.Distance(result.CastTargetPosition) > vectorLenght - Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * target.MoveSpeed)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }

            if (target is Obj_AI_Hero)
            {
                if (((Obj_AI_Hero)target).IsChannelingImportantSpell())
                {
                    result.HitChance          = HitChance.VeryHigh;
                    result.CastTargetPosition = target.ServerPosition.To2D();
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) > range - Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * target.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }

                //to do: find a fuking logic
                if (avgp < 400 && movt < 100)
                {
                    result.HitChance          = HitChance.High;
                    result.CastTargetPosition = target.ServerPosition.To2D();
                    result.UnitPosition       = result.CastTargetPosition;
                    result.CollisionResult    = Collision.GetCollisions(immobileFrom, result.CastTargetPosition, width, delay, vectorSpeed);

                    //check if target can dodge with moving backward
                    if (immobileFrom.Distance(result.CastTargetPosition) > range - Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * target.MoveSpeed)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }
            }

            if (target.IsDashing())
            {
                return(Prediction.GetDashingPrediction(target, width, delay, vectorSpeed, range, false, SkillshotType.SkillshotLine, immobileFrom).AsVectorResult(immobileFrom));
            }

            if (SPrediction.Utility.IsImmobileTarget(target))
            {
                return(Prediction.GetImmobilePrediction(target, width, delay, vectorSpeed, range, false, SkillshotType.SkillshotLine, immobileFrom).AsVectorResult(immobileFrom));
            }

            for (int i = 0; i < path.Count - 1; i++)
            {
                Vector2           point = Geometry.ClosestCirclePoint(rangeCheckFrom, range, path[i], path[i + 1]);
                Prediction.Result res   = Prediction.WaypointAnlysis(target, width, delay, vectorSpeed, vectorLenght, false, SkillshotType.SkillshotLine, path, avgt, movt, avgp, point);
                if (res.HitChance >= HitChance.Low)
                {
                    return(res.AsVectorResult(point));
                }
            }

            result.CastSourcePosition = immobileFrom;
            result.CastTargetPosition = target.ServerPosition.To2D();
            result.HitChance          = HitChance.Impossible;
            return(result);
        }
        /// <summary>
        /// Gets Aoe Prediction result
        /// </summary>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="vectorSpeed">Vector speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="vectorLenght">Vector lenght</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="Prediction.AoeResult"/></returns>
        public static AoeResult GetAoePrediction(float width, float delay, float vectorSpeed, float range, float vectorLenght, Vector2 rangeCheckFrom)
        {
            AoeResult result  = new AoeResult();
            var       enemies = HeroManager.Enemies.Where(p => p.IsValidTarget() && Prediction.GetFastUnitPosition(p, delay, 0, rangeCheckFrom).Distance(rangeCheckFrom) < range);

            foreach (Obj_AI_Hero enemy in enemies)
            {
                List <Vector2> path = enemy.GetWaypoints();
                if (path.Count <= 1)
                {
                    Vector2          from      = rangeCheckFrom + (enemy.ServerPosition.To2D() - rangeCheckFrom).Normalized() * range;
                    Vector2          to        = from + (enemy.ServerPosition.To2D() - from).Normalized() * vectorLenght;
                    Collision.Result colResult = Collision.GetCollisions(from, to, width, delay, vectorSpeed);

                    if (colResult.Objects.HasFlag(Collision.Flags.EnemyChampions))
                    {
                        int collisionCount = colResult.Units.Count(p => p.IsEnemy && p.IsChampion());
                        if (collisionCount > result.HitCount)
                        {
                            result = new AoeResult
                            {
                                CastSourcePosition = from,
                                CastTargetPosition = enemy.ServerPosition.To2D(),
                                HitCount           = collisionCount,
                                CollisionResult    = colResult
                            };
                        }
                    }
                }
                else
                {
                    if (!enemy.IsDashing())
                    {
                        for (int i = 0; i < path.Count - 1; i++)
                        {
                            Vector2           point      = Geometry.ClosestCirclePoint(rangeCheckFrom, range, path[i], path[i + 1]);
                            Prediction.Result prediction = Prediction.GetPrediction(enemy, width, delay, vectorSpeed, vectorLenght, false, SkillshotType.SkillshotLine, path, enemy.AvgMovChangeTime(), enemy.LastMovChangeTime(), enemy.AvgPathLenght(), point, rangeCheckFrom);
                            if (prediction.HitChance > HitChance.Medium)
                            {
                                Vector2          to        = point + (prediction.CastPosition - point).Normalized() * vectorLenght;
                                Collision.Result colResult = Collision.GetCollisions(point, to, width, delay, vectorSpeed, false);
                                if (colResult.Objects.HasFlag(Collision.Flags.EnemyChampions))
                                {
                                    int collisionCount = colResult.Units.Count(p => p.IsEnemy && p.IsChampion());
                                    if (collisionCount > result.HitCount)
                                    {
                                        result = new AoeResult
                                        {
                                            CastSourcePosition = point,
                                            CastTargetPosition = prediction.CastPosition,
                                            HitCount           = collisionCount,
                                            CollisionResult    = colResult
                                        };
                                    }
                                }
                            }
                        }
                    }
                }
            }
            return(result);
        }
 /// <summary>
 /// Gets collided units & flags
 /// </summary>
 /// <param name="to">End position</param>
 /// <param name="isArc">Checks collision for arc spell</param>
 /// <returns>Collision result as <see cref="Collision.Result"/></returns>
 public static Collision.Result GetCollisions(this Spell s, Vector2 to, bool isArc = false)
 {
     return(Collision.GetCollisions(s.From.ToVector2(), to, s.Range, s.Width, s.Delay, s.Speed, isArc));
 }
        /// <summary>
        /// Calculates cast position with target's path
        /// </summary>
        /// <param name="target">Target for spell</param>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="missileSpeed">Spell missile speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="collisionable">Spell collisionable</param>
        /// <param name="type">Spell skillshot type</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="from">Spell casted position</param>
        /// <returns></returns>
        internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, float moveSpeed = 0, bool isDash = false)
        {
            if (moveSpeed == 0)
            {
                moveSpeed = target.MoveSpeed;
            }

            Result result = new Result();

            float flyTimeMax = 0f;

            if (missileSpeed != 0) //skillshot with a missile
            {
                flyTimeMax = range / missileSpeed;
            }

            float tMin     = delay + Game.Ping / 2000f + SpellDelay / 1000f;
            float tMax     = flyTimeMax + delay + Game.Ping / 1000f + SpellDelay / 1000f;
            float pathTime = 0f;

            int[] pathBounds = new int[] { -1, -1 };

            //find bounds
            for (int i = 0; i < path.Count - 1; i++)
            {
                float t = path[i + 1].Distance(path[i]) / moveSpeed;

                if (pathTime <= tMin && pathTime + t >= tMin)
                {
                    pathBounds[0] = i;
                }
                if (pathTime <= tMax && pathTime + t >= tMax)
                {
                    pathBounds[1] = i;
                }

                if (pathBounds[0] != -1 && pathBounds[1] != -1)
                {
                    break;
                }

                pathTime += t;
            }

            //calculate cast & unit position
            if (pathBounds[0] != -1 && pathBounds[1] != -1)
            {
                for (int k = pathBounds[0]; k <= pathBounds[1]; k++)
                {
                    Vector2 direction = (path[k + 1] - path[k]).Normalized();
                    float   distance  = width;

                    int steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance);
                    //split & anlyse current path
                    for (int i = 1; i < steps - 1; i++)
                    {
                        Vector2 pCenter = path[k] + (direction * distance * i);
                        Vector2 pA      = pCenter - (direction * target.BoundingRadius);
                        Vector2 pB      = pCenter + (direction * target.BoundingRadius);

                        float flytime = missileSpeed != 0 ? from.Distance(pCenter) / missileSpeed : 0f;
                        float t       = flytime + delay + Game.Ping / 2000f + SpellDelay / 1000f;

                        Vector2 currentPosition = target.ServerPosition.To2D();

                        float arriveTimeA = currentPosition.Distance(pA) / moveSpeed;
                        float arriveTimeB = currentPosition.Distance(pB) / moveSpeed;

                        if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t)
                        {
                            result.HitChance    = GetHitChance(t, avgt, movt, avgp, anglediff);
                            result.CastPosition = pCenter;
                            result.UnitPosition = pCenter; //+ (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed);

                            /*if (currentPosition.IsBetween(ObjectManager.Player.ServerPosition.To2D(), result.CastPosition))
                             * {
                             *  result.CastPosition = currentPosition;
                             *  Console.WriteLine("corrected");
                             * }*/
                            result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);
                            return(result);
                        }
                    }
                }
            }

            result.HitChance = HitChance.Impossible;

            return(result);
        }
        /// <summary>
        /// Gets Prediction result while unit is immobile
        /// </summary>
        /// <param name="target">Target for spell</param>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="missileSpeed">Spell missile speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="collisionable">Spell collisionable</param>
        /// <param name="type">Spell skillshot type</param>
        /// <param name="from">Spell casted position</param>
        /// <returns></returns>
        internal static Result GetImmobilePrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from)
        {
            Result result = new Result();

            result.CastPosition = target.ServerPosition.To2D();
            result.UnitPosition = result.CastPosition;

            //calculate spell arrival time
            float t = delay + Game.Ping / 2000f;

            if (missileSpeed != 0)
            {
                t += from.Distance(target.ServerPosition) / missileSpeed;
            }

            if (type == SkillshotType.SkillshotCircle)
            {
                t += width / target.MoveSpeed / 2f;
            }

            if (t >= Utility.LeftImmobileTime(target))
            {
                result.HitChance       = HitChance.Immobile;
                result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);

                if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions))
                {
                    result.HitChance = HitChance.Collision;
                }

                if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }

            if (target is Obj_AI_Hero)
            {
                result.HitChance = GetHitChance(t - Utility.LeftImmobileTime(target), ((Obj_AI_Hero)target).AvgMovChangeTime(), 0, 0, 0);
            }
            else
            {
                result.HitChance = HitChance.High;
            }

            //check collisions
            if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions))
            {
                result.HitChance = HitChance.Collision;
            }

            //check range
            if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
            {
                result.HitChance = HitChance.OutOfRange;
            }

            return(result);
        }
        /// <summary>
        /// Gets Prediction result
        /// </summary>
        /// <param name="target">Target for spell</param>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="missileSpeed">Spell missile speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="collisionable">Spell collisionable</param>
        /// <param name="type">Spell skillshot type</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="from">Spell casted position</param>
        /// <param name="rangeCheckFrom"></param>
        /// <returns>Prediction result as <see cref="Prediction.Result"/></returns>
        internal static Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, Vector2 rangeCheckFrom)
        {
            Prediction.AssertInitializationMode();

            Result result = new Result();

            try
            {
                if (type == SkillshotType.SkillshotCircle)
                {
                    range += width;
                }

                //to do: hook logic ? by storing average movement direction etc
                if (path.Count <= 1 && movt > 100 && (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick > 300 || !predMenu.Item("SPREDWINDUP").GetValue <bool>())) //if target is not moving, easy to hit (and not aaing)
                {
                    result.HitChance       = HitChance.VeryHigh;
                    result.CastPosition    = target.ServerPosition.To2D();
                    result.UnitPosition    = result.CastPosition;
                    result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);

                    if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall)))
                    {
                        result.HitChance = HitChance.Collision;
                    }

                    if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
                    {
                        result.HitChance = HitChance.OutOfRange;
                    }

                    return(result);
                }

                if (target is Obj_AI_Hero)
                {
                    if (((Obj_AI_Hero)target).IsChannelingImportantSpell())
                    {
                        result.HitChance       = HitChance.VeryHigh;
                        result.CastPosition    = target.ServerPosition.To2D();
                        result.UnitPosition    = result.CastPosition;
                        result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);

                        //check collisions
                        if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall)))
                        {
                            result.HitChance = HitChance.Collision;
                        }

                        //check if target can dodge with moving backward
                        if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
                        {
                            result.HitChance = HitChance.OutOfRange;
                        }

                        return(result);
                    }

                    if (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick < 300 && predMenu.Item("SPREDWINDUP").GetValue <bool>())
                    {
                        if (target.AttackCastDelay * 1000 + PathTracker.EnemyInfo[target.NetworkId].AvgOrbwalkTime + avgt - width / 2f / target.MoveSpeed >= GetArrivalTime(target.ServerPosition.To2D().Distance(from), delay, missileSpeed))
                        {
                            result.HitChance       = HitChance.High;
                            result.CastPosition    = target.ServerPosition.To2D();
                            result.UnitPosition    = result.CastPosition;
                            result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);

                            //check collisions
                            if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall)))
                            {
                                result.HitChance = HitChance.Collision;
                            }

                            return(result);
                        }
                    }

                    //to do: find a fuking logic
                    if (avgp < 400 && movt < 100 && path.PathLength() <= avgp)
                    {
                        result.HitChance       = HitChance.High;
                        result.CastPosition    = path.Last();
                        result.UnitPosition    = result.CastPosition;
                        result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);

                        //check collisions
                        if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall)))
                        {
                            result.HitChance = HitChance.Collision;
                        }

                        //check if target can dodge with moving backward
                        if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
                        {
                            result.HitChance = HitChance.OutOfRange;
                        }

                        return(result);
                    }
                }

                if (target.IsDashing()) //if unit is dashing
                {
                    return(GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, type, from));
                }

                if (Utility.IsImmobileTarget(target)) //if unit is immobile
                {
                    return(GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, type, from));
                }

                result = WaypointAnlysis(target, width, delay, missileSpeed, range, collisionable, type, path, avgt, movt, avgp, anglediff, from);

                float d = result.CastPosition.Distance(target.ServerPosition.To2D());
                if (d >= (avgt - movt) * target.MoveSpeed && d >= avgp)
                {
                    result.HitChance = HitChance.Medium;
                }

                //check collisions
                if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall)))
                {
                    result.HitChance = HitChance.Collision;
                }

                //check if target can dodge with moving backward
                if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }
            finally
            {
                //check if movement changed while prediction calculations
                if (!target.GetWaypoints().SequenceEqual(path))
                {
                    result.HitChance = HitChance.Medium;
                }
            }
        }
Beispiel #12
0
        /// <summary>
        /// Calculates cast position with target's path
        /// </summary>
        /// <param name="target">Target for spell</param>
        /// <param name="width">Spell width</param>
        /// <param name="delay">Spell delay</param>
        /// <param name="missileSpeed">Spell missile speed</param>
        /// <param name="range">Spell range</param>
        /// <param name="collisionable">Spell collisionable</param>
        /// <param name="type">Spell skillshot type</param>
        /// <param name="path">Waypoints of target</param>
        /// <param name="avgt">Average reaction time (in ms)</param>
        /// <param name="movt">Passed time from last movement change (in ms)</param>
        /// <param name="avgp">Average Path Lenght</param>
        /// <param name="from">Spell casted position</param>
        /// <returns></returns>
        internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, Vector2 from, float moveSpeed = 0, bool isDash = false)
        {
            if (moveSpeed == 0)
            {
                moveSpeed = target.MoveSpeed;
            }

            Result result = new Result();

            float flyTimeMax = 0f;

            if (missileSpeed != 0) //skillshot with a missile
            {
                flyTimeMax = range / missileSpeed;
            }

            float tMin     = delay + Game.Ping / 2000f + SpellDelay / 1000f;
            float tMax     = flyTimeMax + delay + Game.Ping / 1000f + SpellDelay / 1000f;
            float pathTime = 0f;

            int[] pathBounds = new int[] { -1, -1 };

            //find bounds
            for (int i = 0; i < path.Count - 1; i++)
            {
                float t = path[i + 1].Distance(path[i]) / moveSpeed;

                if (pathTime <= tMin && pathTime + t >= tMin)
                {
                    pathBounds[0] = i;
                }
                if (pathTime <= tMax && pathTime + t >= tMax)
                {
                    pathBounds[1] = i;
                }

                if (pathBounds[0] != -1 && pathBounds[1] != -1)
                {
                    break;
                }

                pathTime += t;
            }

            //calculate cast & unit position
            if (pathBounds[0] != -1 && pathBounds[1] != -1)
            {
                for (int k = pathBounds[0]; k <= pathBounds[1]; k++)
                {
                    Vector2 direction = (path[k + 1] - path[k]).Normalized();
                    float   distance  = width;
                    if (predMenu.Item("SPREDWPANALYSIS").GetValue <StringList>().SelectedIndex == 0)
                    {
                        distance = target.BoundingRadius;
                    }

                    int steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance);
                    //split & anlyse current path
                    for (int i = 0; i < steps; i++)
                    {
                        Vector2 pA     = path[k] + (direction * distance * i);
                        Vector2 pB     = path[k] + (direction * distance * (i + 1));
                        Vector2 center = (pA + pB) / 2f;

                        float flytime = missileSpeed != 0 ? from.Distance(center) / missileSpeed : 0f;
                        float t       = flytime + delay + Game.Ping / 1000f + SpellDelay / 1000f;

                        Vector2 currentPosition = isDash ? target.Position.To2D() : target.ServerPosition.To2D();

                        float arriveTimeA = currentPosition.Distance(pA) / moveSpeed;
                        float arriveTimeB = currentPosition.Distance(pB) / moveSpeed;

                        if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t)
                        {
                            result.HitChance       = GetHitChance(t, avgt, movt, avgp);
                            result.CastPosition    = center;
                            result.UnitPosition    = center + (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed);
                            result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);
                            return(result);
                        }
                    }

                    if (steps == 0)
                    {
                        float flytime = missileSpeed != 0 ? from.Distance(path[pathBounds[1]]) / missileSpeed : 0f;
                        float t       = flytime + delay + Game.Ping / 2000f + SpellDelay / 1000f;
                        result.HitChance       = GetHitChance(t, avgt, movt, avgp);
                        result.CastPosition    = path[pathBounds[1]];
                        result.UnitPosition    = path[pathBounds[1]];
                        result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed);
                        return(result);
                    }
                }
            }

            result.HitChance = HitChance.Impossible;

            return(result);
        }