public static bool AnalyzeQ(PredictionInput input, PredictionOutput output) { var posList = new List<Vector3> { ObjectManager.Player.ServerPosition, output.CastPosition }; var collision = Collision.GetCollision(posList, input); var minions = collision.Count(collisionObj => collisionObj.IsMinion); return minions > 1; }
/// <summary> /// The get updated prediction. /// </summary> /// <param name="input"> /// The input. /// </param> /// <returns> /// The <see cref="PredictionOutput" />. /// </returns> internal static PredictionOutput GetUpdatedPrediction(PredictionInput input) { if (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon) { input.Speed = 90000; } var toTarget = Vector3.Normalize(input.Unit.ServerPosition - input.From); var targetVelocity = CalculateVelocity( input.Unit.ServerPosition, input.Unit.Path.LastOrDefault(), input.Unit.MoveSpeed); var a = Vector3.Dot(targetVelocity, targetVelocity) - (input.Speed * input.Speed); var b = 2 * Vector3.Dot(targetVelocity, toTarget); var c = Vector3.Dot(toTarget, toTarget); var p = -b / (2 * a); var q = (float)Math.Sqrt((b * b) - 4 * a * c) / (2 * a); var theorem1 = p - q; var theorem2 = p + q; var t = (theorem1 > theorem2 && theorem2 > 0) ? theorem2 : theorem1; var result = new PredictionOutput() { CastPosition = input.Unit.ServerPosition + targetVelocity * (t + input.Delay), UnitPosition = input.Unit.ServerPosition, Hitchance = HitChance.VeryHigh }; // Check if the unit position is in range if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon) { if (result.Hitchance >= HitChance.High && input.RangeCheckFrom.Distance(input.Unit.Position, true) > Math.Pow(input.Range + input.Radius * 3 / 4, 2)) { result.Hitchance = HitChance.Medium; } if (input.RangeCheckFrom.Distance(result.UnitPosition, true) > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.Radius : 0), 2)) { result.Hitchance = HitChance.OutOfRange; } } // Check for collision if (input.Collision) { var positions = new List<Vector3> { result.UnitPosition, result.CastPosition, input.Unit.Position }; var originalUnit = input.Unit; result.CollisionObjects = Collision.GetCollision(positions, input); result.CollisionObjects.RemoveAll(x => x.NetworkId == originalUnit.NetworkId); result.Hitchance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.Hitchance; } return result; }
static void Game_OnGameLoad(EventArgs args) { if(ObjectManager.Player.ChampionName != "Blitzcrank") return; config = new Menu("AutoGrab", "grab", true); Menu menuTS = new Menu("Selector: ", "targ"); SimpleTs.AddToMenu(menuTS); config.AddSubMenu(menuTS); config.AddItem(new MenuItem("grabem", "Pull While AA'ing")).SetValue(new KeyBind(32, KeyBindType.Press)); config.AddToMainMenu(); p = new PredictionInput {Delay = .25f, Radius = 35, Speed = 1800}; Game.OnGameProcessPacket += Game_OnGameProcessPacket; }
static bool CollisionCheckerino(Obj_AI_Hero source, Obj_AI_Hero target, float width) { var input = new PredictionInput { Radius = width, Unit = source, }; input.CollisionObjects[0] = CollisionableObjects.Heroes; input.CollisionObjects[1] = CollisionableObjects.YasuoWall; return !Collision.GetCollision(new List<Vector3> { target.ServerPosition }, input).Where(x => x.NetworkId != x.NetworkId).Any(); }
internal static List<Obj_AI_Base> getCollisionMinions(Obj_AI_Hero source, SharpDX.Vector3 targetPos, float predDelay, float predWidth, float predSpeed) { var input = new PredictionInput { Unit = source, Radius = predWidth, Delay = predDelay, Speed = predSpeed, }; input.CollisionObjects[0] = CollisionableObjects.Minions; return Collision.GetCollision(new List<SharpDX.Vector3> { targetPos }, input).OrderBy(obj => obj.Distance(source, false)).ToList(); }
/// <summary> /// Gets the list of minions currently between the source and target /// </summary> /// <param name="source"> /// The Source /// </param> /// <param name="targetPosition"> /// The Target Position /// </param> /// <returns> /// The <see cref="List" />. /// </returns> public static List<Obj_AI_Base> GetCollisionMinions(AIHeroClient source, Vector3 targetPosition) { var input = new PredictionInput { Unit = source, Radius = SpellManager.Spell[SpellSlot.Q].Width, Delay = SpellManager.Spell[SpellSlot.Q].Delay, Speed = SpellManager.Spell[SpellSlot.Q].Speed, CollisionObjects = new[] { CollisionableObjects.Minions } }; return Collision.GetCollision(new List<Vector3> { targetPosition }, input) .OrderBy(x => x.Distance(source)) .ToList(); }
public static IEnumerable<Obj_AI_Base> QGetCollisionMinions(Vector3 source, Vector3 targetposition, float width, float range, CollisionableObjects[] collisionObjects) { PredictionInput input = new PredictionInput {From = source, Radius = width, Range = range}; if (collisionObjects.Length > 0) { for (int i = 0; collisionObjects.Length != 0; i ++) { input.CollisionObjects[i] = collisionObjects[i]; } } else { input.CollisionObjects[0] = CollisionableObjects.Minions; } return Collision.GetCollision(new List<Vector3> {targetposition}, input).OrderBy(obj => obj.Distance(source)).ToList(); }
internal static List<PossibleTarget> GetPossibleTargets(PredictionInput input) { var result = new List<PossibleTarget>(); var originalUnit = input.Unit; foreach (var enemy in HeroManager.Enemies.FindAll( h => h.NetworkId != originalUnit.NetworkId && h.IsValidTarget((input.Range + 200 + input.RealRadius), true, input.RangeCheckFrom))) { input.Unit = enemy; var prediction = Prediction.GetPrediction(input, false, false); if (prediction.Hitchance >= HitChance.High) { result.Add(new PossibleTarget { Position = prediction.UnitPosition.To2D(), Unit = enemy }); } } return result; }
internal static PredictionOutput GetPositionOnPath(PredictionInput input, List<Vector2> path, float speed = -1) { speed = (Math.Abs(speed - (-1)) < float.Epsilon) ? input.Unit.MoveSpeed : speed; if (path.Count <= 1) { return new PredictionOutput { Input = input, UnitPosition = input.Unit.ServerPosition, CastPosition = input.Unit.ServerPosition, Hitchance = HitChance.VeryHigh }; } var pLength = path.PathLength(); //Skillshots with only a delay if (pLength >= input.Delay * speed - input.RealRadius && Math.Abs(input.Speed - float.MaxValue) < float.Epsilon) { var tDistance = input.Delay * speed - input.RealRadius; for (var i = 0; i < path.Count - 1; i++) { var a = path[i]; var b = path[i + 1]; var d = a.Distance(b); if (d >= tDistance) { var direction = (b - a).Normalized(); var cp = a + direction * tDistance; var p = a + direction * ((i == path.Count - 2) ? Math.Min(tDistance + input.RealRadius, d) : (tDistance + input.RealRadius)); return new PredictionOutput { Input = input, CastPosition = cp.To3D(), UnitPosition = p.To3D(), Hitchance = HitChance.High }; } tDistance -= d; } } //Skillshot with a delay and speed. if (pLength >= input.Delay * speed - input.RealRadius && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon) { var d = input.Delay * speed - input.RealRadius; if (input.Type == SkillshotType.SkillshotLine || input.Type == SkillshotType.SkillshotCone) { if (input.From.Distance(input.Unit.ServerPosition, true) < 200 * 200) { d = input.Delay * speed; } } path = path.CutPath(d); var tT = 0f; for (var i = 0; i < path.Count - 1; i++) { var a = path[i]; var b = path[i + 1]; var tB = a.Distance(b) / speed; var direction = (b - a).Normalized(); a = a - speed * tT * direction; var sol = Geometry.VectorMovementCollision(a, b, speed, input.From.To2D(), input.Speed, tT); var t = (float)sol[0]; var pos = (Vector2)sol[1]; if (pos.IsValid() && t >= tT && t <= tT + tB) { if (pos.Distance(b, true) < 20) break; var p = pos + input.RealRadius * direction; if (input.Type == SkillshotType.SkillshotLine && false) { var alpha = (input.From.To2D() - p).AngleBetween(a - b); if (alpha > 30 && alpha < 180 - 30) { var beta = (float)Math.Asin(input.RealRadius / p.Distance(input.From)); var cp1 = input.From.To2D() + (p - input.From.To2D()).Rotated(beta); var cp2 = input.From.To2D() + (p - input.From.To2D()).Rotated(-beta); pos = cp1.Distance(pos, true) < cp2.Distance(pos, true) ? cp1 : cp2; } } return new PredictionOutput { Input = input, CastPosition = pos.To3D(), UnitPosition = p.To3D(), Hitchance = HitChance.High }; } tT += tB; } } var position = path.Last(); return new PredictionOutput { Input = input, CastPosition = position.To3D(), UnitPosition = position.To3D(), Hitchance = HitChance.Medium }; }
internal static PredictionOutput GetImmobilePrediction(PredictionInput input, double remainingImmobileT) { var timeToReachTargetPosition = input.Delay + input.Unit.Distance(input.From) / input.Speed; if (timeToReachTargetPosition <= remainingImmobileT + input.RealRadius / input.Unit.MoveSpeed) { return new PredictionOutput { CastPosition = input.Unit.ServerPosition, UnitPosition = input.Unit.Position, Hitchance = HitChance.Immobile }; } return new PredictionOutput { Input = input, CastPosition = input.Unit.ServerPosition, UnitPosition = input.Unit.ServerPosition, Hitchance = HitChance.High /*timeToReachTargetPosition - remainingImmobileT + input.RealRadius / input.Unit.MoveSpeed < 0.4d ? HitChance.High : HitChance.Medium*/ }; }
internal static PredictionOutput WayPointAnalysis(PredictionOutput result, PredictionInput input) { if (!input.Unit.IsValid<Obj_AI_Hero>() || input.Radius == 1) { result.Hitchance = HitChance.VeryHigh; return result; } //Program.debug("PRED: FOR CHAMPION " + input.Unit.BaseSkinName); // CAN'T MOVE SPELLS /////////////////////////////////////////////////////////////////////////////////// if (UnitTracker.GetSpecialSpellEndTime(input.Unit) > 0 || input.Unit.HasBuff("Recall")) { result.Hitchance = HitChance.VeryHigh; return result; } // PREPARE MATH /////////////////////////////////////////////////////////////////////////////////// result.Hitchance = HitChance.Medium; var lastWaypiont = input.Unit.GetWaypoints().Last().To3D(); var distanceUnitToWaypoint = lastWaypiont.Distance(input.Unit.ServerPosition); var distanceFromToUnit = input.From.Distance(input.Unit.ServerPosition); var distanceFromToWaypoint = lastWaypiont.Distance(input.From); float speedDelay = distanceFromToUnit / input.Speed; if (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon) speedDelay = 0; else speedDelay = distanceFromToUnit / input.Speed; float totalDelay = speedDelay + input.Delay; float moveArea = input.Unit.MoveSpeed * totalDelay; float fixRange = moveArea * 0.5f; double angleMove = 30 + (input.Radius / 13) - (totalDelay * 2); float backToFront = moveArea * 1.5f; float pathMinLen = 1000f; if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1d) { pathMinLen = 700f + backToFront; result.Hitchance = HitChance.High; } if (input.Type == SkillshotType.SkillshotCircle) { fixRange -= input.Radius / 2; } // SPAM CLICK /////////////////////////////////////////////////////////////////////////////////// if (UnitTracker.PathCalc(input.Unit)) { if (distanceFromToUnit < input.Range - fixRange) { result.Hitchance = HitChance.VeryHigh; return result; } result.Hitchance = HitChance.High; return result; } // NEW VISABLE /////////////////////////////////////////////////////////////////////////////////// if (UnitTracker.GetLastVisableTime(input.Unit) < 0.08d) { result.Hitchance = HitChance.Medium; return result; } // SPECIAL CASES /////////////////////////////////////////////////////////////////////////////////// if (distanceFromToUnit < 300 || distanceFromToWaypoint < 200) { result.Hitchance = HitChance.VeryHigh; return result; } // LONG CLICK DETECTION /////////////////////////////////////////////////////////////////////////////////// if (distanceUnitToWaypoint > pathMinLen) { result.Hitchance = HitChance.VeryHigh; return result; } // RUN IN LANE DETECTION /////////////////////////////////////////////////////////////////////////////////// if (distanceFromToWaypoint > distanceFromToUnit + fixRange && GetAngle(input.From, input.Unit) < angleMove) { result.Hitchance = HitChance.VeryHigh; return result; } // FIX RANGE /////////////////////////////////////////////////////////////////////////////////// if (distanceFromToWaypoint <= input.Unit.Distance(input.From) && distanceFromToUnit > input.Range - fixRange) { //debug("PRED: FIX RANGE"); result.Hitchance = HitChance.Medium; return result; } // AUTO ATTACK LOGIC /////////////////////////////////////////////////////////////////////////////////// if (UnitTracker.GetLastAutoAttackTime(input.Unit) < 0.1d) { if (input.Type == SkillshotType.SkillshotLine && totalDelay < 0.6 + (input.Radius * 0.001)) result.Hitchance = HitChance.VeryHigh; else if (input.Type == SkillshotType.SkillshotCircle && totalDelay < 0.7 + (input.Radius * 0.001)) result.Hitchance = HitChance.VeryHigh; else result.Hitchance = HitChance.High; return result; } // STOP LOGIC /////////////////////////////////////////////////////////////////////////////////// else { if (input.Unit.IsWindingUp) { result.Hitchance = HitChance.High; return result; } else if (input.Unit.Path.Count() == 0 && !input.Unit.IsMoving) { if (distanceFromToUnit > input.Range - fixRange) result.Hitchance = HitChance.Medium; else if (UnitTracker.GetLastStopMoveTime(input.Unit) < 0.8d) result.Hitchance = HitChance.High; else result.Hitchance = HitChance.VeryHigh; return result; } } // ANGLE HIT CHANCE /////////////////////////////////////////////////////////////////////////////////// if (input.Type == SkillshotType.SkillshotLine && input.Unit.Path.Count() > 0 && input.Unit.IsMoving) { if (GetAngle(input.From, input.Unit) < angleMove) { result.Hitchance = HitChance.VeryHigh; return result; } } // CIRCLE NEW PATH /////////////////////////////////////////////////////////////////////////////////// if (input.Type == SkillshotType.SkillshotCircle) { if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1d && distanceFromToUnit < input.Range - fixRange && distanceUnitToWaypoint > fixRange) { result.Hitchance = HitChance.VeryHigh; return result; } } //Program.debug("PRED: NO DETECTION"); return result; }
public static PredictionOutput GetPrediction(PredictionInput input) { return GetPrediction(input, true, true); }
/// <summary> /// Gets the collision minions /// </summary> /// <param name="source"> /// the source /// </param> /// <param name="targetPosition"> /// the target position /// </param> /// <returns> /// The list of minions /// </returns> private IEnumerable<Obj_AI_Base> GetCollisionMinions(Obj_AI_Base source, Vector3 targetPosition) { var input = new PredictionInput { Unit = source, Radius = this.spells[SpellSlot.Q].Width, Delay = this.spells[SpellSlot.Q].Delay, Speed = this.spells[SpellSlot.Q].Speed }; input.CollisionObjects[0] = CollisionableObjects.Minions; return Collision.GetCollision(new List<Vector3> { targetPosition }, input) .OrderBy(obj => obj.Distance(source)) .ToList(); }
private List<Obj_AI_Base> QGetCollisions(Obj_AI_Hero source, Vector3 targetposition) { try { var input = new PredictionInput { Unit = source, Radius = Q.Width, Delay = Q.Delay, Speed = Q.Speed }; input.CollisionObjects[0] = CollisionableObjects.Minions; return Collision.GetCollision(new List<Vector3> { targetposition }, input) .OrderBy(obj => obj.Distance(source)) .ToList(); } catch (Exception ex) { Global.Logger.AddItem(new LogItem(ex)); } return new List<Obj_AI_Base>(); }
internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision) { PredictionOutput result = null; if (!input.Unit.IsValidTarget(float.MaxValue, false)) { return(new PredictionOutput()); } if (ft) { //Increase the delay due to the latency and server tick: input.Delay += Game.Ping / 2000f + 0.05f; if (input.Aoe) { return(AoePrediction.GetPrediction(input)); } } //Target too far away. if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon && input.Unit.Distance(input.RangeCheckFrom, true) > Math.Pow(input.Range * 1.5, 2)) { return(new PredictionOutput { Input = input }); } //Unit is dashing. if (input.Unit.IsDashing()) { result = GetDashingPrediction(input); } else { //Unit is immobile. var remainingImmobileT = UnitIsImmobileUntil(input.Unit); if (remainingImmobileT >= 0d) { result = GetImmobilePrediction(input, remainingImmobileT); } } //Normal prediction if (result == null) { result = GetStandardPrediction(input); } //Check if the unit position is in range if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon) { if (result.Hitchance == HitChance.High && input.RangeCheckFrom.Distance(input.Unit.Position, true) > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2)) { result.Hitchance = HitChance.Medium; } if (input.RangeCheckFrom.Distance(result.UnitPosition, true) > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2)) { result.Hitchance = HitChance.OutOfRange; } if (input.RangeCheckFrom.Distance(result.CastPosition, true) > Math.Pow(input.Range, 2)) { if (result.Hitchance != HitChance.OutOfRange) { result.CastPosition = input.RangeCheckFrom + input.Range * (result.UnitPosition - input.RangeCheckFrom).To2D().Normalized().To3D(); } else { result.Hitchance = HitChance.OutOfRange; } } } //Check for collision if (checkCollision && input.Collision) { var positions = new List <Vector3> { result.UnitPosition, result.CastPosition, input.Unit.Position }; var originalUnit = input.Unit; result.CollisionObjects = Collision.GetCollision(positions, input); result.CollisionObjects.RemoveAll(x => x.NetworkId == originalUnit.NetworkId); result.Hitchance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.Hitchance; } return(result); }
public static PredictionOutput GetPrediction(PredictionInput input, int method = 0) { return(GetPrediction(input, true, true, method)); }
public static PredictionOutput GetPrediction(PredictionInput input) { var mainTargetPrediction = Prediction.GetPrediction(input, false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.To2D(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { //Add the posible targets in range: posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List<Vector2>(); foreach (var target in posibleTargets) { target.Position = target.Position - input.From.To2D(); } for (var i = 0; i < posibleTargets.Count; i++) { for (var j = 0; j < posibleTargets.Count; j++) { if (i != j) { var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f; if (!candidates.Contains(p)) { candidates.Add(p); } } } } var bestCandidateHits = -1; var bestCandidate = new Vector2(); var positionsList = posibleTargets.Select(t => t.Position).ToList(); foreach (var candidate in candidates) { var hits = GetHits(candidate, input.Range, input.Radius, positionsList); if (hits > bestCandidateHits) { bestCandidate = candidate; bestCandidateHits = hits; } } bestCandidate = bestCandidate + input.From.To2D(); if (bestCandidateHits > 1 && input.From.To2D().Distance(bestCandidate, true) > 50 * 50) { return new PredictionOutput { Hitchance = mainTargetPrediction.Hitchance, _aoeTargetsHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = bestCandidate.To3D(), Input = input }; } } return mainTargetPrediction; }
internal static PredictionOutput GetStandardPrediction(PredictionInput input) { var speed = input.Unit.MoveSpeed; if (input.Unit.Distance(input.From, true) < 200 * 200) { //input.Delay /= 2; speed /= 1.5f; } var result = GetPositionOnPath(input, input.Unit.GetWaypoints(), speed); if (result.Hitchance >= HitChance.High && input.Unit is Obj_AI_Hero) {} return result; }
internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1) { speed = (Math.Abs(speed - (-1)) < float.Epsilon) ? input.Unit.MoveSpeed : speed; if (path.Count <= 1) { return(new PredictionOutput { Input = input, UnitPosition = input.Unit.ServerPosition, CastPosition = input.Unit.ServerPosition, Hitchance = HitChance.VeryHigh }); } var pLength = path.PathLength(); //Skillshots with only a delay if (pLength >= input.Delay * speed - input.RealRadius && input.Speed == float.MaxValue) { var tDistance = input.Delay * speed - input.RealRadius; for (var i = 0; i < path.Count - 1; i++) { var a = path[i]; var b = path[i + 1]; var d = a.Distance(b); if (d >= tDistance) { var direction = (b - a).Normalized(); var cp = a + direction * tDistance; var p = a + direction * ((i == path.Count - 2) ? Math.Min(tDistance + input.RealRadius, d) : (tDistance + input.RealRadius)); return(new PredictionOutput { Input = input, CastPosition = cp.To3D(), UnitPosition = p.To3D(), Hitchance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d ? HitChance.VeryHigh : HitChance.High, }); } tDistance -= d; } } //Skillshot with a delay and speed. if (pLength >= input.Delay * speed - input.RealRadius && Math.Abs(input.Speed - float.MaxValue) > float.Epsilon) { path = path.CutPath(Math.Max(0, input.Delay * speed - input.RealRadius)); var tT = 0f; for (var i = 0; i < path.Count - 1; i++) { var a = path[i]; var b = path[i + 1]; var tB = a.Distance(b) / speed; var direction = (b - a).Normalized(); a = a - speed * tT * direction; var sol = Geometry.VectorMovementCollision(a, b, speed, input.From.To2D(), input.Speed, tT); var t = (float)sol[0]; var pos = (Vector2)sol[1]; if (pos.IsValid() && t >= tT && t <= tT + tB) { var p = pos + input.RealRadius * direction; if (input.Type == SkillshotType.SkillshotLine) { var alpha = (input.From.To2D() - p).AngleBetween(a - b); if (alpha > 30 && alpha < 180 - 30) { var beta = (float)Math.Asin(input.RealRadius / p.Distance(input.From)); var cp1 = input.From.To2D() + (p - input.From.To2D()).Rotated(beta); var cp2 = input.From.To2D() + (p - input.From.To2D()).Rotated(-beta); pos = cp1.Distance(pos, true) < cp2.Distance(pos, true) ? cp1 : cp2; } } return(new PredictionOutput { Input = input, CastPosition = pos.To3D(), UnitPosition = p.To3D(), Hitchance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d ? HitChance.VeryHigh : HitChance.High, }); } tT += tB; } } var position = path.Last(); return(new PredictionOutput { Input = input, CastPosition = position.To3D(), UnitPosition = position.To3D(), Hitchance = HitChance.Medium, }); }
internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1) { speed = (Math.Abs(speed - (-1)) < float.Epsilon) ? input.Unit.MoveSpeed : speed; if (path.Count <= 1) { return(new PredictionOutput { Input = input, UnitPosition = input.Unit.ServerPosition, CastPosition = input.Unit.ServerPosition, Hitchance = HitChance.VeryHigh }); } var pLength = path.PathLength(); //Skillshots with only a delay if (pLength >= input.Delay * speed - input.RealRadius && input.Speed == float.MaxValue) { var tDistance = input.Delay * speed - input.RealRadius; return(new PredictionOutput { Input = input, CastPosition = path.PCutPath(tDistance).Item1.To3D(), UnitPosition = path.PCutPath(tDistance + input.RealRadius).Item1.To3D(), Hitchance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d ? HitChance.VeryHigh : HitChance.High }); } //Skillshot with a delay and speed. if (pLength >= input.Delay * speed - input.RealRadius && input.Speed != float.MaxValue) { var path2 = new List <Vector2>(); path2.AddRange(path); path2[0] = path[0] + input.RealRadius * (path[0] - path[1]); var pp = CalcPositionOnPath(path, speed, input.Speed, input.From.To2D(), input.Delay, 6); var cpp = CalcPositionOnPath(path2, speed, input.Speed, input.From.To2D(), input.Delay, 6); if (cpp.Item3) { return(new PredictionOutput { Input = input, CastPosition = cpp.Item1.To3D(), UnitPosition = pp.Item1.To3D(), Hitchance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d ? HitChance.VeryHigh : HitChance.High }); } } var position = path.Last(); return(new PredictionOutput { Input = input, CastPosition = position.To3D(), UnitPosition = position.To3D(), Hitchance = HitChance.Medium }); }
internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision) { PredictionOutput result = null; if (!input.Unit.IsValidTarget(float.MaxValue, false)) { return new PredictionOutput(); } if (ft) { //Increase the delay due to the latency and server tick: input.Delay += Game.Ping / 2000f + 0.06f; if (input.Aoe) { return AoePrediction.GetPrediction(input); } } //Target too far away. if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon && input.Unit.Distance(input.RangeCheckFrom, true) > Math.Pow(input.Range * 1.5, 2)) { return new PredictionOutput { Input = input }; } //Unit is dashing. if (input.Unit.IsDashing()) { result = GetDashingPrediction(input); } else { //Unit is immobile. var remainingImmobileT = UnitIsImmobileUntil(input.Unit); if (remainingImmobileT >= 0d) { result = GetImmobilePrediction(input, remainingImmobileT); } } //Normal prediction if (result == null) { result = GetStandardPrediction(input); } //Check if the unit position is in range if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon) { if (result.Hitchance >= HitChance.High && input.RangeCheckFrom.Distance(input.Unit.Position, true) > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2)) { result.Hitchance = HitChance.Medium; } if (input.RangeCheckFrom.Distance(result.UnitPosition, true) > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2)) { result.Hitchance = HitChance.OutOfRange; } if (input.RangeCheckFrom.Distance(result.CastPosition, true) > Math.Pow(input.Range, 2)) { if (result.Hitchance != HitChance.OutOfRange) { result.CastPosition = input.RangeCheckFrom + input.Range * (result.UnitPosition - input.RangeCheckFrom).To2D().Normalized().To3D(); } else { result.Hitchance = HitChance.OutOfRange; } } } //Check for collision if (checkCollision && input.Collision) { var positions = new List<Vector3> { result.UnitPosition, result.CastPosition, input.Unit.Position }; var originalUnit = input.Unit; result.CollisionObjects = Collision.GetCollision(positions, input); result.CollisionObjects.RemoveAll(x => x.NetworkId == originalUnit.NetworkId); result.Hitchance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.Hitchance; } return result; }
public static PredictionOutput GetPrediction(PredictionInput input) { var mainTargetPrediction = Prediction.GetPrediction(input, false, true); var posibleTargets = new List <PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.To2D(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { //Add the posible targets in range: posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List <Vector2>(); foreach (var target in posibleTargets) { target.Position = target.Position - input.From.To2D(); } for (var i = 0; i < posibleTargets.Count; i++) { for (var j = 0; j < posibleTargets.Count; j++) { if (i != j) { var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f; if (!candidates.Contains(p)) { candidates.Add(p); } } } } var bestCandidateHits = -1; var bestCandidate = new Vector2(); var positionsList = posibleTargets.Select(t => t.Position).ToList(); foreach (var candidate in candidates) { var hits = GetHits(candidate, input.Range, input.Radius, positionsList); if (hits > bestCandidateHits) { bestCandidate = candidate; bestCandidateHits = hits; } } if (bestCandidateHits > 1 && input.From.To2D().Distance(bestCandidate, true) > 50 * 50) { return(new PredictionOutput { Hitchance = mainTargetPrediction.Hitchance, _aoeTargetsHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = bestCandidate.To3D(), Input = input, }); } } return(mainTargetPrediction); }
/// <summary> /// Returns the list of the units that the skillshot will hit before reaching the set positions. /// </summary> public static List<Obj_AI_Base> GetCollision(List<Vector3> positions, PredictionInput input) { var result = new List<Obj_AI_Base>(); foreach (var position in positions) { foreach (var objectType in input.CollisionObjects) { switch (objectType) { case CollisionableObjects.Minions: foreach (var minion in ObjectManager.Get<Obj_AI_Minion>() .Where( minion => minion.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom))) { input.Unit = minion; var minionPrediction = Prediction.GetPrediction(input, false, false); if ( minionPrediction.UnitPosition.To2D() .Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 15 + minion.BoundingRadius), 2)) { result.Add(minion); } } break; case CollisionableObjects.Heroes: foreach (var hero in HeroManager.Enemies.FindAll( hero => hero.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom)) ) { input.Unit = hero; var prediction = Prediction.GetPrediction(input, false, false); if ( prediction.UnitPosition.To2D() .Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 50 + hero.BoundingRadius), 2)) { result.Add(hero); } } break; case CollisionableObjects.Walls: var step = position.Distance(input.From) / 20; for (var i = 0; i < 20; i++) { var p = input.From.To2D().Extend(position.To2D(), step * i); if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall)) { result.Add(ObjectManager.Player); } } break; case CollisionableObjects.YasuoWall: if (Utils.TickCount - _wallCastT > 4000) { break; } GameObject wall = null; foreach (var gameObject in ObjectManager.Get<GameObject>() .Where( gameObject => gameObject.IsValid && Regex.IsMatch( gameObject.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase)) ) { wall = gameObject; } if (wall == null) { break; } var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = (300 + 50 * Convert.ToInt32(level)); var wallDirection = (wall.Position.To2D() - _yasuoWallCastedPos).Normalized().Perpendicular(); var wallStart = wall.Position.To2D() + wallWidth / 2f * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; if (wallStart.Intersection(wallEnd, position.To2D(), input.From.To2D()).Intersects) { var t = Utils.TickCount + (wallStart.Intersection(wallEnd, position.To2D(), input.From.To2D()) .Point.Distance(input.From) / input.Speed + input.Delay) * 1000; if (t < _wallCastT + 4000) { result.Add(ObjectManager.Player); } } break; } } } return result.Distinct().ToList(); }
public static PredictionOutput GetPrediction(PredictionInput input) { var mainTargetPrediction = Prediction.GetPrediction(input, false, true); var posibleTargets = new List <PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.To2D(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { //Add the posible targets in range: posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List <Vector2>(); foreach (var target in posibleTargets) { var targetCandidates = GetCandidates( input.From.To2D(), target.Position, (input.Radius), input.Range); candidates.AddRange(targetCandidates); } var bestCandidateHits = -1; var bestCandidate = new Vector2(); var bestCandidateHitPoints = new List <Vector2>(); var positionsList = posibleTargets.Select(t => t.Position).ToList(); foreach (var candidate in candidates) { if ( GetHits( input.From.To2D(), candidate, (input.Radius + input.Unit.BoundingRadius / 3 - 10), new List <Vector2> { posibleTargets[0].Position }).Count() == 1) { var hits = GetHits(input.From.To2D(), candidate, input.Radius, positionsList).ToList(); var hitsCount = hits.Count; if (hitsCount >= bestCandidateHits) { bestCandidateHits = hitsCount; bestCandidate = candidate; bestCandidateHitPoints = hits.ToList(); } } } if (bestCandidateHits > 1) { float maxDistance = -1; Vector2 p1 = new Vector2(), p2 = new Vector2(); //Center the position for (var i = 0; i < bestCandidateHitPoints.Count; i++) { for (var j = 0; j < bestCandidateHitPoints.Count; j++) { var startP = input.From.To2D(); var endP = bestCandidate; var proj1 = positionsList[i].ProjectOn(startP, endP); var proj2 = positionsList[j].ProjectOn(startP, endP); var dist = Vector2.DistanceSquared(bestCandidateHitPoints[i], proj1.LinePoint) + Vector2.DistanceSquared(bestCandidateHitPoints[j], proj2.LinePoint); if (dist >= maxDistance && (proj1.LinePoint - positionsList[i]).AngleBetween( proj2.LinePoint - positionsList[j]) > 90) { maxDistance = dist; p1 = positionsList[i]; p2 = positionsList[j]; } } } return(new PredictionOutput { Hitchance = mainTargetPrediction.Hitchance, _aoeTargetsHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = ((p1 + p2) * 0.5f).To3D(), Input = input, }); } } return(mainTargetPrediction); }
/// <summary> /// Returns the list of the units that the skillshot will hit before reaching the set positions. /// </summary> public static List<Obj_AI_Base> GetCollision(List<Vector3> positions, PredictionInput input) { var result = new List<Obj_AI_Base>(); foreach (var position in positions) { foreach (var objectType in input.CollisionObjects) { switch (objectType) { case CollisionableObjects.Minions: foreach (var minion in ObjectManager.Get<Obj_AI_Minion>().Where(minion => minion.IsValidTarget(Math.Min(input.Range + input.Radius + 100, 2000), true, input.From))) { input.Unit = minion; if (minion.Path.Count() > 0) { var minionPrediction = Prediction.GetPrediction(input, true, false); if (minionPrediction.CastPosition.To2D().Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 20 + minion.Path.Count() * minion.BoundingRadius), 2)) { result.Add(minion); } } else { var bonus = 30; if (minion.ServerPosition.To2D().Distance(input.From.To2D()) < input.Radius) result.Add(minion); else if (minion.ServerPosition.To2D().Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + bonus + minion.BoundingRadius), 2)) { result.Add(minion); } } } break; case CollisionableObjects.Heroes: foreach (var hero in HeroManager.Enemies.FindAll( hero => hero.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom)) ) { input.Unit = hero; var prediction = Prediction.GetPrediction(input, false, false); if ( prediction.UnitPosition.To2D() .Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 50 + hero.BoundingRadius), 2)) { result.Add(hero); } } break; case CollisionableObjects.Walls: var step = position.Distance(input.From) / 20; for (var i = 0; i < 20; i++) { var p = input.From.To2D().Extend(position.To2D(), step * i); if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall)) { result.Add(ObjectManager.Player); } } break; } } } return result.Distinct().ToList(); }
/// <summary> /// Returns the list of the units that the skillshot will hit before reaching the set positions. /// </summary> public static List <Obj_AI_Base> GetCollision(List <Vector3> positions, PredictionInput input) { var result = new List <Obj_AI_Base>(); foreach (var position in positions) { foreach (var objectType in input.CollisionObjects) { switch (objectType) { case CollisionableObjects.Minions: foreach ( var minion in ObjectManager.Get <Obj_AI_Minion>() .Where( minion => minion.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom))) { input.Unit = minion; var minionPrediction = Prediction.GetPrediction(input, false, false); if ( minionPrediction.UnitPosition.To2D() .Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 15 + minion.BoundingRadius), 2)) { result.Add(minion); } } break; case CollisionableObjects.Heroes: foreach ( var hero in ObjectManager.Get <Obj_AI_Hero>() .Where( hero => hero.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom))) { input.Unit = hero; var prediction = Prediction.GetPrediction(input, false, false); if ( prediction.UnitPosition.To2D() .Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + 50 + hero.BoundingRadius), 2)) { result.Add(hero); } } break; case CollisionableObjects.Walls: var step = position.Distance(input.From) / 20; for (var i = 0; i < 20; i++) { var p = input.From.To2D().Extend(position.To2D(), step * i); if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall)) { result.Add(ObjectManager.Player); } } break; case CollisionableObjects.YasuoWall: if (Environment.TickCount - _wallCastT > 4000) { break; } GameObject wall = null; foreach ( var gameObject in ObjectManager.Get <GameObject>() .Where( gameObject => gameObject.IsValid && System.Text.RegularExpressions.Regex.IsMatch( gameObject.Name, "_w_windwall_enemy_0.\\.troy", System.Text.RegularExpressions.RegexOptions.IgnoreCase))) { wall = gameObject; } if (wall == null) { break; } var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = (300 + 50 * Convert.ToInt32(level)); var wallDirection = (wall.Position.To2D() - _yasuoWallCastedPos).Normalized().Perpendicular(); var wallStart = wall.Position.To2D() + wallWidth / 2 * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; if (wallStart.Intersection(wallEnd, position.To2D(), input.From.To2D()).Intersects) { var t = Environment.TickCount + (wallStart.Intersection(wallEnd, position.To2D(), input.From.To2D()) .Point.Distance(input.From) / input.Speed + input.Delay) * 1000; if (t < _wallCastT + 4000) { result.Add(ObjectManager.Player); } } break; } } } return(result.Distinct().ToList()); }
internal static PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision) { PredictionOutput result = null; if (!input.Unit.IsValidTarget(float.MaxValue, false)) { return new PredictionOutput(); } if (ft) { //Increase the delay due to the latency and server tick: input.Delay += Game.Ping / 2000f + 0.07f; if (input.Aoe) { return AoePrediction.GetPrediction(input); } } //Target too far away. if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon && input.Unit.Distance(input.RangeCheckFrom, true) > Math.Pow(input.Range * 1.5, 2)) { return new PredictionOutput { Input = input }; } //Unit is dashing. if (input.Unit.IsDashing()) { result = GetDashingPrediction(input); } else { //Unit is immobile. var remainingImmobileT = UnitIsImmobileUntil(input.Unit); if (remainingImmobileT >= 0d) { result = GetImmobilePrediction(input, remainingImmobileT); } } //Normal prediction if (result == null) { result = GetStandardPrediction(input); } //Check if the unit position is in range if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon) { if (result.Hitchance >= HitChance.High && input.RangeCheckFrom.Distance(input.Unit.Position, true) > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2)) { result.Hitchance = HitChance.Medium; } if (input.RangeCheckFrom.Distance(result.UnitPosition, true) > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2)) { result.Hitchance = HitChance.OutOfRange; } /* This does not need to be handled for the updated predictions, but left as a reference.*/ if (input.RangeCheckFrom.Distance(result.CastPosition, true) > Math.Pow(input.Range, 2)) { if (result.Hitchance != HitChance.OutOfRange) { result.CastPosition = input.RangeCheckFrom + input.Range * (result.UnitPosition - input.RangeCheckFrom).To2D().Normalized().To3D(); } else { result.Hitchance = HitChance.OutOfRange; } } } //Set hit chance if (result.Hitchance == HitChance.High || result.Hitchance == HitChance.VeryHigh) { result = WayPointAnalysis(result, input); //.debug(input.Unit.BaseSkinName + result.Hitchance); } //Check for collision if (checkCollision && input.Collision && result.Hitchance > HitChance.Impossible) { var positions = new List<Vector3> { result.CastPosition, result.UnitPosition }; result.CollisionObjects = Collision.GetCollision(positions, input); result.Hitchance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.Hitchance; } return result; }
public static PredictionOutput GetPrediction(PredictionInput input) { return(GetPrediction(input, true, true)); }
internal static PredictionOutput GetDashingPrediction(PredictionInput input) { var dashData = input.Unit.GetDashInfo(); var result = new PredictionOutput { Input = input }; //Normal dashes. if (!dashData.IsBlink) { //Mid air: var endP = dashData.Path.Last(); var dashPred = GetPositionOnPath( input, new List<Vector2> { input.Unit.ServerPosition.To2D(), endP }, dashData.Speed); if (dashPred.Hitchance >= HitChance.High && dashPred.UnitPosition.To2D().Distance(input.Unit.Position.To2D(), endP, true) < 200) { dashPred.CastPosition = dashPred.UnitPosition; dashPred.Hitchance = HitChance.Dashing; return dashPred; } //At the end of the dash: if (dashData.Path.PathLength() > 200) { var timeToPoint = input.Delay / 2f + input.From.To2D().Distance(endP) / input.Speed - 0.25f; if (timeToPoint <= input.Unit.Distance(endP) / dashData.Speed + input.RealRadius / input.Unit.MoveSpeed) { return new PredictionOutput { CastPosition = endP.To3D(), UnitPosition = endP.To3D(), Hitchance = HitChance.Dashing }; } } result.CastPosition = dashData.Path.Last().To3D(); result.UnitPosition = result.CastPosition; //Figure out where the unit is going. } return result; }
public static void OnWaveClear() { // Mana check if (player.ManaPercentage() < Config.SliderLinks["waveMana"].Value.Value) return; // Check spells if (!Q.IsEnabledAndReady(Mode.WAVE) && !E.IsEnabledAndReady(Mode.WAVE)) return; // Minions around var minions = MinionManager.GetMinions(Q.Range, MinionTypes.All, MinionTeam.Enemy, MinionOrderTypes.MaxHealth); if (minions.Count == 0) return; // Q usage if (Q.IsEnabledAndReady(Mode.WAVE) && !player.IsDashing()) { int hitNumber = Config.SliderLinks["waveNumQ"].Value.Value; // Validate available minions if (minions.Count >= hitNumber) { // Get only killable minions var killable = minions.Where(m => m.Health < Q.GetDamage(m)); if (killable.Count() > 0) { // Prepare prediction input for Collision check var input = new PredictionInput() { From = Q.From, Collision = Q.Collision, Delay = Q.Delay, Radius = Q.Width, Range = Q.Range, RangeCheckFrom = Q.RangeCheckFrom, Speed = Q.Speed, Type = Q.Type, CollisionObjects = new[] { CollisionableObjects.Heroes, CollisionableObjects.Minions, CollisionableObjects.YasuoWall } }; // Helpers var currentHitNumber = 0; var castPosition = Vector3.Zero; // Validate the collision foreach (var target in killable) { // Update unit in the input input.Unit = target; // Get colliding objects var colliding = LeagueSharp.Common.Collision.GetCollision(new List<Vector3>() { player.ServerPosition.Extend(Prediction.GetPrediction(input).UnitPosition, Q.Range) }, input) .MakeUnique() .OrderBy(e => e.Distance(player, true)) .ToList(); // Validate collision if (colliding.Count >= hitNumber && !colliding.Contains(player)) { // Calculate hit number int i = 0; foreach (var collide in colliding) { // Break loop here since we can't kill the target if (Q.GetDamage(collide) < collide.Health) { if (currentHitNumber < i && i >= hitNumber) { currentHitNumber = i; castPosition = Q.GetPrediction(collide).CastPosition; } break; } // Increase hit count i++; } } } // Check if we have a valid target with enough targets being killed if (castPosition != Vector3.Zero) { if (Q.Cast(castPosition)) return; } } } } // General E usage if (E.IsEnabledAndReady(Mode.WAVE)) { int hitNumber = Config.SliderLinks["waveNumE"].Value.Value; // Get minions in E range var minionsInRange = minions.Where(m => E.IsInRange(m)); // Validate available minions if (minionsInRange.Count() >= hitNumber) { // Check if enough minions die with E int killableNum = 0; foreach (var minion in minionsInRange) { if (minion.IsRendKillable()) { // Increase kill number killableNum++; // Cast on condition met if (killableNum >= hitNumber) { if (E.Cast(true)) return; break; } } } } } }
internal static PredictionOutput GetStandardPrediction(PredictionInput input) { var speed = input.Unit.MoveSpeed; if (input.Unit.Distance(input.From, true) < 200 * 200) { //input.Delay /= 2; speed /= 1.5f; } if (input.Unit.IsValid<Obj_AI_Hero>() && UnitTracker.PathCalc(input.Unit)) { return GetPositionOnPath(input, UnitTracker.GetPathWayCalc(input.Unit), speed); } else return GetPositionOnPath(input, input.Unit.GetWaypoints(), speed); }
private Vector3 AssistedQLogic(out int hits) { try { if (Ball.IsMoving) { hits = 0; return Vector3.Zero; } var center = Vector2.Zero; float radius = -1; var count = 0; var range = (Q.Range + R.Width) * 1.5f; var input = new PredictionInput { Collision = false, From = Ball.Position, RangeCheckFrom = Ball.Position, Delay = (Q.Delay + R.Delay) - 0.1f, Range = Q.Range + R.Width / 2f, Speed = Q.Speed, Radius = R.Width, Type = R.Type }; var points = new List<Vector2>(); foreach (var enemy in GameObjects.EnemyHeroes.Where(t => t.IsValidTarget(range))) { input.Unit = enemy; var pred = Prediction.GetPrediction(input); if (pred.Hitchance >= HitChance.Low) { points.Add(pred.UnitPosition.To2D()); } } if (points.Any()) { var possibilities = ListExtensions.ProduceEnumeration(points).Where(p => p.Count > 1).ToList(); if (possibilities.Any()) { foreach (var possibility in possibilities) { var mec = MEC.GetMec(possibility); if (mec.Radius < R.Width && Player.Distance(mec.Center) < range) { if (possibility.Count > count || possibility.Count == count && mec.Radius < radius) { center = mec.Center; radius = mec.Radius; count = possibility.Count; } } } if (!center.Equals(Vector2.Zero)) { hits = count; return center.To3D(); } } var dTarget = GameObjects.EnemyHeroes.FirstOrDefault(t => t.IsValidTarget(range)); if (dTarget != null) { hits = 1; return dTarget.Position; } } } catch (Exception ex) { Global.Logger.AddItem(new LogItem(ex)); } hits = 0; return Vector3.Zero; }
public static PredictionOutput GetPrediction(PredictionInput input) { switch (input.Type) { case SkillshotType.SkillshotCircle: return Circle.GetPrediction(input); case SkillshotType.SkillshotCone: return Cone.GetPrediction(input); case SkillshotType.SkillshotLine: return Line.GetPrediction(input); } return new PredictionOutput(); }
private bool ELogic(Obj_AI_Hero mainTarget, List<Obj_AI_Base> targets, HitChance hitChance, int minHits) { try { var input = new PredictionInput { Range = ELength, Delay = E.Delay, Radius = E.Width, Speed = E.Speed, Type = E.Type }; var input2 = new PredictionInput { Range = E.Range + ELength, Delay = E.Delay, Radius = E.Width, Speed = E.Speed, Type = E.Type }; var startPos = Vector3.Zero; var endPos = Vector3.Zero; var hits = 0; targets = targets.Where(t => t.IsValidTarget(E.Range + ELength + E.Width * 1.1f)).ToList(); var targetCount = targets.Count; foreach (var target in targets) { bool containsTarget; var lTarget = target; if (target.Distance(Player.Position) <= E.Range) { containsTarget = mainTarget == null || lTarget.NetworkId == mainTarget.NetworkId; var cCastPos = target.Position; foreach (var t in targets.Where(t => t.NetworkId != lTarget.NetworkId)) { var count = 1; var cTarget = t; input.Unit = t; input.From = cCastPos; input.RangeCheckFrom = cCastPos; var pred = Prediction.GetPrediction(input); if (pred.Hitchance >= (hitChance - 1)) { count++; if (!containsTarget) { containsTarget = t.NetworkId == mainTarget.NetworkId; } var rect = new Geometry.Polygon.Rectangle( cCastPos.To2D(), cCastPos.Extend(pred.CastPosition, ELength).To2D(), E.Width); foreach (var c in targets.Where( c => c.NetworkId != cTarget.NetworkId && c.NetworkId != lTarget.NetworkId)) { input.Unit = c; var cPredPos = c.Type == GameObjectType.obj_AI_Minion ? c.Position : Prediction.GetPrediction(input).UnitPosition; if ( new Geometry.Polygon.Circle( cPredPos, (c.Type == GameObjectType.obj_AI_Minion && c.IsMoving ? (c.BoundingRadius / 2f) : (c.BoundingRadius) * 0.9f)).Points.Any(p => rect.IsInside(p))) { count++; if (!containsTarget && c.NetworkId == mainTarget.NetworkId) { containsTarget = true; } } } if (count > hits && containsTarget) { hits = count; startPos = cCastPos; endPos = cCastPos.Extend(pred.CastPosition, ELength); if (hits == targetCount) { break; } } } } if (endPos.Equals(Vector3.Zero) && containsTarget) { startPos = target.IsFacing(Player) && IsSpellUpgraded(E) ? Player.Position.Extend(cCastPos, Player.Distance(cCastPos) - (ELength / 10f)) : cCastPos; endPos = Player.Position.Extend(cCastPos, ELength); hits = 1; } } else { input2.Unit = lTarget; var castPos = Prediction.GetPrediction(input2).CastPosition; var sCastPos = Player.Position.Extend(castPos, E.Range); var extDist = ELength / 4f; var circle = new Geometry.Polygon.Circle(Player.Position, sCastPos.Distance(Player.Position), 45).Points .Where(p => p.Distance(sCastPos) < extDist).OrderBy(p => p.Distance(lTarget)); foreach (var point in circle) { input2.From = point.To3D(); input2.RangeCheckFrom = point.To3D(); input2.Range = ELength; var pred2 = Prediction.GetPrediction(input2); if (pred2.Hitchance >= hitChance) { containsTarget = mainTarget == null || lTarget.NetworkId == mainTarget.NetworkId; var count = 1; var rect = new Geometry.Polygon.Rectangle( point, point.To3D().Extend(pred2.CastPosition, ELength).To2D(), E.Width); foreach (var c in targets.Where(t => t.NetworkId != lTarget.NetworkId)) { input2.Unit = c; var cPredPos = c.Type == GameObjectType.obj_AI_Minion ? c.Position : Prediction.GetPrediction(input2).UnitPosition; if ( new Geometry.Polygon.Circle( cPredPos, (c.Type == GameObjectType.obj_AI_Minion && c.IsMoving ? (c.BoundingRadius / 2f) : (c.BoundingRadius) * 0.9f)).Points.Any(p => rect.IsInside(p))) { count++; if (!containsTarget && c.NetworkId == mainTarget.NetworkId) { containsTarget = true; } } } if (count > hits && containsTarget || count == hits && containsTarget && mainTarget != null && point.Distance(mainTarget.Position) < startPos.Distance(mainTarget.Position)) { hits = count; startPos = point.To3D(); endPos = startPos.Extend(pred2.CastPosition, ELength); if (hits == targetCount) { break; } } } } } if (hits == targetCount) { break; } } if (hits >= minHits && !startPos.Equals(Vector3.Zero) && !endPos.Equals(Vector3.Zero)) { if (startPos.Distance(Player.Position) > E.Range) { startPos = Player.Position.Extend(startPos, E.Range); } if (startPos.Distance(endPos) > ELength) { endPos = startPos.Extend(endPos, ELength); } E.Cast(startPos, endPos); return true; } } catch (Exception ex) { Global.Logger.AddItem(new LogItem(ex)); } return false; }
public static PredictionOutput GetPrediction(PredictionInput input) { var mainTargetPrediction = Prediction.GetPrediction(input, false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.To2D(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { //Add the posible targets in range: posibleTargets.AddRange(GetPossibleTargets(input)); } while (posibleTargets.Count > 1) { var mecCircle = MEC.GetMec(posibleTargets.Select(h => h.Position).ToList()); if (mecCircle.Radius <= input.RealRadius - 10 && Vector2.DistanceSquared(mecCircle.Center, input.RangeCheckFrom.To2D()) < input.Range * input.Range) { return new PredictionOutput { AoeTargetsHit = posibleTargets.Select(h => (Obj_AI_Hero)h.Unit).ToList(), CastPosition = mecCircle.Center.To3D(), UnitPosition = mainTargetPrediction.UnitPosition, Hitchance = mainTargetPrediction.Hitchance, Input = input, _aoeTargetsHitCount = posibleTargets.Count }; } float maxdist = -1; var maxdistindex = 1; for (var i = 1; i < posibleTargets.Count; i++) { var distance = Vector2.DistanceSquared(posibleTargets[i].Position, posibleTargets[0].Position); if (distance > maxdist || maxdist.CompareTo(-1) == 0) { maxdistindex = i; maxdist = distance; } } posibleTargets.RemoveAt(maxdistindex); } return mainTargetPrediction; }
public override void Execute() { // Jodus please... //if (Player.ManaPercent < Settings.MinMana) if (((Player.Mana / Player.MaxMana) * 100) < Settings.MinMana) { return; } // Precheck if (!(Settings.UseQ && Q.IsReady()) && !(Settings.UseE && E.IsReady())) { return; } // Minions around var minions = MinionManager.GetMinions(Q.Range, MinionTypes.All, MinionTeam.Enemy, MinionOrderTypes.MaxHealth); if (minions.Count == 0) { return; } #region Q usage if (Settings.UseQ && Q.IsReady() && !Player.IsDashing()) { // Validate available minions if (minions.Count >= Settings.MinNumberQ) { // Get only killable minions var killable = minions.Where(m => m.Health < Q.GetDamage(m)); if (killable.Count() > 0) { // Prepare prediction input for Collision check var input = new PredictionInput() { From = Q.From, Collision = Q.Collision, Delay = Q.Delay, Radius = Q.Width, Range = Q.Range, RangeCheckFrom = Q.RangeCheckFrom, Speed = Q.Speed, Type = Q.Type, CollisionObjects = new[] { CollisionableObjects.Heroes, CollisionableObjects.Minions, CollisionableObjects.YasuoWall } }; // Helpers var currentHitNumber = 0; var castPosition = Vector3.Zero; // Validate the collision foreach (var target in killable) { // Update unit in the input input.Unit = target; // Get colliding objects var colliding = LeagueSharp.Common.Collision.GetCollision(new List<Vector3>() { Player.ServerPosition.Extend(Prediction.GetPrediction(input).UnitPosition, Q.Range) }, input) .MakeUnique() .OrderBy(e => e.Distance(Player, true)) .ToList(); // Validate collision if (colliding.Count >= Settings.MinNumberQ && !colliding.Contains(Player)) { // Calculate hit number int i = 0; foreach (var collide in colliding) { // Break loop here since we can't kill the target if (Q.GetDamage(collide) < collide.Health) { if (currentHitNumber < i && i >= Settings.MinNumberQ) { currentHitNumber = i; castPosition = Q.GetPrediction(collide).CastPosition; } break; } // Increase hit count i++; } } } // Check if we have a valid target with enough targets being killed if (castPosition != Vector3.Zero) { if (Q.Cast(castPosition)) return; } } } } #endregion #region E usage if (Settings.UseE && E.IsReady()) { // Get minions in E range var minionsInRange = minions.Where(m => E.IsInRange(m)); // Validate available minions if (minionsInRange.Count() >= Settings.MinNumberE) { // Check if enough minions die with E int killableNum = 0; foreach (var minion in minionsInRange) { if (minion.IsRendKillable()) { // Increase kill number killableNum++; // Cast on condition met if (killableNum >= Settings.MinNumberE) { if (E.Cast(true)) return; break; } } } } } #endregion }
public static PredictionOutput GetPrediction(PredictionInput input) { var mainTargetPrediction = Prediction.GetPrediction(input, false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.To2D(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { //Add the posible targets in range: posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List<Vector2>(); foreach (var target in posibleTargets) { var targetCandidates = GetCandidates( input.From.To2D(), target.Position, (input.Radius), input.Range); candidates.AddRange(targetCandidates); } var bestCandidateHits = -1; var bestCandidate = new Vector2(); var bestCandidateHitPoints = new List<Vector2>(); var positionsList = posibleTargets.Select(t => t.Position).ToList(); foreach (var candidate in candidates) { if ( GetHits( input.From.To2D(), candidate, (input.Radius + input.Unit.BoundingRadius / 3 - 10), new List<Vector2> { posibleTargets[0].Position }).Count() == 1) { var hits = GetHits(input.From.To2D(), candidate, input.Radius, positionsList).ToList(); var hitsCount = hits.Count; if (hitsCount >= bestCandidateHits) { bestCandidateHits = hitsCount; bestCandidate = candidate; bestCandidateHitPoints = hits.ToList(); } } } if (bestCandidateHits > 1) { float maxDistance = -1; Vector2 p1 = new Vector2(), p2 = new Vector2(); //Center the position for (var i = 0; i < bestCandidateHitPoints.Count; i++) { for (var j = 0; j < bestCandidateHitPoints.Count; j++) { var startP = input.From.To2D(); var endP = bestCandidate; var proj1 = positionsList[i].ProjectOn(startP, endP); var proj2 = positionsList[j].ProjectOn(startP, endP); var dist = Vector2.DistanceSquared(bestCandidateHitPoints[i], proj1.LinePoint) + Vector2.DistanceSquared(bestCandidateHitPoints[j], proj2.LinePoint); if (dist >= maxDistance && (proj1.LinePoint - positionsList[i]).AngleBetween( proj2.LinePoint - positionsList[j]) > 90) { maxDistance = dist; p1 = positionsList[i]; p2 = positionsList[j]; } } } return new PredictionOutput { Hitchance = mainTargetPrediction.Hitchance, _aoeTargetsHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = ((p1 + p2) * 0.5f).To3D(), Input = input }; } } return mainTargetPrediction; }
private static double CheckForHit(Obj_AI_Hero hero) { List<IncomingDamage> damageList = Damages[Damages.Last().Key]; double maxDamage = 0; foreach (IncomingDamage incomingDamage in damageList) { var pred = new PredictionInput(); pred.Type = SkillshotType.SkillshotLine; pred.Radius = 50; pred.From = incomingDamage.StartPos; pred.RangeCheckFrom = incomingDamage.StartPos; pred.Range = incomingDamage.StartPos.Distance(incomingDamage.EndPos); pred.Collision = false; pred.Unit = hero; if (Prediction.GetPrediction(pred).Hitchance >= HitChance.Low) maxDamage += incomingDamage.Dmg; } return maxDamage; }