internal static PredictionOutput GetLinePrediction(PredictionInput input) { var mainTargetPrediction = input.GetPrediction(false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.ToVector2(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List<Vector2>(); foreach (var targetCandidates in posibleTargets.Select( i => GetCandidates(input.From.ToVector2(), i.Position, input.Radius, input.Range))) { candidates.AddRange(targetCandidates); } var bestCandidateHits = -1; var bestCandidate = new Vector2(); var bestCandidateHitPoints = new List<Vector2>(); var positionsList = posibleTargets.Select(i => i.Position).ToList(); foreach (var candidate in candidates) { if ( GetHits( input.From.ToVector2(), candidate, input.Radius + input.Unit.BoundingRadius / 3 - 10, new List<Vector2> { posibleTargets[0].Position }).Count == 1) { var hits = GetHits(input.From.ToVector2(), candidate, input.Radius, positionsList); var hitsCount = hits.Count; if (hitsCount >= bestCandidateHits) { bestCandidateHits = hitsCount; bestCandidate = candidate; bestCandidateHitPoints = hits; } } } if (bestCandidateHits > 1) { float maxDistance = -1; Vector2 p1 = new Vector2(), p2 = new Vector2(); for (var i = 0; i < bestCandidateHitPoints.Count; i++) { for (var j = 0; j < bestCandidateHitPoints.Count; j++) { var startP = input.From.ToVector2(); var endP = bestCandidate; var proj1 = positionsList[i].ProjectOn(startP, endP); var proj2 = positionsList[j].ProjectOn(startP, endP); var dist = bestCandidateHitPoints[i].DistanceSquared(proj1.LinePoint) + bestCandidateHitPoints[j].DistanceSquared(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, AoeHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = ((p1 + p2) * 0.5f).ToVector3(), Input = input }; } } return mainTargetPrediction; }
internal static PredictionOutput GetConePrediction(PredictionInput input) { var mainTargetPrediction = input.GetPrediction(false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.ToVector2(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { posibleTargets.AddRange(GetPossibleTargets(input)); } if (posibleTargets.Count > 1) { var candidates = new List<Vector2>(); foreach (var target in posibleTargets) { target.Position = target.Position - input.From.ToVector2(); } 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(i => i.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.ToVector2().DistanceSquared(bestCandidate) > 50 * 50) { return new PredictionOutput { Hitchance = mainTargetPrediction.Hitchance, AoeHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = bestCandidate.ToVector3(), Input = input }; } } return mainTargetPrediction; }
internal static PredictionOutput GetCirclePrediction(PredictionInput input) { var mainTargetPrediction = input.GetPrediction(false, true); var posibleTargets = new List<PossibleTarget> { new PossibleTarget { Position = mainTargetPrediction.UnitPosition.ToVector2(), Unit = input.Unit } }; if (mainTargetPrediction.Hitchance >= HitChance.Medium) { posibleTargets.AddRange(GetPossibleTargets(input)); } while (posibleTargets.Count > 1) { var mecCircle = ConvexHull.GetMec(posibleTargets.Select(i => i.Position).ToList()); if (mecCircle.Radius <= input.RealRadius - 10 && mecCircle.Center.DistanceSquared(input.RangeCheckFrom.ToVector2()) < input.Range * input.Range) { return new PredictionOutput { AoeTargetsHit = posibleTargets.Select(i => (Obj_AI_Hero)i.Unit).ToList(), CastPosition = mecCircle.Center.ToVector3(), UnitPosition = mainTargetPrediction.UnitPosition, Hitchance = mainTargetPrediction.Hitchance, Input = input, AoeHitCount = posibleTargets.Count }; } float maxdist = -1; var maxdistindex = 1; for (var i = 1; i < posibleTargets.Count; i++) { var distance = posibleTargets[i].Position.DistanceSquared(posibleTargets[0].Position); if (distance > maxdist || maxdist.CompareTo(-1) == 0) { maxdistindex = i; maxdist = distance; } } posibleTargets.RemoveAt(maxdistindex); } return mainTargetPrediction; }
private static List<PossibleTarget> GetPossibleTargets(PredictionInput input) { var result = new List<PossibleTarget>(); var originalUnit = input.Unit; foreach (var enemy in GameObjects.EnemyHeroes.Where( i => i.NetworkId != originalUnit.NetworkId && i.IsValidTarget(input.Range + 200 + input.RealRadius, true, input.RangeCheckFrom))) { input.Unit = enemy; var prediction = input.GetPrediction(false, false); if (prediction.Hitchance >= HitChance.High) { result.Add(new PossibleTarget { Position = prediction.UnitPosition.ToVector2(), Unit = enemy }); } } return result; }
public static PredictionOutput GetPrediction(PredictionInput input) { return input.GetPrediction(true, true); }
internal 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 objType in input.CollisionObjects) { switch (objType) { case CollisionableObjects.Minions: foreach (var minion in GameObjects.EnemyMinions.Where( i => i.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom))) { input.Unit = minion; var pred = input.GetPrediction(false, false); if (pred.UnitPosition.ToVector2() .DistanceSquared(input.From.ToVector2(), position.ToVector2(), true) <= Math.Pow(input.Radius + 15 + minion.BoundingRadius, 2)) { result.Add(minion); } } break; case CollisionableObjects.Heroes: foreach (var hero in GameObjects.EnemyHeroes.Where( i => i.IsValidTarget( Math.Min(input.Range + input.Radius + 100, 2000), true, input.RangeCheckFrom))) { input.Unit = hero; var pred = input.GetPrediction(false, false); if (pred.UnitPosition.ToVector2() .DistanceSquared(input.From.ToVector2(), position.ToVector2(), 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.ToVector2().Extend(position.ToVector2(), step * i); if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall)) { result.Add(ObjectManager.Player); } } break; case CollisionableObjects.YasuoWall: if (Variables.TickCount - wallCastT > 4000) { continue; } var wall = GameObjects.AllGameObjects.FirstOrDefault( i => i.IsValid && Regex.IsMatch(i.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase)); if (wall == null) { break; } var wallWidth = 300 + 50 * Convert.ToInt32(wall.Name.Substring(wall.Name.Length - 6, 1)); var wallDirection = (wall.Position.ToVector2() - yasuoWallCastedPos).Normalized().Perpendicular(); var wallStart = wall.Position.ToVector2() + wallWidth / 2f * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; if ( wallStart.Intersection(wallEnd, position.ToVector2(), input.From.ToVector2()) .Intersects) { var t = Variables.TickCount + (wallStart.Intersection( wallEnd, position.ToVector2(), input.From.ToVector2()).Point.Distance(input.From) / input.Speed + input.Delay) * 1000; if (t < wallCastT + 4000) { result.Add(ObjectManager.Player); } } break; } } } return result.Distinct().ToList(); }