Example #1
0
        public static bool InSkillShot(this Vector2 position, Spell spell, float radius, bool predictCollision = true)
        {
            if (spell.SpellType == SpellType.Line)
            {
                var spellPos    = spell.CurrentSpellPosition;
                var spellEndPos = predictCollision ? spell.GetSpellEndPosition() : spell.EndPos;

                var projection = position.ProjectOn(spellPos, spellEndPos);
                return(projection.IsOnSegment && projection.SegmentPoint.Distance(position) <= spell.Radius + radius);
            }

            if (spell.SpellType == SpellType.Circular)
            {
                if (spell.Info.SpellName == "VeigarEventHorizon")
                {
                    return(position.Distance(spell.EndPos) <= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius &&
                           position.Distance(spell.EndPos) >= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius - 125);
                }
                if (spell.Info.SpellName == "DariusCleave")
                {
                    return(position.Distance(spell.EndPos) <= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius &&
                           position.Distance(spell.EndPos) >= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius - 220);
                }

                return(position.Distance(spell.EndPos) <= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius);
            }

            if (spell.SpellType == SpellType.Arc)
            {
                if (position.IsLeftOfLineSegment(spell.StartPos, spell.EndPos))
                {
                    return(false);
                }

                var spellRange = spell.StartPos.Distance(spell.EndPos);
                var midPoint   = spell.StartPos + spell.Direction * (spellRange / 2);

                return(position.Distance(midPoint) <= spell.Radius + radius - ObjectCache.MyHeroCache.BoundingRadius);
            }

            if (spell.SpellType == SpellType.Cone)
            {
                return(!position.IsLeftOfLineSegment(spell.CnStart, spell.CnLeft) && !position.IsLeftOfLineSegment(spell.CnLeft, spell.CnRight) &&
                       !position.IsLeftOfLineSegment(spell.CnRight, spell.CnStart));
            }

            return(false);
        }
