private void CastQ(Obj_AI_Hero target) { float distance = Vector3.Distance(BallPos, target.ServerPosition); if (E.IsReady() && Player.Mana > RMANA + QMANA + WMANA + EMANA && distance > Player.Distance(target.ServerPosition) + 300) { E.CastOnUnit(Player); return; } if (Config.Item("PredictionMODE", true).GetValue <StringList>().SelectedIndex == 1) { //var prepos5 = Core.Prediction.GetPrediction(target, delay, Q.Width); var predInput2 = new Core.PredictionInput { Aoe = true, Collision = Q.Collision, Speed = Q.Speed, Delay = Q.Delay, Range = float.MaxValue, From = BallPos, Radius = Q.Width, Unit = target, Type = Core.SkillshotType.SkillshotCircle }; var prepos5 = Core.Prediction.GetPrediction(predInput2); if ((int)prepos5.Hitchance > 5 - Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex) { if (prepos5.CastPosition.Distance(prepos5.CastPosition) < Q.Range) { Q.Cast(prepos5.CastPosition); } } } else { float delay = (distance / Q.Speed + Q.Delay); var prepos = Prediction.GetPrediction(target, delay, Q.Width); if ((int)prepos.Hitchance > 5 - Config.Item("HitChance", true).GetValue <StringList>().SelectedIndex) { if (prepos.CastPosition.Distance(prepos.CastPosition) < Q.Range) { Q.Cast(prepos.CastPosition); } } } }
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 PredictionOutput GetPrediction(PredictionInput input) { return(GetPrediction(input, true, true)); }
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); } } }
private void Offensive() { if (Botrk.IsReady() && Config.Item("Botrk").GetValue <bool>()) { var t = TargetSelector.GetTarget(Botrk.Range, TargetSelector.DamageType.Physical); if (t.IsValidTarget()) { if (Config.Item("BotrkKS").GetValue <bool>() && Player.CalcDamage(t, Damage.DamageType.Physical, t.MaxHealth * 0.1) > t.Health - OktwCommon.GetIncomingDamage(t)) { Botrk.Cast(t); } if (Config.Item("BotrkLS").GetValue <bool>() && Player.Health < Player.MaxHealth * 0.5) { Botrk.Cast(t); } if (Config.Item("BotrkCombo").GetValue <bool>() && Program.Combo) { Botrk.Cast(t); } } } if (Hextech.IsReady() && Config.Item("Hextech").GetValue <bool>()) { var t = TargetSelector.GetTarget(Hextech.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { if (Config.Item("HextechKS").GetValue <bool>() && Player.CalcDamage(t, Damage.DamageType.Magical, 150 + Player.FlatMagicDamageMod * 0.4) > t.Health - OktwCommon.GetIncomingDamage(t)) { Hextech.Cast(t); } if (Config.Item("HextechCombo").GetValue <bool>() && Program.Combo) { Hextech.Cast(t); } } } if (Program.Combo && FrostQueen.IsReady() && Config.Item("FrostQueen").GetValue <bool>()) { var t = TargetSelector.GetTarget(FrostQueen.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { var predInput2 = new Core.PredictionInput { Aoe = true, Collision = false, Speed = 1200, Delay = 0.25f, Range = FrostQueen.Range, From = Player.ServerPosition, Radius = 200, Unit = t, Type = Core.SkillshotType.SkillshotCircle }; var poutput2 = Core.Prediction.GetPrediction(predInput2); if (poutput2.Hitchance >= Core.HitChance.High) { FrostQueen.Cast(poutput2.CastPosition); } } } if (Cutlass.IsReady() && Config.Item("Cutlass").GetValue <bool>()) { var t = TargetSelector.GetTarget(Cutlass.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { if (Config.Item("CutlassKS").GetValue <bool>() && Player.CalcDamage(t, Damage.DamageType.Magical, 100) > t.Health - OktwCommon.GetIncomingDamage(t)) { Cutlass.Cast(t); } if (Config.Item("CutlassCombo").GetValue <bool>() && Program.Combo) { Cutlass.Cast(t); } } } if (Youmuus.IsReady() && Config.Item("Youmuus").GetValue <bool>()) { var t = Orbwalker.GetTarget(); if (t.IsValidTarget() && t is Obj_AI_Hero) { if (Config.Item("YoumuusKS").GetValue <bool>() && t.Health < Player.MaxHealth * 0.6) { Youmuus.Cast(); } if (Config.Item("YoumuusCombo").GetValue <bool>() && Program.Combo) { Youmuus.Cast(); } } } if (Config.Item("Hydra").GetValue <bool>()) { if (Hydra.IsReady() && Player.CountEnemiesInRange(Hydra.Range) > 0) { Hydra.Cast(); } else if (Hydra2.IsReady() && Player.CountEnemiesInRange(Hydra2.Range) > 0) { Hydra2.Cast(); } } }
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 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 }; }
private void Offensive() { if (Botrk.IsReady() && Config.Item("Botrk").GetValue<bool>()) { var t = TargetSelector.GetTarget(Botrk.Range, TargetSelector.DamageType.Physical); if (t.IsValidTarget()) { if (Config.Item("BotrkKS").GetValue<bool>() && Player.CalcDamage(t, Damage.DamageType.Physical, t.MaxHealth * 0.1) > t.Health) Botrk.Cast(t); if (Config.Item("BotrkLS").GetValue<bool>() && Player.Health < Player.MaxHealth * 0.5) Botrk.Cast(t); if (Config.Item("BotrkCombo").GetValue<bool>() && Program.Combo) Botrk.Cast(t); } } if (Hextech.IsReady() && Config.Item("Hextech").GetValue<bool>()) { var t = TargetSelector.GetTarget(Hextech.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { if (Config.Item("HextechKS").GetValue<bool>() && Player.CalcDamage(t, Damage.DamageType.Magical, 150 + Player.FlatMagicDamageMod * 0.4) > t.Health) Hextech.Cast(t); if (Config.Item("HextechCombo").GetValue<bool>() && Program.Combo) Hextech.Cast(t); } } if (Program.Combo && FrostQueen.IsReady() && Config.Item("FrostQueen").GetValue<bool>()) { var t = TargetSelector.GetTarget(FrostQueen.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { var predInput2 = new Core.PredictionInput { Aoe = true, Collision = false, Speed = 1200, Delay = 0.25f, Range = FrostQueen.Range, From = Player.ServerPosition, Radius = 200, Unit = t, Type = Core.SkillshotType.SkillshotCircle }; var poutput2 = Core.Prediction.GetPrediction(predInput2); if (poutput2.Hitchance >= Core.HitChance.High) FrostQueen.Cast(poutput2.CastPosition); } } if (Cutlass.IsReady() && Config.Item("Cutlass").GetValue<bool>()) { var t = TargetSelector.GetTarget(Cutlass.Range, TargetSelector.DamageType.Magical); if (t.IsValidTarget()) { if (Config.Item("CutlassKS").GetValue<bool>() && Player.CalcDamage(t, Damage.DamageType.Magical, 100) > t.Health) Cutlass.Cast(t); if (Config.Item("CutlassCombo").GetValue<bool>() && Program.Combo) Cutlass.Cast(t); } } if (Youmuus.IsReady() && Config.Item("Youmuus").GetValue<bool>()) { var t = Orbwalker.GetTarget(); if (t.IsValidTarget() && t is Obj_AI_Hero) { if (Config.Item("YoumuusKS").GetValue<bool>() && t.Health < Player.MaxHealth * 0.6) Youmuus.Cast(); if (Config.Item("YoumuusCombo").GetValue<bool>() && Program.Combo) Youmuus.Cast(); } } if (Config.Item("Hydra").GetValue<bool>()) { if (Hydra.IsReady() && Player.CountEnemiesInRange(Hydra.Range) > 0) Hydra.Cast(); else if (Hydra2.IsReady() && Player.CountEnemiesInRange(Hydra2.Range) > 0) Hydra2.Cast(); } }
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); }
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 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.High }); } 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) { path = path.CutPath(input.Delay * speed - input.RealRadius); var distanceToTarget = input.From.Distance(input.Unit.ServerPosition); var m = distanceToTarget > input.Unit.BoundingRadius ? distanceToTarget / (distanceToTarget - input.Unit.BoundingRadius) : 1; var sp = m * input.Speed; 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(), sp, 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 && false) { var alpha = (input.From.To2D() - p).AngleBetween(a - b); if (alpha > 50 && alpha < 180 - 50) { var beta = (float)Math.Asin(input.RealRadius * 0.85f / 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 }); }
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); }
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 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 void CastQ(Obj_AI_Hero target) { float distance = Vector3.Distance(BallPos, target.ServerPosition); if (E.IsReady() && Player.Mana > RMANA + QMANA + WMANA + EMANA && distance > Player.Distance(target.ServerPosition) + 300) { E.CastOnUnit(Player); return; } if (Config.Item("PredictionMODE", true).GetValue<StringList>().SelectedIndex == 1) { //var prepos5 = Core.Prediction.GetPrediction(target, delay, Q.Width); var predInput2 = new Core.PredictionInput { Aoe = true, Collision = Q.Collision, Speed = Q.Speed, Delay = Q.Delay, Range = float.MaxValue, From = BallPos, Radius = Q.Width, Unit = target, Type = Core.SkillshotType.SkillshotCircle }; var prepos5 = Core.Prediction.GetPrediction(predInput2); if ((int)prepos5.Hitchance > 5 - Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex) { if (prepos5.CastPosition.Distance(prepos5.CastPosition) < Q.Range) { Q.Cast(prepos5.CastPosition); } } } else { float delay = (distance / Q.Speed + Q.Delay); var prepos = Prediction.GetPrediction(target, delay, Q.Width); if ((int)prepos.Hitchance > 5 - Config.Item("HitChance", true).GetValue<StringList>().SelectedIndex) { if (prepos.CastPosition.Distance(prepos.CastPosition) < Q.Range) { Q.Cast(prepos.CastPosition); } } } }
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(); }
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); } } } }
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; }
/// <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.ServerPosition.To2D().Distance(input.From.To2D()) < input.Radius) result.Add(minion); else { var minionPos = minion.ServerPosition; int bonusRadius = 20; if (minion.IsMoving) { minionPos = Prediction.GetPrediction(input, false, false).CastPosition; bonusRadius = 100; } if (minionPos.To2D().Distance(input.From.To2D(), position.To2D(), true, true) <= Math.Pow((input.Radius + bonusRadius + 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(); }
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; }
public static PredictionOutput GetPrediction(PredictionInput input) { return GetPrediction(input, true, true); }
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; } /* 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}; var originalUnit = input.Unit; result.CollisionObjects = Collision.GetCollision(positions, input); result.CollisionObjects.RemoveAll(i => i.NetworkId == originalUnit.NetworkId); result.Hitchance = result.CollisionObjects.Count > 0 ? HitChance.Collision : result.Hitchance; } 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 (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); } } }
/// <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 { if (minion.ServerPosition.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()); }