Ejemplo n.º 1
0
        /// <summary>
        /// Spell extension for cast spell with SPrediction
        /// </summary>
        /// <param name="s">Spell to cast</param>
        /// <param name="t">Target for spell</param>
        /// <param name="hc">Minimum HitChance to cast</param>
        /// <param name="reactionIgnoreDelay">Delay to ignore target's reaction time</param>
        /// <param name="minHit">Minimum Hit Count to cast</param>
        /// <param name="rangeCheckFrom">Position where spell will be casted from</param>
        /// <param name="filterHPPercent">Minimum HP Percent to cast (for target)</param>
        /// <returns>true if spell has casted</returns>
        public static bool SPredictionCast(this Spell s, Obj_AI_Hero t, HitChance hc, int reactionIgnoreDelay = 0, byte minHit = 1, Vector3?rangeCheckFrom = null, float filterHPPercent = 100)
        {
            if (rangeCheckFrom == null)
            {
                rangeCheckFrom = ObjectManager.Player.ServerPosition;
            }

            if (t == null)
            {
                return(s.Cast());
            }

            if (!s.IsSkillshot)
            {
                return(s.Cast(t) == Spell.CastStates.SuccessfullyCasted);
            }

            #region if common prediction selected
            if (Prediction.predMenu != null && Prediction.predMenu.Item("PREDICTONLIST").GetValue <StringList>().SelectedIndex == 1)
            {
                var pout = s.GetPrediction(t, minHit > 1);

                if (minHit > 1)
                {
                    if (pout.AoeTargetsHitCount >= minHit)
                    {
                        return(s.Cast(pout.CastPosition));
                    }
                    else
                    {
                        return(false);
                    }
                }

                if (pout.Hitchance >= hc)
                {
                    return(s.Cast(pout.CastPosition));
                }
                else
                {
                    return(false);
                }
            }
            #endregion

            if (minHit > 1)
            {
                return(SPredictionCastAoe(s, minHit));
            }

            if (t.HealthPercent > filterHPPercent)
            {
                return(false);
            }

            if (Monitor.TryEnter(PathTracker.EnemyInfo[t.NetworkId].m_lock))
            {
                try
                {
                    float avgt      = t.AvgMovChangeTime() + reactionIgnoreDelay;
                    float movt      = t.LastMovChangeTime();
                    float avgp      = t.AvgPathLenght();
                    var   waypoints = t.GetWaypoints();

                    Prediction.Result result;

                    switch (s.Type)
                    {
                    case SkillshotType.SkillshotLine: result = LinePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, s.From.To2D(), s.RangeCheckFrom.To2D());
                        break;

                    case SkillshotType.SkillshotCircle: result = CirclePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, s.From.To2D(), s.RangeCheckFrom.To2D());
                        break;

                    case SkillshotType.SkillshotCone: result = ConePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, s.From.To2D(), s.RangeCheckFrom.To2D());
                        break;

                    default:
                        throw new InvalidOperationException("Unknown spell type");
                    }

                    Prediction.lastDrawTick      = Utils.TickCount;
                    Prediction.lastDrawPos       = result.CastPosition;
                    Prediction.lastDrawHitchance = result.HitChance.ToString();
                    Prediction.lastDrawDirection = (result.CastPosition - s.From.To2D()).Normalized().Perpendicular();
                    Prediction.lastDrawWidth     = (int)s.Width;

                    if (result.HitChance >= hc)
                    {
                        s.Cast(result.CastPosition);
                        return(true);
                    }

                    Monitor.Pulse(PathTracker.EnemyInfo[t.NetworkId].m_lock);
                    return(false);
                }
                finally
                {
                    Monitor.Exit(PathTracker.EnemyInfo[t.NetworkId].m_lock);
                }
            }

            return(false);
        }