Example #2
0
        public static float GetClosestDistanceApproach(Spell spell, Vector2 pos, float speed, float delay, Vector2 heroPos, float extraDist)
        {
            var walkDir = (pos - heroPos).Normalized();

            switch (spell.SpellType)
            {
            case SpellType.Line when spell.Info.ProjectileSpeed != float.MaxValue:
            {
                var spellPos    = spell.GetCurrentSpellPosition(true, delay);
                var spellEndPos = spell.GetSpellEndPosition();
                var extendedPos = pos.ExtendDir(walkDir, ObjectCache.MyHeroCache.BoundingRadius + speed * delay / 1000);

                var cpa2 = MathUtils.GetCollisionDistanceEx(heroPos,
                                                            walkDir * speed,
                                                            ObjectCache.MyHeroCache.BoundingRadius,
                                                            spellPos,
                                                            spell.Direction * spell.Info.ProjectileSpeed,
                                                            spell.Radius + extraDist,
                                                            out var cHeroPos,
                                                            out var cSpellPos);

                var cHeroPosProjection  = cHeroPos.ProjectOn(heroPos, extendedPos);
                var cSpellPosProjection = cSpellPos.ProjectOn(spellPos, spellEndPos);

                if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment && cpa2 != float.MaxValue)
                {
                    return(0);
                }

                var cpa = MathUtilsCpa.CPAPointsEx(heroPos, walkDir * speed, spellPos, spell.Direction * spell.Info.ProjectileSpeed, pos, spellEndPos, out cHeroPos, out cSpellPos);

                cHeroPosProjection  = cHeroPos.ProjectOn(heroPos, extendedPos);
                cSpellPosProjection = cSpellPos.ProjectOn(spellPos, spellEndPos);

                var checkDist = ObjectCache.MyHeroCache.BoundingRadius + spell.Radius + extraDist;

                if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment)
                {
                    return(Math.Max(0, cpa - checkDist));
                }

                return(checkDist);

                //return MathUtils.ClosestTimeOfApproach(heroPos, walkDir * speed, spellPos, spell.Orientation * spell.info.projectileSpeed);
            }

            case SpellType.Line when spell.Info.ProjectileSpeed == float.MaxValue:
            {
                var spellHitTime   = Math.Max(0, spell.EndTime - Environment.TickCount - delay);   //extraDelay
                var walkRange      = heroPos.Distance(pos);
                var predictedRange = speed * (spellHitTime / 1000);
                var tHeroPos       = heroPos + walkDir * Math.Min(predictedRange, walkRange); //Hero predicted pos

                var projection = tHeroPos.ProjectOn(spell.StartPos, spell.EndPos);

                return(Math.Max(0, tHeroPos.Distance(projection.SegmentPoint) - (spell.Radius + ObjectCache.MyHeroCache.BoundingRadius + extraDist)));    //+ dodgeBuffer
            }

            case SpellType.Circular:
            {
                var spellHitTime   = Math.Max(0, spell.EndTime - Environment.TickCount - delay);   //extraDelay
                var walkRange      = heroPos.Distance(pos);
                var predictedRange = speed * (spellHitTime / 1000);
                var tHeroPos       = heroPos + walkDir * Math.Min(predictedRange, walkRange); //Hero predicted pos

                switch (spell.Info.SpellName)
                {
                case "VeigarEventHorizon":
                {
                    const int wallRadius = 65;
                    var       midRadius  = spell.Radius - wallRadius;

                    if (spellHitTime == 0)
                    {
                        return(0);
                    }

                    return(tHeroPos.Distance(spell.EndPos) >= spell.Radius
                                       ? Math.Max(0, tHeroPos.Distance(spell.EndPos) - midRadius - wallRadius)
                                       : Math.Max(0, midRadius - tHeroPos.Distance(spell.EndPos) - wallRadius));
                }

                case "DariusCleave":
                {
                    const int wallRadius = 115;
                    var       midRadius  = spell.Radius - wallRadius;

                    if (spellHitTime == 0)
                    {
                        return(0);
                    }

                    return(tHeroPos.Distance(spell.EndPos) >= spell.Radius
                                       ? Math.Max(0, tHeroPos.Distance(spell.EndPos) - midRadius - wallRadius)
                                       : Math.Max(0, midRadius - tHeroPos.Distance(spell.EndPos) - wallRadius));
                }
                }

                var closestDist = Math.Max(0, tHeroPos.Distance(spell.EndPos) - (spell.Radius + extraDist));
                if (spell.Info.ExtraEndTime > 0 && closestDist != 0)
                {
                    var remainingTime   = Math.Max(0, spell.EndTime + spell.Info.ExtraEndTime - Environment.TickCount - delay);
                    var predictedRange2 = speed * (remainingTime / 1000);
                    var tHeroPos2       = heroPos + walkDir * Math.Min(predictedRange2, walkRange);

                    if (CheckMoveToDirection(tHeroPos, tHeroPos2))
                    {
                        return(0);
                    }
                }
                else
                {
                    return(closestDist);
                }
                break;
            }

            case SpellType.Arc:
            {
                var spellPos    = spell.GetCurrentSpellPosition(true, delay);
                var spellEndPos = spell.GetSpellEndPosition();

                var pDir = spell.Direction.Perpendicular();
                spellPos    = spellPos - pDir * spell.Radius / 2;
                spellEndPos = spellEndPos - pDir * spell.Radius / 2;

                var extendedPos = pos.ExtendDir(walkDir, ObjectCache.MyHeroCache.BoundingRadius);

                var cpa = MathUtilsCpa.CPAPointsEx(heroPos, walkDir * speed, spellPos, spell.Direction * spell.Info.ProjectileSpeed, pos, spellEndPos, out var cHeroPos, out var cSpellPos);

                var cHeroPosProjection  = cHeroPos.ProjectOn(heroPos, extendedPos);
                var cSpellPosProjection = cSpellPos.ProjectOn(spellPos, spellEndPos);

                var checkDist = spell.Radius + extraDist;

                if (cHeroPos.InSkillShot(spell, ObjectCache.MyHeroCache.BoundingRadius))
                {
                    if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment)
                    {
                        return(Math.Max(0, cpa - checkDist));
                    }
                    return(checkDist);
                }
                break;
            }

            case SpellType.Cone:
            {
                var spellHitTime   = Math.Max(0, spell.EndTime - Environment.TickCount - delay);   //extraDelay
                var walkRange      = heroPos.Distance(pos);
                var predictedRange = speed * (spellHitTime / 1000);
                var tHeroPos       = heroPos + walkDir * Math.Min(predictedRange, walkRange); //Hero predicted pos

                var sides = new[]
                {
                    heroPos.ProjectOn(spell.CnStart, spell.CnLeft).SegmentPoint,
                    heroPos.ProjectOn(spell.CnLeft, spell.CnRight).SegmentPoint,
                    heroPos.ProjectOn(spell.CnRight, spell.CnStart).SegmentPoint
                };

                var p = sides.OrderBy(x => x.Distance(x)).First();

                return(Math.Max(0, tHeroPos.Distance(p) - (spell.Radius + ObjectCache.MyHeroCache.BoundingRadius + extraDist)));
            }
            }

            return(1);
        }