/// <summary> /// Returns Calculated Prediction based off given data values. /// </summary> /// <param name="input"> /// <see cref="PredictionInput" /> input /// </param> /// <param name="ft">Add Delay</param> /// <param name="checkCollision">Check Collision</param> /// <returns> /// <see cref="PredictionOutput" /> output /// </returns> public PredictionOutput GetPrediction(PredictionInput input, bool ft, bool checkCollision) { PredictionOutput result = null; if (!input.Unit.IsValidTarget()) { return(new PredictionOutput()); } input.From = input.From - (input.Unit.ServerPosition - input.From).Normalized() * ObjectManager.GetLocalPlayer().BoundingRadius; if (ft) { input.Delay += Game.Ping / 2000f + 0.06f; if (input.AoE) { return(AoePrediction.GetAoEPrediction(input)); } } if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon && input.Unit.DistanceSqr(input.RangeCheckFrom) > Math.Pow(input.Range * 1.5, 2)) { return(new PredictionOutput { Input = input }); } if (input.Unit.IsDashing()) { result = GetDashingPrediction(input); } else { var remainingImmobileT = UnitIsImmobileUntil(input.Unit); if (remainingImmobileT >= 0d) { result = GetImmobilePrediction(input, remainingImmobileT); } } if (result == null) { result = GetStandardPrediction(input); } if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon) { if (result.HitChance >= HitChance.High && input.RangeCheckFrom.DistanceSqr(input.Unit.Position) > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2)) { result.HitChance = HitChance.Medium; } if (input.RangeCheckFrom.DistanceSqr(result.UnitPosition) > Math.Pow( input.Range + (input.Type == SkillshotType.Circle ? input.RealRadius : 0), 2)) { result.HitChance = HitChance.OutOfRange; } if (input.RangeCheckFrom.DistanceSqr(result.CastPosition) > Math.Pow(input.Range, 2)) { if (result.HitChance != HitChance.OutOfRange) { result.CastPosition = input.RangeCheckFrom + input.Range * (result.UnitPosition - input.RangeCheckFrom).Normalized().FixHeight(); } else { result.HitChance = HitChance.OutOfRange; } } } if (!checkCollision || !input.Collision) { return(result); } 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); }