Ejemplo n.º 2
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(AIBaseClient 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();

            //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
                {
                    Vector2 predPos1 = Prediction.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
                        {
                            Vector2 predPos2 = Prediction.GetFastUnitPosition(enemy, delay);                                                                                                                                                                                                                                                                                                                //get enemy unit position after delay
                            if (predPos1.Distance(rangeCheckFrom) < range)                                                                                                                                                                                                                                                                                                                                  //if target is in range
                            {
                                Prediction.Result 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
                            {
                                Prediction.Result 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));
                                }
                            }
                        }
                    }
                }
            }

            Vector2 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 - Prediction.GetArrivalTime(immobileFrom.Distance(result.CastTargetPosition), delay, vectorSpeed) * target.MoveSpeed)
                {
                    result.HitChance = HitChance.OutOfRange;
                }

                return(result);
            }

            if (target is AIHeroClient)
            {
                if (((AIHeroClient)target).IsCastingImporantSpell())
                {
                    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);

                    //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.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 - 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, SpellType.Line, immobileFrom, rangeCheckFrom).AsVectorResult(immobileFrom));
            }

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

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

                var res = Prediction.WaypointAnlysis(target, width, delay, vectorSpeed, vectorLenght, false, SpellType.Line, path, avgt, movt, avgp, 360, point);
                res.Input = new Prediction.Input(target, delay, vectorSpeed, width, range, false, SpellType.Line, rangeCheckFrom.ToVector3World(), rangeCheckFrom.ToVector3World());
                res.Lock();
                if (res.HitChance >= HitChance.Low)
                {
                    return(res.AsVectorResult(point));
                }
            }

            result.CastSourcePosition = immobileFrom;
            result.CastTargetPosition = target.PreviousPosition.ToVector2();
            result.HitChance          = HitChance.None;
            return(result);
        }
Ejemplo n.º 3
0
        /// <summary>
        /// Spell extension for cast spell with SPrediction
        /// </summary>
        /// <param name="s">Spell to cast</param>
        /// <param name="t">Target for spell</param>
        /// <param name="hc">Minimum HitChance to cast</param>
        /// <param name="reactionIgnoreDelay">Delay to ignore target's reaction time</param>
        /// <param name="minHit">Minimum Hit Count to cast</param>
        /// <param name="rangeCheckFrom">Position where spell will be casted from</param>
        /// <param name="filterHPPercent">Minimum HP Percent to cast (for target)</param>
        /// <returns>true if spell has casted</returns>
        public static bool SPredictionCast(this Spell s, AIHeroClient t, HitChance hc, int reactionIgnoreDelay = 0, byte minHit = 1, Vector3?rangeCheckFrom = null, float filterHPPercent = 100)
        {
            if (rangeCheckFrom == null)
            {
                rangeCheckFrom = ObjectManager.Player.ServerPosition;
            }

            if (t == null)
            {
                return(s.Cast());
            }

            if (!s.IsSkillshot)
            {
                return(s.Cast(t) == Spell.CastStates.SuccessfullyCasted);
            }

            #region if common prediction selected
            if (ConfigMenu.SelectedPrediction.SelectedIndex == 1)
            {
                var pout = s.GetPrediction(t, minHit > 1);

                if (minHit > 1)
                {
                    if (pout.AoeTargetsHitCount >= minHit)
                    {
                        return(s.Cast(pout.CastPosition));
                    }
                    else
                    {
                        return(false);
                    }
                }

                if (pout.Hitchance >= hc)
                {
                    return(s.Cast(pout.CastPosition));
                }
                else
                {
                    return(false);
                }
            }
            #endregion

            if (minHit > 1)
            {
                return(SPredictionCastAoe(s, minHit));
            }

            if (t.HealthPercent > filterHPPercent)
            {
                return(false);
            }

            float avgt      = t.AvgMovChangeTime() + reactionIgnoreDelay;
            float movt      = t.LastMovChangeTime();
            float avgp      = t.AvgPathLenght();
            var   waypoints = t.Path.ToList().To2D();

            Prediction.Result result;

            switch (s.Type)
            {
            case SkillshotType.SkillshotLine:
                result = LinePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, t.LastAngleDiff(), s.From.To2D(), s.RangeCheckFrom.To2D());
                break;

            case SkillshotType.SkillshotCircle:
                result = CirclePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, t.LastAngleDiff(), s.From.To2D(), s.RangeCheckFrom.To2D());
                break;

            case SkillshotType.SkillshotCone:
                result = ConePrediction.GetPrediction(t, s.Width, s.Delay, s.Speed, s.Range, s.Collision, waypoints, avgt, movt, avgp, t.LastAngleDiff(), s.From.To2D(), s.RangeCheckFrom.To2D());
                break;

            default:
                throw new InvalidOperationException("Unknown spell type");
            }

            Drawings.s_DrawTick      = Utils.TickCount;
            Drawings.s_DrawPos       = result.CastPosition;
            Drawings.s_DrawHitChance = result.HitChance.ToString();
            Drawings.s_DrawDirection = (result.CastPosition - s.From.To2D()).Normalized().Perpendicular();
            Drawings.s_DrawWidth     = (int)s.Width;

            if (result.HitChance >= hc)
            {
                s.Cast(result.CastPosition);
                return(true);
            }

            return(false);
        }
