public Input(Obj_AI_Base _target, Spell s, Vector3 _from, Vector3 _rangeCheckFrom) { Target = _target; SpellDelay = s.Delay; SpellMissileSpeed = s.Speed; SpellWidth = s.Width; SpellRange = s.Range; SpellCollisionable = s.Collision; SpellSkillShotType = s.Type; Path = Target.GetWaypoints(); if (Target is Obj_AI_Hero) { Obj_AI_Hero t = Target as Obj_AI_Hero; AvgReactionTime = t.AvgMovChangeTime(); LastMovChangeTime = t.LastMovChangeTime(); AvgPathLenght = t.AvgPathLenght(); } else { AvgReactionTime = 0; LastMovChangeTime = 0; AvgPathLenght = 0; } From = _from; RangeCheckFrom = _rangeCheckFrom; }
public static List<Vector2> GetCastMinionsPredictedPositions(List<Obj_AI_Base> minions, float delay, float width, float speed, Vector3 from, float range, bool collision, SkillshotType stype, Vector3 rangeCheckFrom = new Vector3()) { var result = new List<Vector2>(); from = from.To2D().IsValid() ? from : ObjectManager.Player.ServerPosition; foreach (var minion in minions) { var pos = Prediction.GetPrediction(new PredictionInput { Unit = minion, Delay = delay, Radius = width, Speed = speed, From = from, Range = range, Collision = collision, Type = stype, RangeCheckFrom = rangeCheckFrom }); if (pos.Hitchance >= HitChance.High) { result.Add(pos.CastPosition.To2D()); } } return result; }
public SpellData(string baseSkinName, string spellName, SpellSlot slot, SkillshotType type, float delay, float range, float radius, float missileSpeed, bool addHitbox, bool fixedRange, int defaultDangerValue) { BaseSkinName = baseSkinName; SpellName = spellName; Slot = slot; Type = type; Delay = delay; Range = range; _radius = radius; MissileSpeed = missileSpeed; AddHitbox = addHitbox; FixedRange = fixedRange; DangerValue = defaultDangerValue; }
/// <summary> /// Sets the spell to be a skillshot. /// </summary> /// <param name="delay">The delay.</param> /// <param name="width">The width.</param> /// <param name="speed">The speed.</param> /// <param name="collision">if set to <c>true</c>, the spell has collision.</param> /// <param name="type">The type.</param> /// <param name="from">From.</param> /// <param name="rangeCheckFrom">The range check from.</param> public void SetSkillshot(float delay, float width, float speed, bool collision, SkillshotType type, Vector3 from = new Vector3(), Vector3 rangeCheckFrom = new Vector3()) { Delay = delay; Width = width; Speed = speed; From = from; Collision = collision; Type = type; RangeCheckFrom = rangeCheckFrom; IsSkillshot = true; }
/// <summary> /// Sets the spell to be a skillshot. /// </summary> /// <param name="delay">The delay.</param> /// <param name="width">The width.</param> /// <param name="speed">The speed.</param> /// <param name="collision">if set to <c>true</c>, the spell has collision.</param> /// <param name="type">The type.</param> /// <param name="from">From.</param> /// <param name="rangeCheckFrom">The range check from.</param> public void SetSkillshot( float delay, float width, float speed, bool collision, SkillshotType type, Vector3 from = new Vector3(), Vector3 rangeCheckFrom = new Vector3()) { this.Delay = delay; this.Width = width; this.Speed = speed; this.From = from; this.Collision = collision; this.Type = type; this.RangeCheckFrom = rangeCheckFrom; this.IsSkillshot = true; }
public static void CastSpell(Spell qwer, Obj_AI_Base target) { switch (GetStringValue("PredictionMode")) { case 0: { const SkillshotType coreType2 = SkillshotType.SkillshotLine; var predInput2 = new PredictionInput { Collision = qwer.Collision, Speed = qwer.Speed, Delay = qwer.Delay, Range = qwer.Range, From = Player.ServerPosition, Radius = qwer.Width, Unit = target, Type = coreType2 }; var poutput2 = Prediction.GetPrediction(predInput2); // if (poutput2 == null) return; if (poutput2.Hitchance >= HitChance.High || poutput2.Hitchance == HitChance.Immobile || poutput2.Hitchance == HitChance.Dashing) { qwer.Cast(poutput2.CastPosition); } break; } case 1: var pred = Q.GetPrediction(target); if (pred.Hitchance >= LeagueSharp.Common.HitChance.High || pred.Hitchance == LeagueSharp.Common.HitChance.Immobile) { if (pred.CollisionObjects.Count == 0) { Q.Cast(pred.CastPosition); } } break; } }
/// <summary> /// Sets the Spell Data to Skill-shot data. /// </summary> /// <param name="delay"> /// Spell Delay /// </param> /// <param name="skillWidth"> /// Spell Width /// </param> /// <param name="speed"> /// Spell Speed /// </param> /// <param name="collision"> /// Spell Collision Flag /// </param> /// <param name="type"> /// Skill-shot Type /// </param> /// <param name="fromVector3"> /// From Vector3 Source /// </param> /// <param name="rangeCheckFromVector3"> /// Range Check From Vector3 Source /// </param> /// <returns> /// The <see cref="Spell" />. /// </returns> public Spell SetSkillshot( float delay, float skillWidth, float speed, bool collision, SkillshotType type, Vector3 fromVector3 = default(Vector3), Vector3 rangeCheckFromVector3 = default(Vector3)) { this.Delay = delay; this.Width = skillWidth; this.Speed = speed; this.From = fromVector3; this.Collision = collision; this.Type = type; this.RangeCheckFrom = rangeCheckFromVector3; this.IsSkillshot = true; return(this); }
public void SetSkillshot(float delay, float width, float speed, bool collision, SkillshotType type, Vector3 from = new Vector3(), Vector3 rangeCheckFrom = new Vector3()) { From = from; Collision = collision; Type = type; RangeCheckFrom = rangeCheckFrom; IsTargeted = false; IsSkillshot = true; IsChargedSpell = false; if (speed == float.MaxValue) { speed = 2147483648f; } charge = null; targeted = null; if (type == SkillshotType.SkillshotCircle) { skillshot = new EloBuddy.SDK.Spell.Skillshot(Slot, (uint)_range, SkillShotType.Circular, (int)(delay * 1000), (int)(speed), (int)width); } if (Type == SkillshotType.SkillshotCone) { skillshot = new EloBuddy.SDK.Spell.Skillshot(Slot, (uint)_range, SkillShotType.Cone, (int)(delay * 1000), (int)(speed), (int)width); } if (Type == SkillshotType.SkillshotLine) { skillshot = new EloBuddy.SDK.Spell.Skillshot(Slot, (uint)_range, SkillShotType.Linear, (int)(delay * 1000), (int)(speed), (int)width); } if (collision) { skillshot.AllowedCollisionCount = 0; } }
private static LeagueSharp.Common.SkillshotType ConvertSkillShotType(CCChainer.Data.SkillShotType Type) { var result = new SkillshotType(); switch (Type) { case SkillShotType.SkillshotCircle: result = SkillshotType.SkillshotCircle; break; case SkillShotType.SkillshotMissileLine: case SkillShotType.SkillshotLine: result = SkillshotType.SkillshotLine; break; case SkillShotType.SkillshotMissileCone: case SkillShotType.SkillshotCone: result = SkillshotType.SkillshotCone; break; } return(result); }
private void CastW(Obj_AI_Base t) { SkillshotType CoreType2 = SkillshotType.SkillshotLine; var predInput2 = new PredictionInput { Aoe = false, Collision = W.Collision, Speed = W.Speed, Delay = W.Delay, Range = W.Range, From = Player.ServerPosition, Radius = W.Width, Unit = t, Type = CoreType2 }; var poutput2 = Prediction.GetPrediction(predInput2); if (poutput2.Hitchance >= HitChance.High) { W.Cast(poutput2.CastPosition); } }
public SpellData(string championName, string spellName, SpellSlot slot, SkillshotType type, int delay, int range, int radius, int missileSpeed, bool addHitbox, bool fixedRange, int defaultDangerValue) { ChampionName = championName; SpellName = spellName; Slot = slot; Type = type; Delay = delay; Range = range; RawRadius = radius; MissileSpeed = missileSpeed; AddHitbox = addHitbox; FixedRange = fixedRange; DangerValue = defaultDangerValue; }
public static List <Vector2> GetMinionsPredictedPositions(List <Obj_AI_Base> minions, float delay, float width, float speed, Vector3 from, float range, bool collision, SkillshotType stype, Vector3 rangeCheckFrom = new Vector3()) { var result = new List <Vector2>(); from = from.To2D().IsValid() ? from : ObjectManager.Player.ServerPosition; foreach (var minion in minions) { var pos = Prediction.GetPrediction(new PredictionInput { Unit = minion, Delay = delay, Radius = width, Speed = speed, From = from, Range = range, Collision = collision, Type = stype, RangeCheckFrom = rangeCheckFrom }); if (pos.Hitchance >= HitChance.High) { result.Add(pos.UnitPosition.To2D()); } } return(result); }
public void SetSkillshot(int delay, int width, int speed, SkillshotType skillshotType, Vector3 sourcePosition = new Vector3(), Vector3 rangeCheckPosition = new Vector3()) { Delay = delay; Width = width; Speed = speed; SkillShotType = skillshotType; SourcePosition = sourcePosition; RangeCheckPosition = rangeCheckPosition; IsSkillshot = true; }
public static bool IsBehindWindWall(this AIHeroClient target, float delay = 0f, float radiusOrWidth = 0f, float speed = float.MaxValue, SkillshotType testType = SkillshotType.SkillshotLine) { return(Prediction.GetPrediction(new PredictionInput { Collision = true, CollisionObjects = new[] { CollisionableObjects.YasuoWall }, Aoe = false, Delay = delay, From = ObjectManager.Player.ServerPosition, Radius = radiusOrWidth, Speed = speed, Type = testType, Unit = target }, true, true).Hitchance == HitChance.Collision); }
public Input(Obj_AI_Base _target, Spell s) { Target = _target; SpellDelay = s.Delay; SpellMissileSpeed = s.Speed; SpellWidth = s.Width; SpellRange = s.Range; SpellCollisionable = s.Collision; SpellSkillShotType = s.Type; Path = Target.GetWaypoints(); if (Target is AIHeroClient) { var t = Target as AIHeroClient; AvgReactionTime = t.AvgMovChangeTime(); LastMovChangeTime = t.LastMovChangeTime(); AvgPathLenght = t.AvgPathLenght(); LastAngleDiff = t.LastAngleDiff(); } else { AvgReactionTime = 0; LastMovChangeTime = 0; AvgPathLenght = 0; LastAngleDiff = 0; } From = s.From; RangeCheckFrom = s.RangeCheckFrom; }
public static bool CanCastSpellPred(Spell QWER, Obj_AI_Base target) { int predIndex = 0; HitChance hitchance = HitChance.Low; if (QWER.Slot == SpellSlot.Q) { predIndex = MainMenu.Item("Qpred", true).GetValue <StringList>().SelectedIndex; if (MainMenu.Item("QHitChance", true).GetValue <StringList>().SelectedIndex == 0) { hitchance = HitChance.VeryHigh; } else if (MainMenu.Item("QHitChance", true).GetValue <StringList>().SelectedIndex == 1) { hitchance = HitChance.High; } else if (MainMenu.Item("QHitChance", true).GetValue <StringList>().SelectedIndex == 2) { hitchance = HitChance.Medium; } } else if (QWER.Slot == SpellSlot.W) { predIndex = MainMenu.Item("Wpred", true).GetValue <StringList>().SelectedIndex; if (MainMenu.Item("WHitChance", true).GetValue <StringList>().SelectedIndex == 0) { hitchance = HitChance.VeryHigh; } else if (MainMenu.Item("WHitChance", true).GetValue <StringList>().SelectedIndex == 1) { hitchance = HitChance.High; } else if (MainMenu.Item("WHitChance", true).GetValue <StringList>().SelectedIndex == 2) { hitchance = HitChance.Medium; } } else if (QWER.Slot == SpellSlot.E) { predIndex = MainMenu.Item("Epred", true).GetValue <StringList>().SelectedIndex; if (MainMenu.Item("EHitChance", true).GetValue <StringList>().SelectedIndex == 0) { hitchance = HitChance.VeryHigh; } else if (MainMenu.Item("EHitChance", true).GetValue <StringList>().SelectedIndex == 1) { hitchance = HitChance.High; } else if (MainMenu.Item("EHitChance", true).GetValue <StringList>().SelectedIndex == 2) { hitchance = HitChance.Medium; } } else if (QWER.Slot == SpellSlot.R) { predIndex = MainMenu.Item("Rpred", true).GetValue <StringList>().SelectedIndex; if (MainMenu.Item("RHitChance", true).GetValue <StringList>().SelectedIndex == 0) { hitchance = HitChance.VeryHigh; } else if (MainMenu.Item("RHitChance", true).GetValue <StringList>().SelectedIndex == 1) { hitchance = HitChance.High; } else if (MainMenu.Item("RHitChance", true).GetValue <StringList>().SelectedIndex == 2) { hitchance = HitChance.Medium; } } if (predIndex == 3) { SkillshotType CoreType2 = SkillshotType.SkillshotLine; bool aoe2 = false; if (QWER.Width > 80 && !QWER.Collision) { aoe2 = true; } var predInput2 = new PredictionInput { Aoe = aoe2, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType2 }; var poutput2 = Prediction.GetPrediction(predInput2); if (QWER.Speed != float.MaxValue && OktwCommon.CollisionYasuo(Player.ServerPosition, poutput2.CastPosition)) { return(false); } if ((int)hitchance == 6) { if (poutput2.Hitchance >= HitChance.VeryHigh) { return(true); } else if (predInput2.Aoe && poutput2.AoeTargetsHitCount > 1 && poutput2.Hitchance >= HitChance.High) { return(true); } } else if ((int)hitchance == 5) { if (poutput2.Hitchance >= HitChance.High) { return(true); } } else if ((int)hitchance == 4) { if (poutput2.Hitchance >= HitChance.Medium) { return(true); } } } else if (predIndex == 1) { SkillshotType CoreType2 = SkillshotType.SkillshotLine; bool aoe2 = false; if (QWER.Type == SkillshotType.SkillshotCircle) { CoreType2 = SkillshotType.SkillshotCircle; aoe2 = true; } if (QWER.Width > 80 && !QWER.Collision) { aoe2 = true; } var predInput2 = new PredictionInput { Aoe = aoe2, Collision = QWER.Collision, Speed = QWER.Speed, Delay = QWER.Delay, Range = QWER.Range, From = Player.ServerPosition, Radius = QWER.Width, Unit = target, Type = CoreType2 }; var poutput2 = Prediction.GetPrediction(predInput2); //var poutput2 = QWER.GetPrediction(target); if (QWER.Speed != float.MaxValue && OktwCommon.CollisionYasuo(Player.ServerPosition, poutput2.CastPosition)) { return(false); } if ((int)hitchance == 6) { if (poutput2.Hitchance >= HitChance.VeryHigh) { return(true); } else if (predInput2.Aoe && poutput2.AoeTargetsHitCount > 1 && poutput2.Hitchance >= HitChance.High) { return(true); } } else if ((int)hitchance == 5) { if (poutput2.Hitchance >= HitChance.High) { return(true); } } else if ((int)hitchance == 4) { if (poutput2.Hitchance >= HitChance.Medium) { return(true); } } if (Game.Time - DrawSpellTime > 0.5) { DrawSpell = QWER; DrawSpellTime = Game.Time; } DrawSpellPos = poutput2; } else if (predIndex == 0) { return(QWER.GetPrediction(target).Hitchance >= hitchance); } else if (predIndex == 2) { return(QWER.GetPrediction(target).Hitchance >= HitChance.High); } return(false); }
public MarksmanSpell(SpellSlot nSpellSlot, TargetSelector.DamageType nDamageType, float nRange, float nDelay, float nWidth, float nSpeed, SkillshotType nSkillshotType, bool nCollision, CollisionTypes[] nCollisions) { MNSpellSlot = nSpellSlot; mDamageType = nDamageType; mRange = nRange; mDelay = nDelay; mWidth = nWidth; mSpeed = nSpeed; mCollision = nCollision; mCollisions = nCollisions; }
public Input(Obj_AI_Base _target, float delay, float speed, float radius, float range, bool collision, SkillshotType type, Vector3 _from, Vector3 _rangeCheckFrom) { Target = _target; SpellDelay = delay; SpellMissileSpeed = speed; SpellWidth = radius; SpellRange = range; SpellCollisionable = collision; SpellSkillShotType = type; Path = Target.GetWaypoints(); if (Target is Obj_AI_Hero) { Obj_AI_Hero t = Target as Obj_AI_Hero; AvgReactionTime = t.AvgMovChangeTime(); LastMovChangeTime = t.LastMovChangeTime(); AvgPathLenght = t.AvgPathLenght(); LastAngleDiff = t.LastAngleDiff(); } else { AvgReactionTime = 0; LastMovChangeTime = 0; AvgPathLenght = 0; LastAngleDiff = 0; } From = _from; RangeCheckFrom = _rangeCheckFrom; }
public static List <Vector2> GetMinionsPredictedPositions(List <Obj_AI_Base> minions, float delay, float width, float speed, Vector3 from, float range, bool collision, SkillshotType stype, Vector3 rangeCheckFrom = new Vector3()) { from = from.To2D().IsValid() ? from : ObjectManager.Player.ServerPosition; return((from minion in minions select Prediction.GetPrediction( new PredictionInput { Unit = minion, Delay = delay, Radius = width, Speed = speed, From = @from, Range = range, Collision = collision, Type = stype, RangeCheckFrom = rangeCheckFrom }) into pos where pos.Hitchance >= HitChance.High select pos.UnitPosition.To2D()).ToList()); }
/// <summary> /// Gets Prediction result while unit is immobile /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetImmobilePrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from) { Result result = new Result(); result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; //calculate spell arrival time float t = delay + Game.Ping / 2000f; if (missileSpeed != 0) { t += from.Distance(target.ServerPosition) / missileSpeed; } if (type == SkillshotType.SkillshotCircle) { t += width / target.MoveSpeed / 2f; } if (t >= Utility.LeftImmobileTime(target)) { result.HitChance = HitChance.Immobile; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) { result.HitChance = HitChance.Collision; } if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); } if (target is Obj_AI_Hero) { result.HitChance = GetHitChance(t - Utility.LeftImmobileTime(target), ((Obj_AI_Hero)target).AvgMovChangeTime(), 0, 0); } else { result.HitChance = HitChance.High; } //check collisions if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) { result.HitChance = HitChance.Collision; } //check range if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) { moveSpeed = target.MoveSpeed; } Result result = new Result(); float flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile { flyTimeMax = range / missileSpeed; } float tMin = delay + Game.Ping / 2000f + SpellDelay / 1000f; float tMax = flyTimeMax + delay + Game.Ping / 1000f + SpellDelay / 1000f; float pathTime = 0f; int[] pathBounds = new int[] { -1, -1 }; //find bounds for (int i = 0; i < path.Count - 1; i++) { float t = path[i + 1].Distance(path[i]) / moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) { pathBounds[0] = i; } if (pathTime <= tMax && pathTime + t >= tMax) { pathBounds[1] = i; } if (pathBounds[0] != -1 && pathBounds[1] != -1) { break; } pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (int k = pathBounds[0]; k <= pathBounds[1]; k++) { Vector2 direction = (path[k + 1] - path[k]).Normalized(); float distance = width; if (predMenu.Item("SPREDWPANALYSIS").GetValue <StringList>().SelectedIndex == 0) { distance = target.BoundingRadius; } int steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance); //split & anlyse current path for (int i = 0; i < steps; i++) { Vector2 pA = path[k] + (direction * distance * i); Vector2 pB = path[k] + (direction * distance * (i + 1)); Vector2 center = (pA + pB) / 2f; float flytime = missileSpeed != 0 ? from.Distance(center) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 1000f + SpellDelay / 1000f; Vector2 currentPosition = isDash ? target.Position.To2D() : target.ServerPosition.To2D(); float arriveTimeA = currentPosition.Distance(pA) / moveSpeed; float arriveTimeB = currentPosition.Distance(pB) / moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp); result.CastPosition = center; result.UnitPosition = center + (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); return(result); } } if (steps == 0) { float flytime = missileSpeed != 0 ? from.Distance(path[pathBounds[1]]) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 2000f + SpellDelay / 1000f; result.HitChance = GetHitChance(t, avgt, movt, avgp); result.CastPosition = path[pathBounds[1]]; result.UnitPosition = path[pathBounds[1]]; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); return(result); } } } result.HitChance = HitChance.Impossible; return(result); }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <param name="rangeCheckFrom"></param> /// <returns>Prediction result as <see cref="Prediction.Result"/></returns> internal static Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, Vector2 from, Vector2 rangeCheckFrom) { Prediction.AssertInitializationMode(); Result result = new Result(); try { if (type == SkillshotType.SkillshotCircle) { range += width; } //to do: hook logic ? by storing average movement direction etc if (path.Count <= 1 && movt > 100 && (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick > 300 || !predMenu.Item("SPREDWINDUP").GetValue <bool>())) //if target is not moving, easy to hit (and not aaing) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); } if (target is Obj_AI_Hero) { if (((Obj_AI_Hero)target).IsChannelingImportantSpell()) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); } if (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick < 300 && predMenu.Item("SPREDWINDUP").GetValue <bool>()) { if (target.AttackCastDelay * 1000 + PathTracker.EnemyInfo[target.NetworkId].AvgOrbwalkTime + avgt - width / 2f / target.MoveSpeed >= GetArrivalTime(target.ServerPosition.To2D().Distance(from), delay, missileSpeed)) { result.HitChance = HitChance.High; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } return(result); } } //to do: find a fuking logic if (avgp < 400 && movt < 100 && path.PathLength() <= avgp) { result.HitChance = HitChance.High; result.CastPosition = path.Last(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); } } if (target.IsDashing()) //if unit is dashing { return(GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, type, from)); } if (Utility.IsImmobileTarget(target)) //if unit is immobile { return(GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, type, from)); } result = WaypointAnlysis(target, width, delay, missileSpeed, range, collisionable, type, path, avgt, movt, avgp, from); float d = result.CastPosition.Distance(target.ServerPosition.To2D()); if (d >= (avgt - movt) * target.MoveSpeed && d >= avgp) { result.HitChance = HitChance.Medium; } //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue <Slider>().Value) / 100f) { result.HitChance = HitChance.OutOfRange; } return(result); } finally { //check if movement changed while prediction calculations if (!target.GetWaypoints().SequenceEqual(path)) { result.HitChance = HitChance.Medium; } } }
/// <summary> /// Gets Prediction result while unit is dashing /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetDashingPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from) { Result result = new Result(); if (target.IsDashing()) { var dashInfo = target.GetDashInfo(); if (dashInfo.IsBlink) { result.HitChance = HitChance.Impossible; return(result); } //define hitboxes var dashHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(dashInfo.StartPos, dashInfo.EndPos + (dashInfo.EndPos - dashInfo.StartPos).Normalized() * 500, target.BoundingRadius * 2)); var myHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(from, from == ObjectManager.Player.ServerPosition.To2D() ? ObjectManager.Player.BoundingRadius : width)); if (ClipperWrapper.IsIntersects(myHitBox, dashHitBox)) { result.HitChance = HitChance.Dashing; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) { result.HitChance = HitChance.Collision; } return(result); } result.CastPosition = GetFastUnitPosition(target, dashInfo.Path, delay, missileSpeed, from, dashInfo.Speed); result.HitChance = HitChance.Dashing; //check range if (result.CastPosition.Distance(from) > range) { result.HitChance = HitChance.OutOfRange; } //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) { result.HitChance = HitChance.Collision; } } else { result.HitChance = HitChance.Impossible; } return(result); }
public Spells(SpellSlot Spellslot, SkillshotType Skillshottype, float Range, float Delay, float Radius, bool Collision, float Speed = 4000000, float ExtraRange = 0) { spellslot = Spellslot; delay = Delay; radius = Radius; speed = Speed; range = Range; extrarange = ExtraRange; collision = Collision; skillshottype = Skillshottype; MinHitChance = HitChances.VeryLow; }
/// <summary> /// Sets the Spell Data to Skill-shot data. /// </summary> /// <param name="collision"> /// Spell Collision Flag /// </param> /// <param name="type"> /// Skill-shot Type /// </param> /// <param name="fromVector3"> /// From Vector3 Source /// </param> /// <param name="rangeCheckFromVector3"> /// Range Check From Vector3 Source /// </param> /// <returns> /// The <see cref="Spell" />. /// </returns> public Spell SetSkillshot( bool collision, SkillshotType type, Vector3 fromVector3 = default(Vector3), Vector3 rangeCheckFromVector3 = default(Vector3)) { this.From = fromVector3; this.Collision = collision; this.Type = type; this.RangeCheckFrom = rangeCheckFromVector3; this.IsSkillshot = true; return this; }
/// <summary> /// Sets the Spell Data to Skill-shot data. /// </summary> /// <param name="delay"> /// Spell Delay /// </param> /// <param name="skillWidth"> /// Spell Width /// </param> /// <param name="speed"> /// Spell Speed /// </param> /// <param name="collision"> /// Spell Collision Flag /// </param> /// <param name="type"> /// Skill-shot Type /// </param> /// <param name="fromVector3"> /// From Vector3 Source /// </param> /// <param name="rangeCheckFromVector3"> /// Range Check From Vector3 Source /// </param> /// <returns> /// The <see cref="Spell" />. /// </returns> public Spell SetSkillshot( float delay, float skillWidth, float speed, bool collision, SkillshotType type, Vector3 fromVector3 = default(Vector3), Vector3 rangeCheckFromVector3 = default(Vector3)) { this.Delay = delay; this.Width = skillWidth; this.Speed = speed; this.From = fromVector3; this.Collision = collision; this.Type = type; this.RangeCheckFrom = rangeCheckFromVector3; this.IsSkillshot = true; return this; }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <param name="rangeCheckFrom"></param> /// <returns>Prediction result as <see cref="Prediction.Result" /></returns> internal static Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, Vector2 rangeCheckFrom) { Prediction.AssertInitializationMode(); Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; try { if (type == SkillshotType.SkillshotCircle) { range += width; } //to do: hook logic ? by storing average movement direction etc if (path.Count <= 1 && movt > 100 && (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick > 300 || !ConfigMenu.CheckAAWindUp)) //if target is not moving, easy to hit (and not aaing) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; result.Lock(); return(result); } if (target is AIHeroClient) { if (((AIHeroClient)target).IsChannelingImportantSpell()) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; result.Lock(); return(result); } if (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick < 300 && ConfigMenu.CheckAAWindUp) { if (target.AttackCastDelay * 1000 + PathTracker.EnemyInfo[target.NetworkId].AvgOrbwalkTime + avgt - width / 2f / target.MoveSpeed >= GetArrivalTime(target.ServerPosition.LSTo2D().LSDistance(from), delay, missileSpeed)) { result.HitChance = HitChance.High; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; result.Lock(); return(result); } } //to do: find a fuking logic if (avgp < 400 && movt < 100 && path.LSPathLength() <= avgp) { result.HitChance = HitChance.High; result.CastPosition = path.Last(); result.UnitPosition = result.CastPosition; result.Lock(); return(result); } } if (target.LSIsDashing()) //if unit is dashing { return(GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, type, from, rangeCheckFrom)); } if (Utility.IsImmobileTarget(target)) //if unit is immobile { return(GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, type, from, rangeCheckFrom)); } result = WaypointAnlysis(target, width, delay, missileSpeed, range, collisionable, type, path, avgt, movt, avgp, anglediff, from); float d = result.CastPosition.LSDistance(target.ServerPosition.LSTo2D()); if (d >= (avgt - movt) * target.MoveSpeed && d >= avgp) { result.HitChance = HitChance.Medium; } result.Lock(); return(result); } finally { //check if movement changed while prediction calculations if (!target.GetWaypoints().SequenceEqual(path)) { result.HitChance = HitChance.Medium; } } }
public void SetValues(float delay, float speed, float width, int minRange, int maxRange, string buffName, SkillshotType type) { Data.SetSkillshot(delay, width, speed, (colTable != null), type); Data.ChargedBuffName = buffName; Data.ChargedMinRange = minRange; Data.ChargedMaxRange = maxRange; Data.Range = (float)maxRange; }
/// <summary> /// Gets Prediction result while unit is immobile /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetImmobilePrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from, Vector2 rangeCheckFrom) { Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; //calculate spell arrival time float t = delay + Game.Ping / 2000f; if (missileSpeed != 0) { t += from.LSDistance(target.ServerPosition) / missileSpeed; } if (type == SkillshotType.SkillshotCircle) { t += width / target.MoveSpeed / 2f; } if (t >= Utility.LeftImmobileTime(target)) { result.HitChance = HitChance.Immobile; result.Lock(); return(result); } if (target is AIHeroClient) { result.HitChance = GetHitChance(t - Utility.LeftImmobileTime(target), ((AIHeroClient)target).AvgMovChangeTime(), 0, 0, 0); } else { result.HitChance = HitChance.High; } result.Lock(); return(result); }
public void SetValues(float delay, float speed, float width, float range, SkillshotType type) { Data.SetSkillshot(delay, width, speed, (colTable != null), type); Data.Range = range; }
/// <summary> /// Gets Prediction result while unit is dashing /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetDashingPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from, Vector2 rangeCheckFrom) { Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; if (target.IsDashing()) { var dashInfo = target.GetDashInfo(); if (dashInfo.IsBlink) { result.HitChance = HitChance.Impossible; result.CastPosition = dashInfo.EndPos; return result; } result.CastPosition = GetFastUnitPosition(target, dashInfo.Path, delay, missileSpeed, from, dashInfo.Speed); result.HitChance = HitChance.Dashing; result.Lock(false); } else { result = GetPrediction(target, width, delay, missileSpeed, range, collisionable, type, target.GetWaypoints(), 0, 0, 0, 0, from, rangeCheckFrom); result.Lock(false); } return result; }
public static List<Vector2> GetMinionsPredictedPositions(List<Obj_AI_Base> minions, float delay, float width, float speed, Vector3 from, float range, bool collision, SkillshotType stype, Vector3 rangeCheckFrom = new Vector3()) { from = from.To2D().IsValid() ? from : ObjectManager.Player.ServerPosition; return (from minion in minions select Prediction.GetPrediction( new PredictionInput { Unit = minion, Delay = delay, Radius = width, Speed = speed, From = @from, Range = range, Collision = collision, Type = stype, RangeCheckFrom = rangeCheckFrom }) into pos where pos.Hitchance >= HitChance.High select pos.UnitPosition.To2D()).ToList(); }
public Input(Obj_AI_Base _target, float delay, float speed, float radius, float range, bool collision, SkillshotType type, Vector3 _from, Vector3 _rangeCheckFrom) { Target = _target; SpellDelay = delay; SpellMissileSpeed = speed; SpellWidth = radius; SpellRange = range; SpellCollisionable = collision; SpellSkillShotType = type; Path = Target.GetWaypoints(); if (Target is AIHeroClient) { AIHeroClient t = Target as AIHeroClient; AvgReactionTime = t.AvgMovChangeTime(); LastMovChangeTime = t.LastMovChangeTime(); AvgPathLenght = t.AvgPathLenght(); LastAngleDiff = t.LastAngleDiff(); } else { AvgReactionTime = 0; LastMovChangeTime = 0; AvgPathLenght = 0; LastAngleDiff = 0; } From = _from; RangeCheckFrom = _rangeCheckFrom; }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) { moveSpeed = target.MoveSpeed; } var result = new Result { Unit = target }; var flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile { flyTimeMax = range / missileSpeed; } var tMin = delay + Game.Ping / 2000f + ConfigMenu.SpellDelay / 1000f; var tMax = flyTimeMax + delay + Game.Ping / 1000f + ConfigMenu.SpellDelay / 1000f; var pathTime = 0f; int[] pathBounds = { -1, -1 }; //find bounds for (var i = 0; i < path.Count - 1; i++) { var t = path[i + 1].Distance(path[i]) / moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) { pathBounds[0] = i; } if (pathTime <= tMax && pathTime + t >= tMax) { pathBounds[1] = i; } if (pathBounds[0] != -1 && pathBounds[1] != -1) { break; } pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (var k = pathBounds[0]; k <= pathBounds[1]; k++) { var direction = (path[k + 1] - path[k]).Normalized(); var distance = width; var extender = target.BoundingRadius; if (type == SkillshotType.SkillshotLine) { extender = width; } var steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance); //split & anlyse current path for (var i = 1; i < steps - 1; i++) { var pCenter = path[k] + direction * distance * i; var pA = pCenter - direction * extender; var pB = pCenter + direction * extender; var flytime = missileSpeed != 0 ? from.Distance(pCenter) / missileSpeed : 0f; var t = flytime + delay + Game.Ping / 2000f + ConfigMenu.SpellDelay / 1000f; var currentPosition = target.ServerPosition.To2D(); var arriveTimeA = currentPosition.Distance(pA) / moveSpeed; var arriveTimeB = currentPosition.Distance(pB) / moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp, anglediff); result.CastPosition = pCenter; result.UnitPosition = pCenter; //+ (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); /*if (currentPosition.IsBetween(ObjectManager.Player.ServerPosition.To2D(), result.CastPosition)) * { * result.CastPosition = currentPosition; * Console.WriteLine("corrected"); * }*/ return(result); } } } } result.HitChance = HitChance.Impossible; result.CastPosition = target.ServerPosition.To2D(); return(result); }
internal static PredictionOutput GetPositionOnPath(PredictionInput input, List <Vector2> path, float speed = -1f) { speed = ((Math.Abs(speed - -1f) < float.Epsilon) ? input.Unit.MoveSpeed : speed); if (path.Count <= 1) { return(new PredictionOutput { Input = input, UnitPosition = input.Unit.Position, CastPosition = input.Unit.Position, Hitchance = HitChance.VeryHigh }); } float num = path.PathLength(); if (num >= input.Delay * speed - input.RealRadius && Math.Abs(input.Speed - 3.40282347E+38f) < 1.401298E-45f) { float num2 = input.Delay * speed - input.RealRadius; for (int i = 0; i < path.Count - 1; i++) { Vector2 vector = path[i]; Vector2 vector2 = path[i + 1]; float num3 = vector.Distance(vector2); if (num3 >= num2) { Vector2 value = (vector2 - vector).Normalized(); Vector2 v = vector + value * num2; Vector2 v2 = vector + value * ((i == path.Count - 2) ? Math.Min(num2 + input.RealRadius, num3) : (num2 + input.RealRadius)); return(new PredictionOutput { Input = input, CastPosition = v.ToVector3(), UnitPosition = v2.ToVector3(), Hitchance = (HitChance.High) }); } num2 -= num3; } } if (num >= input.Delay * speed - input.RealRadius && Math.Abs(input.Speed - 3.40282347E+38f) > 1.401298E-45f) { float distance = input.Delay * speed - input.RealRadius; if ((input.Type == SkillshotType.SkillshotLine || input.Type == SkillshotType.SkillshotCone) && input.From.DistanceSquared(input.Unit.Position) < 40000f) { distance = input.Delay * speed; } path = path.CutPath(distance); float num4 = 0f; int j = 0; while (j < path.Count - 1) { Vector2 vector3 = path[j]; Vector2 vector4 = path[j + 1]; float num5 = vector3.Distance(vector4) / speed; Vector2 value2 = (vector4 - vector3).Normalized(); vector3 -= speed * num4 * value2; object[] array = VectorMovementCollision(vector3, vector4, speed, input.From.ToVector2(), input.Speed, num4); float num6 = (float)array[0]; Vector2 vector5 = (Vector2)array[1]; if (vector5.IsValid() && num6 >= num4 && num6 <= num4 + num5) { if (vector5.DistanceSquared(vector4) >= 20f) { Vector2 v3 = vector5 + input.RealRadius * value2; SkillshotType type = input.Type; return(new PredictionOutput { Input = input, CastPosition = vector5.ToVector3(), UnitPosition = v3.ToVector3(), Hitchance = (HitChance.High) }); } break; } else { num4 += num5; j++; } } } Vector2 v4 = path.Last <Vector2>(); return(new PredictionOutput { Input = input, CastPosition = v4.ToVector3(), UnitPosition = v4.ToVector3(), Hitchance = HitChance.Medium }); }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns>Prediction result as <see cref="Prediction.Result"/></returns> internal static Result GetPrediction(Obj_AI_Hero target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type) { return GetPrediction(target, width, delay, missileSpeed, range, collisionable, type, target.GetWaypoints(), target.AvgMovChangeTime(), target.LastMovChangeTime(), target.AvgPathLenght(), ObjectManager.Player.ServerPosition.To2D(), ObjectManager.Player.ServerPosition.To2D()); }
public void SetSkillshot(float delay, float width, float speed, bool collision, SkillshotType type, Vector3 from = new Vector3(), Vector3 rangeCheckFrom = new Vector3()) { Delay = delay; Width = width; Speed = speed; From = from; Collision = collision; Type = type; RangeCheckFrom = rangeCheckFrom; IsSkillshot = true; }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <param name="rangeCheckFrom"></param> /// <returns>Prediction result as <see cref="Prediction.Result"/></returns> internal static Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List<Vector2> path, float avgt, float movt, float avgp, Vector2 from, Vector2 rangeCheckFrom) { Prediction.AssertInitializationMode(); Result result = new Result(); try { if (type == SkillshotType.SkillshotCircle) range += width; //to do: hook logic ? by storing average movement direction etc if (path.Count <= 1 && movt > 100 && (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick > 300 || !predMenu.Item("SPREDWINDUP").GetValue<bool>())) //if target is not moving, easy to hit (and not aaing) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; } if (target is Obj_AI_Hero) { if (((Obj_AI_Hero)target).IsChannelingImportantSpell()) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; } if (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick < 300 && predMenu.Item("SPREDWINDUP").GetValue<bool>()) { if (target.AttackCastDelay * 1000 + PathTracker.EnemyInfo[target.NetworkId].AvgOrbwalkTime + avgt - width / 2f / target.MoveSpeed >= GetArrivalTime(target.ServerPosition.To2D().Distance(from), delay, missileSpeed)) { result.HitChance = HitChance.High; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; return result; } } //to do: find a fuking logic if (avgp < 400 && movt < 100 && path.PathLength() <= avgp) { result.HitChance = HitChance.High; result.CastPosition = path.Last(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; } } if (target.IsDashing()) //if unit is dashing return GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, type, from); if (Utility.IsImmobileTarget(target)) //if unit is immobile return GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, type, from); result = WaypointAnlysis(target, width, delay, missileSpeed, range, collisionable, type, path, avgt, movt, avgp, from); //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; //check if target can dodge with moving backward if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; } finally { //check if movement changed while prediction calculations if (!target.GetWaypoints().SequenceEqual(path)) result.HitChance = HitChance.Medium; } }
public static void CastPrediction(this Spell spell, AIHeroClient target, int menuValue, int hitCount) { if (!spell.IsReady() || !target.IsValidEntity(spell.Range)) { return; } /* TODO: MEH */ if (!target.CanMove) { spell.Cast(target.ServerPosition); return; } HitChance hitchance = HitChance.High; switch (menuValue) { case 0: hitchance = HitChance.VeryHigh; break; case 1: hitchance = HitChance.High; break; case 2: hitchance = HitChance.Medium; break; default: throw new Exception("damm you f****d it up"); } SkillshotType skillshotType = SkillshotType.SkillshotLine; bool isAoe = false; if (spell.Type == SkillshotType.SkillshotCircle) { skillshotType = SkillshotType.SkillshotCircle; isAoe = true; } if (spell.Width > 80 && !spell.Collision) { isAoe = true; } PredictionInput predictionInput = new PredictionInput { Aoe = isAoe, Collision = spell.Collision, Speed = spell.Speed, Delay = spell.Delay, Range = spell.Range, From = ObjectManager.Me.ServerPosition, Radius = spell.Width, Unit = target, Type = skillshotType }; PredictionOutput getPrediction = new Prediction().GetPrediction(predictionInput, true, true); if (isAoe && getPrediction.Hitchance >= hitchance && getPrediction.AoeTargetsHitCount >= hitCount) { spell.Cast(getPrediction.CastPosition); } else if (getPrediction.Hitchance >= hitchance) { spell.Cast(getPrediction.CastPosition); } }
/// <summary> /// Gets Prediction result while unit is dashing /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetDashingPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from) { Result result = new Result(); if (target.IsDashing()) { var dashInfo = target.GetDashInfo(); if (dashInfo.IsBlink) { result.HitChance = HitChance.Impossible; return result; } //define hitboxes var dashHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(dashInfo.StartPos, dashInfo.EndPos + (dashInfo.EndPos - dashInfo.StartPos).Normalized() * 500, target.BoundingRadius * 2)); var myHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(from, from == ObjectManager.Player.ServerPosition.To2D() ? ObjectManager.Player.BoundingRadius : width)); if (ClipperWrapper.IsIntersects(myHitBox, dashHitBox)) { result.HitChance = HitChance.Dashing; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); //check collisions if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) result.HitChance = HitChance.Collision; return result; } result.CastPosition = GetFastUnitPosition(target, dashInfo.Path, delay, missileSpeed, from, dashInfo.Speed); result.HitChance = HitChance.Dashing; //check range if (result.CastPosition.Distance(from) > range) result.HitChance = HitChance.OutOfRange; //check collisions if (collisionable && (result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions) || result.CollisionResult.Objects.HasFlag(Collision.Flags.YasuoWall))) result.HitChance = HitChance.Collision; } else result.HitChance = HitChance.Impossible; return result; }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List<Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) moveSpeed = target.MoveSpeed; var result = new Result {Unit = target}; var flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile flyTimeMax = range/missileSpeed; var tMin = delay + Game.Ping/2000f + ConfigMenu.SpellDelay/1000f; var tMax = flyTimeMax + delay + Game.Ping/1000f + ConfigMenu.SpellDelay/1000f; var pathTime = 0f; int[] pathBounds = {-1, -1}; //find bounds for (var i = 0; i < path.Count - 1; i++) { var t = path[i + 1].LSDistance(path[i])/moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) pathBounds[0] = i; if (pathTime <= tMax && pathTime + t >= tMax) pathBounds[1] = i; if (pathBounds[0] != -1 && pathBounds[1] != -1) break; pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (var k = pathBounds[0]; k <= pathBounds[1]; k++) { var direction = (path[k + 1] - path[k]).LSNormalized(); var distance = width; var extender = target.BoundingRadius; if (type == SkillshotType.SkillshotLine) extender = width; var steps = (int) Math.Floor(path[k].LSDistance(path[k + 1])/distance); //split & anlyse current path for (var i = 1; i < steps - 1; i++) { var pCenter = path[k] + direction*distance*i; var pA = pCenter - direction*extender; var pB = pCenter + direction*extender; var flytime = missileSpeed != 0 ? from.LSDistance(pCenter)/missileSpeed : 0f; var t = flytime + delay + Game.Ping/2000f + ConfigMenu.SpellDelay/1000f; var currentPosition = target.ServerPosition.LSTo2D(); var arriveTimeA = currentPosition.LSDistance(pA)/moveSpeed; var arriveTimeB = currentPosition.LSDistance(pB)/moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp, anglediff); result.CastPosition = pCenter; result.UnitPosition = pCenter; //+ (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); return result; } } } } result.HitChance = HitChance.Impossible; result.CastPosition = target.ServerPosition.LSTo2D(); return result; }
/// <summary> /// Gets Prediction result while unit is immobile /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetImmobilePrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from) { Result result = new Result(); result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; //calculate spell arrival time float t = delay + Game.Ping / 2000f; if (missileSpeed != 0) t += from.Distance(target.ServerPosition) / missileSpeed; if (type == SkillshotType.SkillshotCircle) t += width / target.MoveSpeed / 2f; if (t >= Utility.LeftImmobileTime(target)) { result.HitChance = HitChance.Immobile; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) result.HitChance = HitChance.Collision; if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; } if (target is Obj_AI_Hero) result.HitChance = GetHitChance(t - Utility.LeftImmobileTime(target), ((Obj_AI_Hero)target).AvgMovChangeTime(), 0, 0); else result.HitChance = HitChance.High; //check collisions if (collisionable && result.CollisionResult.Objects.HasFlag(Collision.Flags.Minions)) result.HitChance = HitChance.Collision; //check range if (from.Distance(result.CastPosition) > range - GetArrivalTime(from.Distance(result.CastPosition), delay, missileSpeed) * target.MoveSpeed * (100 - predMenu.Item("SPREDMAXRANGEIGNORE").GetValue<Slider>().Value) / 100f) result.HitChance = HitChance.OutOfRange; return result; }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns>Prediction result as <see cref="Prediction.Result" /></returns> internal static Result GetPrediction(AIHeroClient target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type) { return(GetPrediction(target, width, delay, missileSpeed, range, collisionable, type, target.GetWaypoints(), target.AvgMovChangeTime(), target.LastMovChangeTime(), target.AvgPathLenght(), target.LastAngleDiff(), ObjectManager.Player.ServerPosition.LSTo2D(), ObjectManager.Player.ServerPosition.LSTo2D())); }
/// <summary> /// Gets Prediction result while unit is immobile /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetImmobilePrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from, Vector2 rangeCheckFrom) { Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; //calculate spell arrival time float t = delay + Game.Ping / 2000f; if (missileSpeed != 0) t += from.Distance(target.ServerPosition) / missileSpeed; if (type == SkillshotType.SkillshotCircle) t += width / target.MoveSpeed / 2f; if (t >= Utility.LeftImmobileTime(target)) { result.HitChance = HitChance.Immobile; result.Lock(); return result; } if (target is Obj_AI_Hero) result.HitChance = GetHitChance(t - Utility.LeftImmobileTime(target), ((Obj_AI_Hero)target).AvgMovChangeTime(), 0, 0, 0); else result.HitChance = HitChance.High; result.Lock(); return result; }
/// <summary> /// Gets Prediction result while unit is dashing /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> /// <summary> /// Gets Prediction result while unit is dashing /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result GetDashingPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, Vector2 from, Vector2 rangeCheckFrom) { Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; if (target.LSIsDashing()) { var dashInfo = target.LSGetDashInfo(); if (dashInfo.IsBlink) { result.HitChance = HitChance.Impossible; result.CastPosition = dashInfo.EndPos; return(result); } result.CastPosition = GetFastUnitPosition(target, dashInfo.Path, delay, missileSpeed, from, dashInfo.Speed); result.HitChance = HitChance.Dashing; result.Lock(false); } else { result = GetPrediction(target, width, delay, missileSpeed, range, collisionable, type, target.GetWaypoints(), 0, 0, 0, 0, from, rangeCheckFrom); result.Lock(false); } return(result); }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List<Vector2> path, float avgt, float movt, float avgp, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) moveSpeed = target.MoveSpeed; Result result = new Result(); float flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile flyTimeMax = range / missileSpeed; float tMin = delay + Game.Ping / 2000f + SpellDelay / 1000f; float tMax = flyTimeMax + delay + Game.Ping / 1000f + SpellDelay / 1000f; float pathTime = 0f; int[] pathBounds = new int[] { -1, -1 }; //find bounds for (int i = 0; i < path.Count - 1; i++) { float t = path[i + 1].Distance(path[i]) / moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) pathBounds[0] = i; if (pathTime <= tMax && pathTime + t >= tMax) pathBounds[1] = i; if (pathBounds[0] != -1 && pathBounds[1] != -1) break; pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (int k = pathBounds[0]; k <= pathBounds[1]; k++) { Vector2 direction = (path[k + 1] - path[k]).Normalized(); float distance = width; if (predMenu.Item("SPREDWPANALYSIS").GetValue<StringList>().SelectedIndex == 0) distance = target.BoundingRadius; int steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance); //split & anlyse current path for (int i = 0; i < steps; i++) { Vector2 pA = path[k] + (direction * distance * i); Vector2 pB = path[k] + (direction * distance * (i + 1)); Vector2 center = (pA + pB) / 2f; float flytime = missileSpeed != 0 ? from.Distance(center) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 1000f + SpellDelay / 1000f; Vector2 currentPosition = isDash ? target.Position.To2D() : target.ServerPosition.To2D(); float arriveTimeA = currentPosition.Distance(pA) / moveSpeed; float arriveTimeB = currentPosition.Distance(pB) / moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp); result.CastPosition = center; result.UnitPosition = center + (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); return result; } } if (steps == 0) { float flytime = missileSpeed != 0 ? from.Distance(path[pathBounds[1]]) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 2000f + SpellDelay / 1000f; result.HitChance = GetHitChance(t, avgt, movt, avgp); result.CastPosition = path[pathBounds[1]]; result.UnitPosition = path[pathBounds[1]]; result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); return result; } } } result.HitChance = HitChance.Impossible; return result; }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List <Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) { moveSpeed = target.MoveSpeed; } Result result = new Result(); result.Unit = target; float flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile { flyTimeMax = range / missileSpeed; } float tMin = delay + Game.Ping / 2000f + ConfigMenu.SpellDelay / 1000f; float tMax = flyTimeMax + delay + Game.Ping / 1000f + ConfigMenu.SpellDelay / 1000f; float pathTime = 0f; int[] pathBounds = new int[] { -1, -1 }; //find bounds for (int i = 0; i < path.Count - 1; i++) { float t = path[i + 1].LSDistance(path[i]) / moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) { pathBounds[0] = i; } if (pathTime <= tMax && pathTime + t >= tMax) { pathBounds[1] = i; } if (pathBounds[0] != -1 && pathBounds[1] != -1) { break; } pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (int k = pathBounds[0]; k <= pathBounds[1]; k++) { Vector2 direction = (path[k + 1] - path[k]).LSNormalized(); float distance = width; float extender = target.BoundingRadius; if (type == SkillshotType.SkillshotLine) { extender = width; } int steps = (int)Math.Floor(path[k].LSDistance(path[k + 1]) / distance); //split & anlyse current path for (int i = 1; i < steps - 1; i++) { Vector2 pCenter = path[k] + (direction * distance * i); Vector2 pA = pCenter - (direction * extender); Vector2 pB = pCenter + (direction * extender); float flytime = missileSpeed != 0 ? from.LSDistance(pCenter) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 2000f + ConfigMenu.SpellDelay / 1000f; Vector2 currentPosition = target.ServerPosition.LSTo2D(); float arriveTimeA = currentPosition.LSDistance(pA) / moveSpeed; float arriveTimeB = currentPosition.LSDistance(pB) / moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp, anglediff); result.CastPosition = pCenter; result.UnitPosition = pCenter; //+ (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); return(result); } } } } result.HitChance = HitChance.Impossible; result.CastPosition = target.ServerPosition.LSTo2D(); return(result); }
/// <summary> /// Gets Prediction result /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <param name="rangeCheckFrom"></param> /// <returns>Prediction result as <see cref="Prediction.Result"/></returns> internal static Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List<Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, Vector2 rangeCheckFrom) { Prediction.AssertInitializationMode(); Result result = new Result(); result.Input = new Input(target, delay, missileSpeed, width, range, collisionable, type, from.To3D2(), rangeCheckFrom.To3D2()); result.Unit = target; try { if (type == SkillshotType.SkillshotCircle) range += width; //to do: hook logic ? by storing average movement direction etc if (path.Count <= 1 && movt > 100 && (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick > 300 || !ConfigMenu.CheckAAWindUp)) //if target is not moving, easy to hit (and not aaing) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.Lock(); return result; } if (target is Obj_AI_Hero) { if (((Obj_AI_Hero)target).IsChannelingImportantSpell()) { result.HitChance = HitChance.VeryHigh; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.Lock(); return result; } if (Environment.TickCount - PathTracker.EnemyInfo[target.NetworkId].LastAATick < 300 && ConfigMenu.CheckAAWindUp) { if (target.AttackCastDelay * 1000 + PathTracker.EnemyInfo[target.NetworkId].AvgOrbwalkTime + avgt - width / 2f / target.MoveSpeed >= GetArrivalTime(target.ServerPosition.To2D().Distance(from), delay, missileSpeed)) { result.HitChance = HitChance.High; result.CastPosition = target.ServerPosition.To2D(); result.UnitPosition = result.CastPosition; result.Lock(); return result; } } //to do: find a fuking logic if (avgp < 400 && movt < 100 && path.PathLength() <= avgp) { result.HitChance = HitChance.High; result.CastPosition = path.Last(); result.UnitPosition = result.CastPosition; result.Lock(); return result; } } if (target.IsDashing()) //if unit is dashing return GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, type, from, rangeCheckFrom); if (Utility.IsImmobileTarget(target)) //if unit is immobile return GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, type, from, rangeCheckFrom); result = WaypointAnlysis(target, width, delay, missileSpeed, range, collisionable, type, path, avgt, movt, avgp, anglediff, from); float d = result.CastPosition.Distance(target.ServerPosition.To2D()); if (d >= (avgt - movt) * target.MoveSpeed && d >= avgp) result.HitChance = HitChance.Medium; result.Lock(); return result; } finally { //check if movement changed while prediction calculations if (!target.GetWaypoints().SequenceEqual(path)) result.HitChance = HitChance.Medium; } }
/// <summary> /// Calculates cast position with target's path /// </summary> /// <param name="target">Target for spell</param> /// <param name="width">Spell width</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="range">Spell range</param> /// <param name="collisionable">Spell collisionable</param> /// <param name="type">Spell skillshot type</param> /// <param name="path">Waypoints of target</param> /// <param name="avgt">Average reaction time (in ms)</param> /// <param name="movt">Passed time from last movement change (in ms)</param> /// <param name="avgp">Average Path Lenght</param> /// <param name="from">Spell casted position</param> /// <returns></returns> internal static Result WaypointAnlysis(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, SkillshotType type, List<Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, float moveSpeed = 0, bool isDash = false) { if (moveSpeed == 0) moveSpeed = target.MoveSpeed; Result result = new Result(); float flyTimeMax = 0f; if (missileSpeed != 0) //skillshot with a missile flyTimeMax = range / missileSpeed; float tMin = delay + Game.Ping / 2000f + SpellDelay / 1000f; float tMax = flyTimeMax + delay + Game.Ping / 1000f + SpellDelay / 1000f; float pathTime = 0f; int[] pathBounds = new int[] { -1, -1 }; //find bounds for (int i = 0; i < path.Count - 1; i++) { float t = path[i + 1].Distance(path[i]) / moveSpeed; if (pathTime <= tMin && pathTime + t >= tMin) pathBounds[0] = i; if (pathTime <= tMax && pathTime + t >= tMax) pathBounds[1] = i; if (pathBounds[0] != -1 && pathBounds[1] != -1) break; pathTime += t; } //calculate cast & unit position if (pathBounds[0] != -1 && pathBounds[1] != -1) { for (int k = pathBounds[0]; k <= pathBounds[1]; k++) { Vector2 direction = (path[k + 1] - path[k]).Normalized(); float distance = width; float extender = target.BoundingRadius; if (type == SkillshotType.SkillshotLine) extender = width; int steps = (int)Math.Floor(path[k].Distance(path[k + 1]) / distance); //split & anlyse current path for (int i = 1; i < steps - 1; i++) { Vector2 pCenter = path[k] + (direction * distance * i); Vector2 pA = pCenter - (direction * extender); Vector2 pB = pCenter + (direction * extender); float flytime = missileSpeed != 0 ? from.Distance(pCenter) / missileSpeed : 0f; float t = flytime + delay + Game.Ping / 2000f + SpellDelay / 1000f; Vector2 currentPosition = target.ServerPosition.To2D(); float arriveTimeA = currentPosition.Distance(pA) / moveSpeed; float arriveTimeB = currentPosition.Distance(pB) / moveSpeed; if (Math.Min(arriveTimeA, arriveTimeB) <= t && Math.Max(arriveTimeA, arriveTimeB) >= t) { result.HitChance = GetHitChance(t, avgt, movt, avgp, anglediff); result.CastPosition = pCenter; result.UnitPosition = pCenter; //+ (direction * (t - Math.Min(arriveTimeA, arriveTimeB)) * moveSpeed); /*if (currentPosition.IsBetween(ObjectManager.Player.ServerPosition.To2D(), result.CastPosition)) { result.CastPosition = currentPosition; Console.WriteLine("corrected"); }*/ result.CollisionResult = Collision.GetCollisions(from, result.CastPosition, width, delay, missileSpeed); return result; } } } } result.HitChance = HitChance.Impossible; return result; }
private static LeagueSharp.Common.SkillshotType ConvertSkillShotType(CCChainer.Data.SkillShotType Type) { var result = new SkillshotType(); switch (Type) { case SkillShotType.SkillshotCircle: result = SkillshotType.SkillshotCircle; break; case SkillShotType.SkillshotMissileLine: case SkillShotType.SkillshotLine: result = SkillshotType.SkillshotLine; break; case SkillShotType.SkillshotMissileCone: case SkillShotType.SkillshotCone: result = SkillshotType.SkillshotCone; break; } return result; }