public PredictionOutput GetPrediction(PredictionInput input) { return(this.GetPrediction(input, true, input.Collision)); }
/// <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).To2D().Normalized().To3D(); } 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); }
internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1) { speed = Math.Abs(speed) < 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.GetPathLength(); 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 = PathTracker.GetCurrentPath(input.Unit).Time < 0.1d ? HitChance.VeryHigh : HitChance.High }); } tDistance -= d; } } 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.Line || input.Type == SkillshotType.Cone) { if (input.From.DistanceSquared(input.Unit.ServerPosition) < 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 = sol.Time; var pos = sol.Position; if (!pos.IsZero && t >= tT && t <= tT + tB) { if (pos.DistanceSquared(b) < 20) { break; } var p = pos + input.RealRadius * direction; return(new PredictionOutput { Input = input, CastPosition = pos.To3D(), UnitPosition = p.To3D(), HitChance = PathTracker.GetCurrentPath(input.Unit).Time < 0.1 ? HitChance.VeryHigh : HitChance.High }); } tT += tB; } } var position = path.Last(); return(new PredictionOutput { Input = input, CastPosition = position.To3D(), UnitPosition = position.To3D(), HitChance = HitChance.Medium }); }