Ejemplo n.º 4
0
        /// <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>
        public static Prediction.Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed,
                                                      float range, bool collisionable, List <Vector2> path, float avgt, float movt, float avgp, float anglediff,
                                                      Vector2 from, Vector2 rangeCheckFrom, bool arconly = true)
        {
            Prediction.AssertInitializationMode();

            if (arconly)
            {
                if (target.LSDistance(from) < width || target.LSDistance(from) > range * 0.75f)
                {
                    return(CirclePrediction.GetPrediction(target, width, delay, missileSpeed, range, collisionable, path,
                                                          avgt, movt, avgp, anglediff, from, rangeCheckFrom));
                }

                var pred = LinePrediction.GetPrediction(target, 80f, delay, missileSpeed, range, collisionable, path,
                                                        avgt, movt, avgp, anglediff, from, rangeCheckFrom);
                if (pred.HitChance >= HitChance.Low)
                {
                    pred.CastPosition = @from + (pred.CastPosition - @from).Normalized() * range
                                        /*.RotateAroundPoint(from, (1 - pred.UnitPosition.LSDistance(ObjectManager.Player.ServerPosition.To2D()) / 820f) * (float)Math.PI / 2f)*/;
                    var cos = (float)Math.Cos((1 - pred.UnitPosition.LSDistance(from) / 820f) * Math.PI / 2);
                    var sin = (float)Math.Sin((1 - pred.UnitPosition.LSDistance(from) / 820f) * Math.PI / 2);
                    var x   = cos * (pred.CastPosition.X - from.X) - sin * (pred.CastPosition.Y - from.Y) + from.X;
                    var y   = sin * (pred.CastPosition.X - from.X) + cos * (pred.CastPosition.Y - from.Y) + from.Y;
                    pred.CastPosition = new Vector2(x, y);
                }

                return(pred);
            }
            var result = new Prediction.Result();

            if (path.Count <= 1) //if target is not moving, easy to hit
            {
                result.HitChance    = HitChance.Immobile;
                result.CastPosition = target.ServerPosition.To2D();
                result.UnitPosition = result.CastPosition;
                return(result);
            }

            if (target is AIHeroClient && ((AIHeroClient)target).IsChannelingImportantSpell())
            {
                result.HitChance    = HitChance.Immobile;
                result.CastPosition = target.ServerPosition.To2D();
                result.UnitPosition = result.CastPosition;
                return(result);
            }

            if (Utility.IsImmobileTarget(target))
            {
                return(Prediction.GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable,
                                                        SkillshotType.SkillshotCircle, @from, rangeCheckFrom));
            }

            if (target.IsDashing())
            {
                return(Prediction.GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable,
                                                       SkillshotType.SkillshotCircle, @from, rangeCheckFrom));
            }

            var targetDistance = rangeCheckFrom.LSDistance(target.ServerPosition);
            var flyTime        = 0f;

            if (missileSpeed != 0)
            {
                var Vt = (path[path.Count - 1] - path[0]).Normalized() * target.MoveSpeed;
                var Vs = (target.ServerPosition.To2D() - rangeCheckFrom).Normalized() * missileSpeed;
                var Vr = Vs - Vt;

                flyTime = targetDistance / Vr.Length();

                if (path.Count > 5)
                {
                    flyTime = targetDistance / missileSpeed;
                }
            }

            var t = flyTime + delay + Game.Ping / 2000f + ConfigMenu.SpellDelay / 1000f;

            result.HitChance = Prediction.GetHitChance(t * 1000f, avgt, movt, avgp, anglediff);

            #region arc collision test

            if (result.HitChance > HitChance.Low)
            {
                for (var i = 1; i < path.Count; i++)
                {
                    var senderPos = rangeCheckFrom;
                    var testPos   = path[i];

                    var multp = testPos.LSDistance(senderPos) / 875.0f;

                    var dianaArc = new Geometry.Polygon(
                        ClipperWrapper.DefineArc(senderPos - new Vector2(875 / 2f, 20), testPos, (float)Math.PI * multp,
                                                 410, 200 * multp),
                        ClipperWrapper.DefineArc(senderPos - new Vector2(875 / 2f, 20), testPos, (float)Math.PI * multp,
                                                 410, 320 * multp));

                    if (!dianaArc.IsOutside(target.ServerPosition.To2D()))
                    {
                        result.HitChance    = HitChance.VeryHigh;
                        result.CastPosition = testPos;
                        result.UnitPosition = testPos;
                        return(result);
                    }
                }
            }

            #endregion

            return(CirclePrediction.GetPrediction(target, width, delay, missileSpeed, range, collisionable, path, avgt,
                                                  movt, avgp, anglediff, @from, rangeCheckFrom));
        }