/// <summary> /// Gets the list of minions currently between the source and target /// </summary> /// <param name="source"> /// The Source /// </param> /// <param name="targetPosition"> /// The Target Position /// </param> /// <returns> /// The <see cref="List" />. /// </returns> public static List <Obj_AI_Base> GetCollisionMinions(Obj_AI_Hero source, Vector3 targetPosition) { var input = new PredictionInput { Unit = source, Radius = SpellManager.Spell[SpellSlot.Q].Width, Delay = SpellManager.Spell[SpellSlot.Q].Delay, Speed = SpellManager.Spell[SpellSlot.Q].Speed, CollisionObjects = CollisionableObjects.Minions }; return (Collision.GetCollision(new List <Vector3> { targetPosition }, input) .OrderBy(x => x.Distance(source)) .ToList()); }
/// <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> 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(Cluster.GetAoEPrediction(input)); } } // Target too far away. if (Math.Abs(input.Range - float.MaxValue) > float.Epsilon && input.Unit.DistanceSquared(input.RangeCheckFrom) > 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 = GetAdvancedPrediction(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.DistanceSquared(input.Unit.Position) > Math.Pow(input.Range + input.RealRadius * 3 / 4, 2)) { result.Hitchance = HitChance.Medium; } if (input.RangeCheckFrom.DistanceSquared(result.UnitPosition) > Math.Pow(input.Range + (input.Type == SkillshotType.SkillshotCircle ? input.RealRadius : 0), 2)) { result.Hitchance = HitChance.OutOfRange; } if (input.RangeCheckFrom.DistanceSquared(result.CastPosition) > Math.Pow(input.Range, 2)) { if (result.Hitchance != HitChance.OutOfRange) { result.CastPosition = input.RangeCheckFrom + input.Range * (result.UnitPosition - input.RangeCheckFrom).Normalized().SetZ(); } else { result.Hitchance = HitChance.OutOfRange; } } } // Check for collision if (checkCollision && input.Collision) { 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); }