public static PredictionOutput GetLinePrediction(PredictionInput input) { var mainTargetPrediction = Prediction.Instance.GetPrediction(input, false, true); var posibleTargets = new List <PossibleTarget> { new PossibleTarget { Position = (Vector2)mainTargetPrediction.UnitPosition, Unit = input.Unit } }; if (mainTargetPrediction.HitChance >= HitChance.Medium) { posibleTargets.AddRange(AoePrediction.GetPossibleTargets(input)); } if (posibleTargets.Count <= 1) { return(mainTargetPrediction); } var candidates = new List <Vector2>(); foreach (var targetCandidates in posibleTargets.Select( target => GetCandidates((Vector2)input.From, target.Position, input.Radius, input.Range))) { candidates.AddRange(targetCandidates); } var bestCandidateHits = -1; var bestCandidate = default(Vector2); var bestCandidateHitPoints = new List <Vector2>(); var positionsList = posibleTargets.Select(t => t.Position).ToList(); foreach (var candidate in candidates) { if (GetHits( (Vector2)input.From, candidate, input.Radius + input.Unit.BoundingRadius / 3 - 10, new List <Vector2> { posibleTargets[0].Position }).Count() != 1) { continue; } var hits = GetHits((Vector2)input.From, candidate, input.Radius, positionsList).ToList(); var hitsCount = hits.Count; if (hitsCount < bestCandidateHits) { continue; } bestCandidateHits = hitsCount; bestCandidate = candidate; bestCandidateHitPoints = hits.ToList(); } if (bestCandidateHits <= 1) { return(mainTargetPrediction); } float maxDistance = -1; Vector2 p1 = default(Vector2), p2 = default(Vector2); for (var i = 0; i < bestCandidateHitPoints.Count; i++) { for (var j = 0; j < bestCandidateHitPoints.Count; j++) { var startP = (Vector2)input.From; 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)) { continue; } maxDistance = dist; p1 = positionsList[i]; p2 = positionsList[j]; } } return(new PredictionOutput { HitChance = mainTargetPrediction.HitChance, AoeHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = (Vector3)((p1 + p2) * 0.5f), Input = input }); }
public static PredictionOutput GetConePrediction(PredictionInput input) { var mainTargetPrediction = Prediction.Instance.GetPrediction(input, false, true); var posibleTargets = new List <PossibleTarget> { new PossibleTarget { Position = (Vector2)mainTargetPrediction.UnitPosition, Unit = input.Unit } }; if (mainTargetPrediction.HitChance >= HitChance.Medium) { posibleTargets.AddRange(AoePrediction.GetPossibleTargets(input)); } if (posibleTargets.Count <= 1) { return(mainTargetPrediction); } var candidates = new List <Vector2>(); foreach (var target in posibleTargets) { target.Position = target.Position - (Vector2)input.From; } for (var i = 0; i < posibleTargets.Count; i++) { for (var j = 0; j < posibleTargets.Count; j++) { if (i == j) { continue; } var p = (posibleTargets[i].Position + posibleTargets[j].Position) * 0.5f; if (!candidates.Contains(p)) { candidates.Add(p); } } } var bestCandidateHits = -1; var bestCandidate = default(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) { continue; } bestCandidate = candidate; bestCandidateHits = hits; } if (bestCandidateHits > 1 && input.From.DistanceSquared(bestCandidate) > 50 * 50) { return(new PredictionOutput { HitChance = mainTargetPrediction.HitChance, AoeHitCount = bestCandidateHits, UnitPosition = mainTargetPrediction.UnitPosition, CastPosition = (Vector3)bestCandidate, Input = input }); } return(mainTargetPrediction); }