/// <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, Vector2 from, Vector2 rangeCheckFrom) { Prediction.AssertInitializationMode(); Prediction.Result result = Prediction.GetPrediction(target, width, delay, missileSpeed, range, collisionable, SkillshotType.SkillshotCircle, path, avgt, movt, avgp, from, rangeCheckFrom); if (result.HitChance >= HitChance.Low && result.HitChance < HitChance.VeryHigh) { if (result.CastPosition.Distance(from) < 875.0f) { Vector2 direction = (result.CastPosition - from).Normalized(); result.CastPosition = from + direction * (875f + width / 2f); var targetHitBox = ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(target, delay, missileSpeed, from), target.BoundingRadius); float multp = (result.CastPosition.Distance(from) / 875.0f); var arcHitBox = new SPrediction.Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), result.CastPosition, (float)Math.PI * multp, 410, 200 * multp), ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), result.CastPosition, (float)Math.PI * multp, 410, 320 * multp)); if (ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(targetHitBox), ClipperWrapper.MakePaths(arcHitBox))) { result.HitChance = (HitChance)(result.HitChance + 1); } } } return(result); }
/// <summary> /// Gets Prediction result while unit is dashing /// </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 GetDashingPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from) { Result result = new Result(); if (target.IsDashing()) { var dashInfo = target.GetDashInfo(); if (dashInfo.IsBlink) { result.HitChance = HitChance.Impossible; return(result); } //define hitboxes var dashHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(dashInfo.StartPos, dashInfo.EndPos + (dashInfo.EndPos - dashInfo.StartPos).Normalized() * 500, target.BoundingRadius * 2)); var myHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(from, from == ObjectManager.Player.ServerPosition.To2D() ? ObjectManager.Player.BoundingRadius : width)); if (ClipperWrapper.IsIntersects(myHitBox, dashHitBox)) { result.HitChance = HitChance.Dashing; 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.HitChance = HitChance.Collision; } return(result); } result.CastPosition = GetFastUnitPosition(target, dashInfo.Path, delay, missileSpeed, from, dashInfo.Speed); result.HitChance = HitChance.Dashing; //check range if (result.CastPosition.Distance(from) > range) { result.HitChance = HitChance.OutOfRange; } //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } } else { result.HitChance = HitChance.Impossible; } return(result); }
/// <summary> /// Gets collided units & flags /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <returns>Collision result as <see cref="Collision.Result" /></returns> public static Result GetCollisions(Vector2 from, Vector2 to, float range, float width, float delay, float missileSpeed = 0, bool isArc = false) { var collidedUnits = new List<Obj_AI_Base>(); var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to.LSExtend(from, -width), width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float) Math.PI*(to.LSDistance(from)/ 900), 410, 200*(to.LSDistance(from)/ 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float) Math.PI*(to.LSDistance(from)/ 900), 410, 320*(to.LSDistance(from)/ 900)))); } var _colFlags = Flags.None; var collidedMinions = MinionManager.GetMinions(range + 100, MinionTypes.All, MinionTeam.NotAlly, MinionOrderTypes.None).AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius + 15)), spellHitBox)); var collidedEnemies = HeroManager.Enemies.AsParallel().Where(p =>ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); var collidedAllies = HeroManager.Allies.AsParallel() .Where( p => ClipperWrapper.IsIntersects( ClipperWrapper.MakePaths( ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); if (collidedMinions != null && collidedMinions.Count() != 0) { collidedUnits.AddRange(collidedMinions); _colFlags |= Flags.Minions; } if (collidedEnemies != null && collidedEnemies.Count() != 0) { collidedUnits.AddRange(collidedEnemies); _colFlags |= Flags.EnemyChampions; } if (collidedAllies != null && collidedAllies.Count() != 0) { collidedUnits.AddRange(collidedAllies); _colFlags |= Flags.AllyChampions; } if (CheckWallCollision(from, to)) _colFlags |= Flags.Wall; if (CheckYasuoWallCollision(from, to, width)) _colFlags |= Flags.YasuoWall; return new Result(collidedUnits, _colFlags); }
/// <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 = HeroManager.Enemies.Where( p => p.IsValidTarget() && Prediction.GetFastUnitPosition(p, delay, 0, from).Distance(rangeCheckFrom) < range); foreach (var enemy in enemies) { var 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) { var multp = result.CastPosition.Distance(@from) / 875.0f; var spellHitBox = new Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), result.CastPosition, (float)Math.PI * multp, 410, 200 * multp), ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), result.CastPosition, (float)Math.PI * multp, 410, 320 * multp)); var collidedEnemies = HeroManager.Enemies.AsParallel() .Where( p => ClipperWrapper.IsIntersects( ClipperWrapper.MakePaths( ClipperWrapper.DefineCircle( Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), ClipperWrapper.MakePaths(spellHitBox))); var collisionCount = collidedEnemies.Count(); if (collisionCount > result.HitCount) { result = prediction.ToAoeResult(collisionCount, new Collision.Result(collidedEnemies.ToList <Obj_AI_Base>(), Collision.Flags.EnemyChampions)); } } } return(result); }
/// <summary> /// Checks enemy hero collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="isArc">Checks collision for arc spell</param> /// <returns>true if collision found</returns> public static bool CheckAllyHeroCollision(Vector2 from, Vector2 to, float width, float delay, float missileSpeed = 0, bool isArc = false) { var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to, width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float) Math.PI*(to.LSDistance(from)/ 900), 410, 200*(to.LSDistance(from)/ 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float) Math.PI*(to.LSDistance(from)/ 900), 410, 320*(to.LSDistance(from)/ 900)))); } return HeroManager.Allies.AsParallel() .Any( p => ClipperWrapper.IsIntersects( ClipperWrapper.MakePaths( ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); }
/// <summary> /// Checks minion collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="isArc">Checks collision for arc spell</param> /// <returns>true if collision found</returns> public static bool CheckMinionCollision(Vector2 from, Vector2 to, float width, float delay, float missileSpeed = 0, bool isArc = false) { var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to, width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), to, (float)Math.PI * (to.Distance(from) / 875f), 410, 200 * (to.Distance(from) / 875f)), ClipperWrapper.DefineArc(from - new Vector2(875 / 2f, 20), to, (float)Math.PI * (to.Distance(from) / 875f), 410, 320 * (to.Distance(from) / 875f)))); } return (MinionManager.GetMinions(from.Distance(to) + 250, MinionTypes.All, MinionTeam.NotAlly, MinionOrderTypes.None) .AsParallel() .Any( p => ClipperWrapper.IsIntersects( ClipperWrapper.MakePaths( ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius * 2f + 10f)), spellHitBox))); }
/// <summary> /// Checks hero collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Width</param> /// <param name="checkAlly">Check ally heroes</param> /// <returns>true if collision found</returns> public bool CheckHeroCollision(Vector2 from, Vector2 to, Spell s, bool checkAlly = false) { Geometry.Polygon poly = ClipperWrapper.DefineRectangle(from, to, s.Width); List <Obj_AI_Hero> listToCheck = checkAlly ? HeroManager.AllHeroes : HeroManager.Enemies; return(listToCheck.AsParallel().Any(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(poly), ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(p.ServerPosition.To2D(), p.BoundingRadius))))); }
/// <summary> /// Checks minion collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Width</param> /// <returns>true if collision found</returns> public bool CheckMinionCollision(Vector2 from, Vector2 to, Spell s) { Geometry.Polygon poly = ClipperWrapper.DefineRectangle(from, to, s.Width); HitChance hc; return(MinionManager.GetMinions(from.Distance(to) + 100, MinionTypes.All, MinionTeam.NotAlly, MinionOrderTypes.None).AsParallel().Any(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetPrediction(p, s, p.GetWaypoints(), 0, 0, 0, out hc, p.ServerPosition), p.BoundingRadius)), ClipperWrapper.MakePaths(poly)))); }
/// <summary> /// Gets collided units & flags /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="range"></param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="isArc"></param> /// <returns>Collision result as <see cref="CollisionResult"/></returns> public static CollisionResult GetCollisions(Vector2 from, Vector2 to, float range, float width, float delay, float missileSpeed = 0, bool isArc = false) { var collidedUnits = new List <AIBaseClient>(); var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to.Extend(from, -width), width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.Distance(from) / 900), 410, 200 * (to.Distance(from) / 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.Distance(from) / 900), 410, 320 * (to.Distance(from) / 900)))); } var _colFlags = CollisionFlags.None; var collidedMinions = GameObjects.GetMinions(range + 100).AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(PredictionExtensions.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius + 15)), spellHitBox)).ToList(); var collidedJungles = GameObjects.GetJungles(range + 100).AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(PredictionExtensions.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius + 15)), spellHitBox)).ToList(); var collidedEnemies = GameObjects.EnemyHeroes.AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(PredictionExtensions.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)).ToList(); var collidedAllies = GameObjects.AllyHeroes.AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(PredictionExtensions.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)).ToList(); if (collidedMinions.Count != 0) { collidedUnits.AddRange(collidedMinions); _colFlags |= CollisionFlags.Minions; } if (collidedJungles.Count != 0) { collidedUnits.AddRange(collidedJungles); _colFlags |= CollisionFlags.Minions; } if (collidedEnemies.Count != 0) { collidedUnits.AddRange(collidedEnemies); _colFlags |= CollisionFlags.EnemyChampions; } if (collidedAllies.Count != 0) { collidedUnits.AddRange(collidedAllies); _colFlags |= CollisionFlags.AllyChampions; } if (CheckWallCollision(from, to)) { _colFlags |= CollisionFlags.Wall; } if (CheckYasuoWallCollision(from, to, width)) { _colFlags |= CollisionFlags.YasuoWall; } return(new CollisionResult(collidedUnits, _colFlags)); }