public static void CastSpell(Spell QWER, Obj_AI_Base target) { if (Config.Item("PredictionMODE", true).GetValue <StringList>().SelectedIndex == 1) { Core.SkillshotType CoreType2 = Core.SkillshotType.SkillshotLine; bool aoe2 = false; if (QWER.Type == SkillshotType.SkillshotCircle) { CoreType2 = Core.SkillshotType.SkillshotCircle; aoe2 = true; } if (QWER.Width > 80 && !QWER.Collision) { aoe2 = true; } var predInput2 = new Core.PredictionInput { Aoe = aoe2, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType2 }; var poutput2 = Core.Prediction.GetPrediction(predInput2); //var poutput2 = QWER.GetPrediction(target); if (QWER.Speed != float.MaxValue && OktwCommon.CollisionYasuo(Player.ServerPosition, poutput2.CastPosition)) { return; } if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 0) { if (poutput2.Hitchance >= Core.HitChance.VeryHigh) { QWER.Cast(poutput2.CastPosition); } else if (predInput2.Aoe && poutput2.AoeTargetsHitCount > 1 && poutput2.Hitchance >= Core.HitChance.High) { QWER.Cast(poutput2.CastPosition); } } else if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 1) { if (poutput2.Hitchance >= Core.HitChance.High) { QWER.Cast(poutput2.CastPosition); } } else if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 2) { if (poutput2.Hitchance >= Core.HitChance.Medium) { QWER.Cast(poutput2.CastPosition); } } if (Game.Time - DrawSpellTime > 0.5) { DrawSpell = QWER; DrawSpellTime = Game.Time; } DrawSpellPos = poutput2; } else if (Config.Item("PredictionMODE", true).GetValue <StringList>().SelectedIndex == 0) { if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 0) { QWER.CastIfHitchanceEquals(target, HitChance.VeryHigh); return; } else if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 1) { QWER.CastIfHitchanceEquals(target, HitChance.High); return; } else if (Config.Item("HitChance ", true).GetValue <StringList>().SelectedIndex == 2) { QWER.CastIfHitchanceEquals(target, HitChance.Medium); return; } } else if (Config.Item("PredictionMODE", true).GetValue <StringList>().SelectedIndex == 2) { if (target is Obj_AI_Hero && target.IsValid) { var t = target as Obj_AI_Hero; if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 0) { QWER.SPredictionCast(t, HitChance.VeryHigh); return; } else if (Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex == 1) { QWER.SPredictionCast(t, HitChance.High); return; } else if (Config.Item("HitChance ", true).GetValue <StringList>().SelectedIndex == 2) { QWER.SPredictionCast(t, HitChance.Medium); return; } } else { QWER.CastIfHitchanceEquals(target, HitChance.High); } } }
public static void CastSpell(Spell QWER, Obj_AI_Base target) { if (Config.Item("PredictionMODE", true).GetValue<StringList>().SelectedIndex == 1) { Core.SkillshotType CoreType2 = Core.SkillshotType.SkillshotLine; bool aoe2 = false; if (QWER.Type == SkillshotType.SkillshotCircle) { CoreType2 = Core.SkillshotType.SkillshotCircle; aoe2 = true; } if (QWER.Width > 80 && !QWER.Collision) aoe2 = true; var predInput2 = new Core.PredictionInput { Aoe = aoe2, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType2 }; var poutput2 = Core.Prediction.GetPrediction(predInput2); //var poutput2 = QWER.GetPrediction(target); if (QWER.Speed != float.MaxValue && OktwCommon.CollisionYasuo(Player.ServerPosition, poutput2.CastPosition)) return; if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 0) { if (poutput2.Hitchance >= Core.HitChance.VeryHigh) QWER.Cast(poutput2.CastPosition); else if (predInput2.Aoe && poutput2.AoeTargetsHitCount > 1 && poutput2.Hitchance >= Core.HitChance.High) { QWER.Cast(poutput2.CastPosition); } } else if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 1) { if (poutput2.Hitchance >= Core.HitChance.High) QWER.Cast(poutput2.CastPosition); } else if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 2) { if (poutput2.Hitchance >= Core.HitChance.Medium) QWER.Cast(poutput2.CastPosition); } if (Game.Time - DrawSpellTime > 0.5) { DrawSpell = QWER; DrawSpellTime = Game.Time; } DrawSpellPos = poutput2; } else if (Config.Item("PredictionMODE", true).GetValue<StringList>().SelectedIndex == 0) { if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 0) { QWER.CastIfHitchanceEquals(target, HitChance.VeryHigh); return; } else if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 1) { QWER.CastIfHitchanceEquals(target, HitChance.High); return; } else if (Config.Item("HitChance ", true).GetValue<StringList>().SelectedIndex == 2) { QWER.CastIfHitchanceEquals(target, HitChance.Medium); return; } } else if (Config.Item("PredictionMODE", true).GetValue<StringList>().SelectedIndex == 2 ) { if (target is Obj_AI_Hero && target.IsValid) { var t = target as Obj_AI_Hero; if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 0) { QWER.SPredictionCast(t, HitChance.VeryHigh); return; } else if (Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex == 1) { QWER.SPredictionCast(t, HitChance.High); return; } else if (Config.Item("HitChance ", true).GetValue<StringList>().SelectedIndex == 2) { QWER.SPredictionCast(t, HitChance.Medium); return; } } else { QWER.CastIfHitchanceEquals(target, HitChance.High); } } }
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; }
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.High; 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 / 17) - (totalDelay * 2); float backToFront = moveArea * 1.5f; float pathMinLen = 900f; if (angleMove < 31) angleMove = 31; if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1d) { pathMinLen = 600f + backToFront; result.Hitchance = HitChance.High; } if (input.Type == SkillshotType.SkillshotCircle) { fixRange -= input.Radius / 2; } // SPAM CLICK /////////////////////////////////////////////////////////////////////////////////// if (UnitTracker.PathCalc(input.Unit)) { Program.debug("PRED: SPAM CLICK"); 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.1d) { Program.debug("PRED: NEW VISABLE"); result.Hitchance = HitChance.Medium; return result; } // SPECIAL CASES /////////////////////////////////////////////////////////////////////////////////// if (distanceFromToUnit < 300 || distanceFromToWaypoint < 200) { Program.debug("PRED: SPECIAL CASES"); result.Hitchance = HitChance.VeryHigh; return result; } // LONG CLICK DETECTION /////////////////////////////////////////////////////////////////////////////////// if (distanceUnitToWaypoint > pathMinLen) { Program.debug("PRED: LONG CLICK DETECTION"); result.Hitchance = HitChance.VeryHigh; return result; } // RUN IN LANE DETECTION /////////////////////////////////////////////////////////////////////////////////// if (distanceFromToWaypoint > fixRange && GetAngle(input.From, input.Unit) < angleMove) { Program.debug(GetAngle(input.From, input.Unit) + " PRED: RUN IN LANE DETECTION " + 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; Program.debug("PRED: AUTO ATTACK DETECTION"); 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; Program.debug("PRED: STOP LOGIC"); return result; } } // ANGLE HIT CHANCE /////////////////////////////////////////////////////////////////////////////////// if (input.Type == SkillshotType.SkillshotLine && input.Unit.Path.Count() > 0 && input.Unit.IsMoving) { if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1d && GetAngle(input.From, input.Unit) < angleMove && distanceUnitToWaypoint > moveArea * 0.6) { Program.debug("PRED: ANGLE HIT CHANCE " + angleMove + " > " + GetAngle(input.From, input.Unit)); result.Hitchance = HitChance.VeryHigh; return result; } } // CIRCLE NEW PATH /////////////////////////////////////////////////////////////////////////////////// if (input.Type == SkillshotType.SkillshotCircle) { if (UnitTracker.GetLastNewPathTime(input.Unit) < 0.1d && distanceUnitToWaypoint > fixRange && distanceFromToUnit < input.Range - fixRange && distanceUnitToWaypoint > fixRange) { Program.debug("PRED: CIRCLE NEW PATH"); result.Hitchance = HitChance.VeryHigh; return result; } } //Program.debug("PRED: NO DETECTION"); return result; }
public static void CastSpell(Spell QWER, Obj_AI_Base target) { if (HitChanceNum == 5) { Core.SkillshotType CoreType2 = Core.SkillshotType.SkillshotLine; bool aoe2 = false; if (QWER.Type == SkillshotType.SkillshotCircle) { CoreType2 = Core.SkillshotType.SkillshotCircle; aoe2 = true; } if (QWER.Width > 100) aoe2 = true; var predInput2 = new Core.PredictionInput { Aoe = aoe2, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType2 }; var poutput2 = Core.Prediction.GetPrediction(predInput2); //var poutput2 = QWER.GetPrediction(target); if (Game.Time - DrawSpellTime > 0.5) { DrawSpell = QWER; DrawSpellTime = Game.Time; } DrawSpellPos = poutput2; if(poutput2.Hitchance == Core.HitChance.VeryHigh) QWER.Cast(poutput2.CastPosition); return; } if (target.Path.Count() > 1) return; Core.SkillshotType CoreType = Core.SkillshotType.SkillshotLine; bool aoe = false; if (QWER.Type == SkillshotType.SkillshotCircle) { CoreType = Core.SkillshotType.SkillshotCircle; aoe = true; } if (QWER.Width > 100) aoe = true; var predInput = new Core.PredictionInput { Aoe = aoe, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType }; var poutput = Core.Prediction.GetPrediction(predInput); //var poutput2 = QWER.GetPrediction(target); if (Game.Time - DrawSpellTime > 0.5) { DrawSpell = QWER; DrawSpellTime = Game.Time; } DrawSpellPos = poutput; if (ColFix && HitChanceNum == 4) { if (QWER.Collision && OktwCommon.GetCollision(target, QWER, false, true)) return; } else { var col = poutput.CollisionObjects.Count(ColObj => ColObj.IsEnemy && ColObj.IsMinion && !ColObj.IsDead); if (col > 0) { return; } } if ((int)poutput.Hitchance > 4 && target.HasBuffOfType(BuffType.Slow)) { QWER.Cast(poutput.CastPosition); return; } if (target.HasBuff("Recall") || poutput.Hitchance == Core.HitChance.Immobile ) { QWER.Cast(poutput.CastPosition); return; } if (poutput.Hitchance == Core.HitChance.Dashing && QWER.Delay < 0.30f) { QWER.Cast(poutput.CastPosition); return; } if (HitChanceNum == 4) { if ((int)poutput.Hitchance < 5) return; if (NewWay && (int)poutput.Hitchance < 6) return; float fixRange; if (RangeFix) fixRange = (target.MoveSpeed * (Player.ServerPosition.Distance(target.ServerPosition) / QWER.Speed + QWER.Delay)) / 2; else fixRange = 0; if (target.IsWindingUp) { if (!tryAA) return; debug("IsWinding: "); if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { if (FastMode) QWER.Cast(poutput.CastPosition); else QWER.Cast(target); } return; } else if (target.Path.Count() == 0 && target.Position == target.ServerPosition ) { if (IgnoreNoMove) return; debug("NotMove"); if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { if (FastMode) QWER.Cast(poutput.CastPosition); else QWER.Cast(target); } return; } var LastWaypiont = target.GetWaypoints().Last().To3D(); if (target.ServerPosition.Distance(Player.ServerPosition) < LastWaypiont.Distance(Player.ServerPosition) - fixRange) { if (FastMode) QWER.Cast(poutput.CastPosition); else QWER.Cast(target); debug("Run" ); } else if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { float BackToFront = ((target.MoveSpeed * QWER.Delay) + (Player.Distance(target.ServerPosition) / QWER.Speed)); float SiteToSite = (BackToFront * 2) - QWER.Width; if ((target.ServerPosition.Distance(LastWaypiont) > SiteToSite || Math.Abs(Player.Distance(LastWaypiont) - Player.Distance(target.ServerPosition)) > BackToFront) || Player.Distance(target.ServerPosition) < SiteToSite + target.BoundingRadius * 2 || Player.Distance(LastWaypiont) < BackToFront) { if (FastMode) QWER.Cast(poutput.CastPosition); else QWER.Cast(target); debug("good 2"); } else debug("ignore 2"); } else debug("fixed " + fixRange); } else if (HitChanceNum == 3) { if ((int)poutput.Hitchance < 5) return; if ( QWER.Delay > 0.4) { if ((int)poutput.Hitchance < 6 || target.IsWindingUp) return; } var fixRange = (target.MoveSpeed * (Player.ServerPosition.Distance(target.ServerPosition) / QWER.Speed + QWER.Delay)) / 2; if (QWER.Delay < 0.3 && (QWER.Speed > 1500 || QWER.Type == SkillshotType.SkillshotCircle) && (target.IsWindingUp || (int)poutput.Hitchance == 6)) { if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { QWER.Cast(poutput.CastPosition); } return; } if (target.Path.Count() == 0 && target.Position == target.ServerPosition && !target.IsWindingUp) { if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { QWER.Cast(poutput.CastPosition); } return; } var waypoints = target.GetWaypoints().Last<Vector2>().To3D(); float BackToFront = ((target.MoveSpeed * QWER.Delay) + (Player.Distance(target.ServerPosition) / QWER.Speed)); float SiteToSite = (BackToFront * 2) - QWER.Width; if ((target.ServerPosition.Distance(waypoints) > SiteToSite || Math.Abs(Player.Distance(waypoints) - Player.Distance(target.Position)) > BackToFront) || Player.Distance(target.Position) < SiteToSite + target.BoundingRadius * 2 || Player.Distance(waypoints) < BackToFront ) { if (waypoints.Distance(Player.Position) <= target.Distance(Player.Position)) { if (Player.Distance(target.ServerPosition) < QWER.Range - fixRange) { QWER.Cast(poutput.CastPosition); } } else { QWER.Cast(poutput.CastPosition); } } } else if (HitChanceNum == 0) QWER.Cast(target, true); else if (HitChanceNum == 1) { if ((int)poutput.Hitchance > 4) QWER.Cast(poutput.CastPosition); } else if (HitChanceNum == 2) { List<Vector2> waypoints = target.GetWaypoints(); if (waypoints.Last<Vector2>().To3D().Distance(poutput.CastPosition) > QWER.Width && (int)poutput.Hitchance > 4) { if (waypoints.Last<Vector2>().To3D().Distance(Player.Position) <= target.Distance(Player.Position) || (target.Path.Count() == 0 && target.Position == target.ServerPosition)) { if (Player.Distance(target.ServerPosition) < QWER.Range - (poutput.CastPosition.Distance(target.ServerPosition) + target.BoundingRadius)) { QWER.Cast(poutput.CastPosition); } } else if ((int)poutput.Hitchance == 5) { QWER.Cast(poutput.CastPosition); } } } }
private static PredictionOutput WayPointAnalysis(PredictionOutput result, PredictionInput input) { var totalDelay = input.From.Distance(input.Unit.ServerPosition) / input.Speed + input.Delay; if (Math.Abs(input.Speed - float.MaxValue) < float.Epsilon) { totalDelay = input.Delay; } var fixRange = (input.Unit.MoveSpeed * totalDelay) / 2; var LastWaypiont = input.Unit.GetWaypoints().Last().To3D(); var pathMinLen = 800; double angleMove = 30 + (input.Radius / 10); if (PathTracker.GetCurrentPath(input.Unit).Time < 0.1d) { pathMinLen = 600; angleMove += 5; fixRange = (input.Unit.MoveSpeed * totalDelay) / 3; } if (input.Type == SkillshotType.SkillshotCircle) { fixRange -= input.Radius / 2; } if (input.Type == SkillshotType.SkillshotLine) { if (input.Unit.Path.Count() > 0) { if (GetAngle(input.From, input.Unit) < angleMove) { result.Hitchance = HitChance.VeryHigh; } else { result.Hitchance = HitChance.High; } } } else if (input.Type == SkillshotType.SkillshotCircle) { if (totalDelay < 1.1) { if (totalDelay < 0.7 && OnProcessSpellDetection.GetLastAutoAttackTime(input.Unit) < 0.1d) { result.Hitchance = HitChance.VeryHigh; } if (PathTracker.GetCurrentPath(input.Unit).Time < 0.1d) { result.Hitchance = HitChance.VeryHigh; } } } if (input.Unit.HasBuffOfType(BuffType.Slow) || input.Unit.Distance(input.From) < 300 || LastWaypiont.Distance(input.From) < 250) { result.Hitchance = HitChance.VeryHigh; } if (LastWaypiont.Distance(input.Unit.ServerPosition) > pathMinLen) { result.Hitchance = HitChance.VeryHigh; } if (input.Unit.Path.Count() == 0 && input.Unit.Position == input.Unit.ServerPosition && !input.Unit.IsWindingUp) { if (input.From.Distance(input.Unit.ServerPosition) > input.Range - fixRange) { result.Hitchance = HitChance.High; } else { result.Hitchance = HitChance.VeryHigh; } return(result); } else if (LastWaypiont.Distance(input.From) <= input.Unit.Distance(input.From)) { if (input.From.Distance(input.Unit.ServerPosition) > input.Range - fixRange) { result.Hitchance = HitChance.High; } } float BackToFront = ((input.Unit.MoveSpeed * totalDelay)); if (input.Unit.Path.Count() > 0) { if (input.Unit.Distance(LastWaypiont) < BackToFront) { result.Hitchance = HitChance.Medium; } } if (totalDelay > 0.7 && input.Unit.IsWindingUp) { result.Hitchance = HitChance.Medium; } if (totalDelay > 1 && OnProcessSpellDetection.GetLastAutoAttackTime(input.Unit) < 0.1d) { result.Hitchance = HitChance.Medium; } if (input.Unit.Path.Count() > 1 && input.Type == SkillshotType.SkillshotLine) { result.Hitchance = HitChance.Medium; } if (input.Unit.Distance(input.From) < 300 || LastWaypiont.Distance(input.From) < 250) { result.Hitchance = HitChance.VeryHigh; } return(result); }
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; } } } if (result.Hitchance > HitChance.Medium) { WayPointAnalysis(result, input); } //Check for collision if (checkCollision && input.Collision && result.Hitchance > HitChance.Impossible) { var positions = new List <Vector3> { result.CastPosition }; 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); }