public static double BadaoAngleBetween(Vector2 a, Vector2 center, Vector2 c) { float a1 = c.LSDistance(center); float b1 = a.LSDistance(c); float c1 = center.LSDistance(a); if (a1 == 0 || c1 == 0) { return 0; } else { return Math.Acos((a1 * a1 + c1 * c1 - b1 * b1) / (2 * a1 * c1)) * (180 / Math.PI); } }
/// <summary> /// Gets Aoe Prediction result /// </summary> /// <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="from">Spell casted position</param> /// <param name="rangeCheckFrom"></param> /// <returns>Prediction result as <see cref="Prediction.AoeResult" /></returns> public static Prediction.AoeResult GetAoePrediction(float width, float delay, float missileSpeed, float range, Vector2 from, Vector2 rangeCheckFrom) { var result = new Prediction.AoeResult {HitCount = 0}; var enemies = HeroManager.Enemies.Where( p => p.LSIsValidTarget() && Prediction.GetFastUnitPosition(p, delay, 0, from).LSDistance(rangeCheckFrom) < range); if (enemies.Count() > 0) { var posSummary = Vector2.Zero; enemies.AsParallel() .ForAll(p => posSummary += Prediction.GetFastUnitPosition(p, delay, missileSpeed, from)); var center = posSummary/enemies.Count(); float flyTime = 0; if (missileSpeed != 0) flyTime = from.LSDistance(center)/missileSpeed; posSummary = Vector2.Zero; var predictionResults = new List<Tuple<Prediction.Result, float>>(); foreach (var enemy in enemies) { var prediction = GetPrediction(enemy, width, delay + flyTime, 0, range, false, enemy.GetWaypoints(), enemy.AvgMovChangeTime(), enemy.LastMovChangeTime(), enemy.AvgPathLenght(), enemy.LastAngleDiff(), from, rangeCheckFrom); if (prediction.HitChance > EloBuddy.SDK.Enumerations.HitChance.Medium) { posSummary += prediction.UnitPosition; predictionResults.Add(new Tuple<Prediction.Result, float>(prediction, enemy.BoundingRadius)); } } if (predictionResults.Count > 0) { center = posSummary/predictionResults.Count; result.CastPosition = center; foreach (var res in predictionResults) { if ( LeagueSharp.Common.Geometry.CircleCircleIntersection(center, res.Item1.UnitPosition, width, res.Item2).Length > 1) result.HitCount++; } } predictionResults.Clear(); GC.Collect(GC.GetGeneration(predictionResults)); } return result; }
public static Vector2? GetFirstWallPoint(Vector2 from, Vector2 to, float step = 25) { var direction = (to - from).Normalized(); for (float d = 0; d < from.LSDistance(to); d = d + step) { var testPoint = from + d * direction; var flags = NavMesh.GetCollisionFlags(testPoint.X, testPoint.Y); if (flags.HasFlag(CollisionFlags.Wall) || flags.HasFlag(CollisionFlags.Building)) { return from + (d - step) * direction; } } return null; }
public static bool CanReach(Vector2 start, Vector2 end, List<Geometry.Polygon> polygons, bool checkWalls = false) { if (start == end) { return false; } //TODO Disable if the distance to the start position is high if (checkWalls) { var nPoints = 2; var step = start.LSDistance(end) / nPoints; var direction = (end - start).LSNormalized(); for (int i = 0; i <= nPoints; i++) { var p = start + i * step * direction; if (p.LSIsWall()) { return false; } } } foreach (var polygon in polygons) { for (int i = 0; i < polygon.Points.Count; i++) { var a = polygon.Points[i]; var b = polygon.Points[i == polygon.Points.Count - 1 ? 0 : i + 1]; if (EvadeA.Utils.LineSegmentsCross(start, end, a, b)) { return false; } } } return true; }
public static FastPredResult FastPrediction(Vector2 from, Obj_AI_Base unit, int delay, int speed) { var tDelay = delay / 1000f + (from.LSDistance(unit) / speed); var d = tDelay * unit.MoveSpeed; var path = unit.GetWaypoints(); if (path.LSPathLength() > d) { return new FastPredResult { IsMoving = true, CurrentPos = unit.ServerPosition.LSTo2D(), PredictedPos = path.CutPath((int) d)[0], }; } return new FastPredResult { IsMoving = false, CurrentPos = path[path.Count - 1], PredictedPos = path[path.Count - 1], }; }
public static FastPredictionResult FastPrediction(Vector2 fromVector2, Obj_AI_Base unitAiBase, int delay, int speed) { var tickDelay = delay / 1000f + (fromVector2.LSDistance(unitAiBase) / speed); var moveSpeedF = tickDelay * unitAiBase.MoveSpeed; var path = unitAiBase.GetWaypoints(); if (path.PathLength() > moveSpeedF) { return new FastPredictionResult { IsMoving = true, CurrentPosVector2 = unitAiBase.ServerPosition.LSTo2D(), PredictedPosVector2 = path.CutPath((int) moveSpeedF)[0] }; } if (path.Count == 0) { return new FastPredictionResult { IsMoving = false, CurrentPosVector2 = unitAiBase.ServerPosition.LSTo2D(), PredictedPosVector2 = unitAiBase.ServerPosition.LSTo2D() }; } return new FastPredictionResult { IsMoving = false, CurrentPosVector2 = path[path.Count - 1], PredictedPosVector2 = path[path.Count - 1] }; }
public static bool PointInLineSegment(Vector2 segmentStart, Vector2 segmentEnd, Vector2 point) { var distanceStartEnd = segmentStart.LSDistance(segmentEnd, true); var distanceStartPoint = segmentStart.LSDistance(point, true); var distanceEndPoint = segmentEnd.LSDistance(point, true); return !(distanceEndPoint > distanceStartEnd || distanceStartPoint > distanceStartEnd); }
/// <summary> /// Checks enemy hero collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <param name="isArc">Checks collision for arc spell</param> /// <returns>true if collision found</returns> public static bool CheckAllyHeroCollision(Vector2 from, Vector2 to, float width, float delay, float missileSpeed = 0, bool isArc = false) { var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to, width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new SPrediction.Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 200 * (to.LSDistance(from) / 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 320 * (to.LSDistance(from) / 900)))); } return HeroManager.Allies.AsParallel().Any(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); }
/// <summary> /// Checks if the point is between 2 points /// </summary> /// <param name="b">The point to check.</param> /// <param name="a">The other point 1.</param> /// <param name="c">The other point 2.</param> /// <returns><c>true</c> if the point is between given 2 points</returns> internal static bool IsBetween(this Vector2 b, Vector2 a, Vector2 c) { return a.LSDistance(c) + c.LSDistance(b) - a.LSDistance(b) < float.Epsilon; }
public static float GetMovementBlockPositionValue(Vector2 pos, Vector2 movePos) { float value = 0;// pos.LSDistance(movePos); foreach (KeyValuePair<int, Spell> entry in SpellDetector.spells) { Spell spell = entry.Value; var spellPos = spell.GetCurrentSpellPosition(true, ObjectCache.gamePing); var extraDist = 100 + spell.radius; value -= Math.Max(0, -(10 * ((float)0.8 * extraDist) / pos.LSDistance(spell.GetSpellProjection(pos))) + extraDist); } return value; }
/// <summary> /// Gets collided units & flags /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="delay">Spell delay</param> /// <param name="missileSpeed">Spell missile speed</param> /// <returns>Collision result as <see cref="Collision.Result"/></returns> public static Result GetCollisions(Vector2 from, Vector2 to, float range, float width, float delay, float missileSpeed = 0, bool isArc = false) { List<Obj_AI_Base> collidedUnits = new List<Obj_AI_Base>(); var spellHitBox = ClipperWrapper.MakePaths(ClipperWrapper.DefineRectangle(from, to.LSExtend(from, -width), width)); if (isArc) { spellHitBox = ClipperWrapper.MakePaths(new SPrediction.Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 200 * (to.LSDistance(from) / 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 320 * (to.LSDistance(from) / 900)))); } Flags _colFlags = Flags.None; var collidedMinions = MinionManager.GetMinions(range + 100, MinionTypes.All, MinionTeam.NotAlly, MinionOrderTypes.None).AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius + 15)), spellHitBox)); var collidedEnemies = HeroManager.Enemies.AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); var collidedAllies = HeroManager.Allies.AsParallel().Where(p => ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(ClipperWrapper.DefineCircle(Prediction.GetFastUnitPosition(p, delay, missileSpeed), p.BoundingRadius)), spellHitBox)); if (collidedMinions != null && collidedMinions.Count() != 0) { collidedUnits.AddRange(collidedMinions); _colFlags |= Flags.Minions; } if (collidedEnemies != null && collidedEnemies.Count() != 0) { collidedUnits.AddRange(collidedEnemies); _colFlags |= Flags.EnemyChampions; } if (collidedAllies != null && collidedAllies.Count() != 0) { collidedUnits.AddRange(collidedAllies); _colFlags |= Flags.AllyChampions; } if (CheckWallCollision(from, to)) _colFlags |= Flags.Wall; if (CheckYasuoWallCollision(from, to, width)) _colFlags |= Flags.YasuoWall; return new Result(collidedUnits, _colFlags); }
public Arc(Vector2 start, Vector2 end, int hitbox) { Start = start; End = end; HitBox = hitbox; Distance = Start.LSDistance(End); }
public static bool CheckPathCollision(Obj_AI_Base unit, Vector2 movePos) { var path = unit.GetPath(ObjectCache.myHeroCache.serverPos2D.To3D(), movePos.To3D()); if (path.Length > 0) { if (movePos.LSDistance(path[path.Length - 1].LSTo2D()) > 5 || path.Length > 2) { return true; } } return false; }
public static void gapCloseE(Vector2 pos, List<AIHeroClient> ignore = null) { if (!E.IsReady()) return; Vector2 pPos = Player.ServerPosition.LSTo2D(); Obj_AI_Base bestEnem = null; float distToPos = Player.LSDistance(pos); if (((distToPos < Q.Range)) && goesThroughWall(pos.To3D(), Player.Position)) return; Vector2 bestLoc = pPos + (Vector2.Normalize(pos - pPos) * (Player.MoveSpeed * 0.35f)); float bestDist = pos.LSDistance(pPos) - 50; try { foreach (Obj_AI_Base enemy in ObjectManager.Get<Obj_AI_Base>().Where(ob => enemyIsJumpable(ob, ignore))) { float trueRange = E.Range + enemy.BoundingRadius; float distToEnem = Player.LSDistance(enemy); if (distToEnem < trueRange && distToEnem > 15) { Vector2 posAfterE = pPos + (Vector2.Normalize(enemy.Position.LSTo2D() - pPos) * E.Range); float distE = pos.LSDistance(posAfterE); if (distE < bestDist) { bestLoc = posAfterE; bestDist = distE; bestEnem = enemy; // Console.WriteLine("Gap to best enem"); } } } } catch (Exception ex) { Console.WriteLine(ex); } if (bestEnem != null) { Console.WriteLine("should use gap"); useENormal(bestEnem); } }
private static void Game_OnOnGameUpdate(EventArgs args) { PlayerPosition = ObjectManager.Player.ServerPosition.LSTo2D(); //Set evading to false after blinking if (PreviousTickPosition.IsValid() && PlayerPosition.LSDistance(PreviousTickPosition) > 200) { Evading = false; } PreviousTickPosition = PlayerPosition; //Remove the detected skillshots that have expired. DetectedSkillshots.RemoveAll(skillshot => !skillshot.IsActive()); //Trigger OnGameUpdate on each skillshot. foreach (var skillshot in DetectedSkillshots) { skillshot.Game_OnGameUpdate(); } //Evading disabled if (!getKeyBindItem(Config.Menu, "Enabled")) { Evading = false; EvadeToPoint = Vector2.Zero; PathFollower.Stop(); return; } if (PlayerChampionName == "Olaf" && getCheckBoxItem(Config.misc, "DisableEvadeForOlafR") && ObjectManager.Player.HasBuff("OlafRagnarok")) { Evading = false; EvadeToPoint = Vector2.Zero; PathFollower.Stop(); return; } //Avoid sending move/cast packets while dead. if (ObjectManager.Player.IsDead) { Evading = false; EvadeToPoint = Vector2.Zero; PathFollower.Stop(); return; } //Avoid sending move/cast packets while channeling interruptable spells that cause hero not being able to move. if (ObjectManager.Player.IsCastingInterruptableSpell(true)) { Evading = false; EvadeToPoint = Vector2.Zero; PathFollower.Stop(); return; } if (ObjectManager.Player.Spellbook.IsAutoAttacking && !Orbwalking.IsAutoAttack(ObjectManager.Player.LastCastedSpellName())) { Evading = false; return; } /*Avoid evading while stunned or immobile.*/ if (Utils.ImmobileTime(ObjectManager.Player) - Utils.TickCount > Game.Ping / 2 + 70) { Evading = false; return; } /*Avoid evading while dashing.*/ if (ObjectManager.Player.LSIsDashing()) { Evading = false; return; } //Don't evade while casting R as sion if (PlayerChampionName == "Sion" && ObjectManager.Player.HasBuff("SionR")) { PathFollower.Stop(); return; } //Shield allies. foreach (var ally in ObjectManager.Get<AIHeroClient>()) { if (ally.LSIsValidTarget(1000, false)) { var shieldAlly = Config.shielding["shield" + ally.ChampionName]; if (shieldAlly != null && shieldAlly.Cast<CheckBox>().CurrentValue) { var allySafeResult = IsSafe(ally.ServerPosition.LSTo2D()); if (!allySafeResult.IsSafe) { var dangerLevel = 0; foreach (var skillshot in allySafeResult.SkillshotList) { dangerLevel = Math.Max(dangerLevel, getSliderItem(Config.skillShots, "DangerLevel" + skillshot.SpellData.MenuItemName)); } foreach (var evadeSpell in EvadeSpellDatabase.Spells) { if (evadeSpell.IsShield && evadeSpell.CanShieldAllies && ally.LSDistance(ObjectManager.Player) < evadeSpell.MaxRange && dangerLevel >= evadeSpell.DangerLevel && ObjectManager.Player.Spellbook.CanUseSpell(evadeSpell.Slot) == SpellState.Ready && IsAboutToHit(ally, evadeSpell.Delay)) { ObjectManager.Player.Spellbook.CastSpell(evadeSpell.Slot, ally); } } } } } } //Spell Shielded if (ObjectManager.Player.IsSpellShielded()) { PathFollower.Stop(); return; } if (NoSolutionFound) { PathFollower.Stop(); } var currentPath = ObjectManager.Player.GetWaypoints(); var safeResult = IsSafe(PlayerPosition); var safePath = IsSafePath(currentPath, 100); /*FOLLOWPATH*/ if (FollowPath && !NoSolutionFound && (Keepfollowing || !Evading) && EvadeToPoint.IsValid() && safeResult.IsSafe) { if (EvadeSpellDatabase.Spells.Any(evadeSpell => evadeSpell.Name == "Walking" && evadeSpell.Enabled)) { if (Utils.TickCount - LastSentMovePacketT2 > 300) { var candidate = Pathfinding.Pathfinding.PathFind(PlayerPosition, EvadeToPoint); PathFollower.Follow(candidate); LastSentMovePacketT2 = Utils.TickCount; } } } else { FollowPath = false; } NoSolutionFound = false; //Continue evading if (Evading && IsSafe(EvadePoint).IsSafe) { if (safeResult.IsSafe) { //We are safe, stop evading. Evading = false; } else { if (Utils.TickCount - LastSentMovePacketT > 1000/15) { LastSentMovePacketT = Utils.TickCount; ObjectManager.Player.SendMovePacket(EvadePoint); } return; } } //Stop evading if the point is not safe. else if (Evading) { Evading = false; } //The path is not safe. if (!safePath.IsSafe) { //Inside the danger polygon. if (!safeResult.IsSafe) { //Search for an evade point: TryToEvade(safeResult.SkillshotList, EvadeToPoint.IsValid() ? EvadeToPoint : Game.CursorPos.LSTo2D()); } //Outside the danger polygon. else { FollowPath = true; //Stop at the edge of the skillshot. if (EvadeSpellDatabase.Spells.Any(evadeSpell => evadeSpell.Name == "Walking" && evadeSpell.Enabled)) { ObjectManager.Player.SendMovePacket(safePath.Intersection.Point); } } } }
public void UltimateLock() { var currentTarget = TargetSelector.SelectedTarget; if (currentTarget.LSIsValidTarget()) { var predictedPosition = Variables.Spell[Variables.Spells.R].GetPrediction(currentTarget).UnitPosition; var directionVector = (currentTarget.ServerPosition - ObjectManager.Player.ServerPosition).Normalized(); const float RRangeCoefficient = 0.95f; var rRangeAdjusted = Variables.Spell[Variables.Spells.R].Range * RRangeCoefficient; var rEndPointXCoordinate = predictedPosition.X + directionVector.X * rRangeAdjusted; var rEndPointYCoordinate = predictedPosition.Y + directionVector.Y * rRangeAdjusted; var rEndPoint = new Vector2(rEndPointXCoordinate, rEndPointYCoordinate).To3D(); if (rEndPoint.LSDistance(ObjectManager.Player.ServerPosition) < Variables.Spell[Variables.Spells.R].Range) { EloBuddy.Player.IssueOrder(GameObjectOrder.MoveTo, rEndPoint); } } }
public static Vector2 GetCollisionPoint(Skillshot skillshot) { var collisions = new List<DetectedCollision>(); var from = skillshot.GetMissilePosition(0); skillshot.ForceDisabled = false; foreach (var cObject in skillshot.SpellData.CollisionObjects) { switch (cObject) { case CollisionObjectTypes.Minion: if (!getCheckBoxItem(Config.collision, "MinionCollision")) { break; } foreach (var minion in MinionManager.GetMinions( from.To3D(), 1200, MinionTypes.All, skillshot.Unit.Team == ObjectManager.Player.Team ? MinionTeam.NotAlly : MinionTeam.NotAllyForEnemy)) { var pred = FastPrediction( from, minion, Math.Max(0, skillshot.SpellData.Delay - (Utils.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed); var pos = pred.PredictedPos; var w = skillshot.SpellData.RawRadius + (!pred.IsMoving ? (minion.BoundingRadius - 15) : 0) - pos.LSDistance(from, skillshot.End, true); if (w > 0) { collisions.Add( new DetectedCollision { Position = pos.LSProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = minion, Type = CollisionObjectTypes.Minion, Distance = pos.LSDistance(from), Diff = w, }); } } break; case CollisionObjectTypes.Champions: if (!getCheckBoxItem(Config.collision, "HeroCollision")) { break; } foreach (var hero in ObjectManager.Get<AIHeroClient>() .Where( h => (h.LSIsValidTarget(1200, false) && h.Team == ObjectManager.Player.Team && !h.IsMe || Config.TestOnAllies && h.Team != ObjectManager.Player.Team))) { var pred = FastPrediction( from, hero, Math.Max(0, skillshot.SpellData.Delay - (Utils.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed); var pos = pred.PredictedPos; var w = skillshot.SpellData.RawRadius + 30 - pos.LSDistance(from, skillshot.End, true); if (w > 0) { collisions.Add( new DetectedCollision { Position = pos.LSProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = hero, Type = CollisionObjectTypes.Minion, Distance = pos.LSDistance(from), Diff = w, }); } } break; case CollisionObjectTypes.YasuoWall: if (!getCheckBoxItem(Config.collision, "YasuoCollision")) { break; } if ( !ObjectManager.Get<AIHeroClient>() .Any( hero => hero.LSIsValidTarget(float.MaxValue, false) && hero.Team == ObjectManager.Player.Team && hero.ChampionName == "Yasuo")) { break; } GameObject wall = null; foreach (var gameObject in ObjectManager.Get<GameObject>()) { if (gameObject.IsValid && System.Text.RegularExpressions.Regex.IsMatch( gameObject.Name, "_w_windwall.\\.troy", System.Text.RegularExpressions.RegexOptions.IgnoreCase)) { wall = gameObject; } } if (wall == null) { break; } var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = (300 + 50 * Convert.ToInt32(level)); var wallDirection = (wall.Position.LSTo2D() - YasuoWallCastedPos).LSNormalized().LSPerpendicular(); var wallStart = wall.Position.LSTo2D() + wallWidth / 2 * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; var wallPolygon = new Geometry.Rectangle(wallStart, wallEnd, 75).ToPolygon(); var intersection = new Vector2(); var intersections = new List<Vector2>(); for (var i = 0; i < wallPolygon.Points.Count; i++) { var inter = wallPolygon.Points[i].LSIntersection( wallPolygon.Points[i != wallPolygon.Points.Count - 1 ? i + 1 : 0], from, skillshot.End); if (inter.Intersects) { intersections.Add(inter.Point); } } if (intersections.Count > 0) { intersection = intersections.OrderBy(item => item.LSDistance(from)).ToList()[0]; var collisionT = Utils.TickCount + Math.Max( 0, skillshot.SpellData.Delay - (Utils.TickCount - skillshot.StartTick)) + 100 + (1000 * intersection.LSDistance(from)) / skillshot.SpellData.MissileSpeed; if (collisionT - WallCastT < 4000) { if (skillshot.SpellData.Type != SkillShotType.SkillshotMissileLine) { skillshot.ForceDisabled = true; } return intersection; } } break; } } Vector2 result; if (collisions.Count > 0) { result = collisions.OrderBy(c => c.Distance).ToList()[0].Position; } else { result = new Vector2(); } return result; }
public static bool CheckPointCollision(Obj_AI_Base unit, Vector2 movePos) { var path = unit.GetPath(movePos.To3D()); if (path.Length > 0) { if (movePos.LSDistance(path[path.Length - 1].LSTo2D()) > 5) { return true; } } return false; }
internal static Vector2 GetDashPosFrom(Vector2 startPos, Obj_AI_Base @base) { var startPos3D = startPos.To3D(); var predictedposition = startPos3D.LSExtend(@base.Position, startPos.LSDistance(@base) + 475 - startPos.LSDistance(@base)).LSTo2D(); DashPosition = predictedposition; return predictedposition; }
public static float GetClosestDistanceApproach(Spell spell, Vector2 pos, float speed, float delay, Vector2 heroPos, float extraDist) { var walkDir = (pos - heroPos).LSNormalized(); if (spell.spellType == SpellType.Line && spell.info.projectileSpeed != float.MaxValue) { var spellPos = spell.GetCurrentSpellPosition(true, delay); var spellStartPos = spell.currentSpellPosition; var spellEndPos = spell.GetSpellEndPosition(); var extendedPos = pos.ExtendDir(walkDir, ObjectCache.myHeroCache.boundingRadius + speed * delay / 1000); Vector2 cHeroPos; Vector2 cSpellPos; var cpa2 = MathUtils.GetCollisionDistanceEx( heroPos, walkDir * speed, ObjectCache.myHeroCache.boundingRadius, spellPos, spell.direction * spell.info.projectileSpeed, spell.radius + extraDist, out cHeroPos, out cSpellPos); var cHeroPosProjection = cHeroPos.LSProjectOn(heroPos, extendedPos); var cSpellPosProjection = cSpellPos.LSProjectOn(spellPos, spellEndPos); if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment && cpa2 != float.MaxValue) { return 0; } var cpa = MathUtilsCPA.CPAPointsEx(heroPos, walkDir * speed, spellPos, spell.direction * spell.info.projectileSpeed, pos, spellEndPos, out cHeroPos, out cSpellPos); cHeroPosProjection = cHeroPos.LSProjectOn(heroPos, extendedPos); cSpellPosProjection = cSpellPos.LSProjectOn(spellPos, spellEndPos); var checkDist = ObjectCache.myHeroCache.boundingRadius + spell.radius + extraDist; if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment) { return Math.Max(0, cpa - checkDist); } else { return checkDist; } //return MathUtils.ClosestTimeOfApproach(heroPos, walkDir * speed, spellPos, spell.direction * spell.info.projectileSpeed); } else if (spell.spellType == SpellType.Line && spell.info.projectileSpeed == float.MaxValue) { var spellHitTime = Math.Max(0, spell.endTime - EvadeUtils.TickCount - delay); //extraDelay var walkRange = heroPos.LSDistance(pos); var predictedRange = speed * (spellHitTime / 1000); var tHeroPos = heroPos + walkDir * Math.Min(predictedRange, walkRange); //Hero predicted pos var projection = tHeroPos.LSProjectOn(spell.startPos, spell.endPos); return Math.Max(0, tHeroPos.LSDistance(projection.SegmentPoint) - (spell.radius + ObjectCache.myHeroCache.boundingRadius + extraDist)); //+ dodgeBuffer } else if (spell.spellType == SpellType.Circular) { var spellHitTime = Math.Max(0, spell.endTime - EvadeUtils.TickCount - delay); //extraDelay var walkRange = heroPos.LSDistance(pos); var predictedRange = speed * (spellHitTime / 1000); var tHeroPos = heroPos + walkDir * Math.Min(predictedRange, walkRange); //Hero predicted pos if (spell.info.spellName == "VeigarEventHorizon") { var wallRadius = 65; var midRadius = spell.radius - wallRadius; if (spellHitTime == 0) { return 0; } if (tHeroPos.LSDistance(spell.endPos) >= spell.radius) { return Math.Max(0, tHeroPos.LSDistance(spell.endPos) - midRadius - wallRadius); } else { return Math.Max(0, midRadius - tHeroPos.LSDistance(spell.endPos) - wallRadius); } } var closestDist = Math.Max(0, tHeroPos.LSDistance(spell.endPos) - (spell.radius + extraDist)); if (spell.info.extraEndTime > 0 && closestDist != 0) { var remainingTime = Math.Max(0, spell.endTime + spell.info.extraEndTime - EvadeUtils.TickCount - delay); var predictedRange2 = speed * (remainingTime / 1000); var tHeroPos2 = heroPos + walkDir * Math.Min(predictedRange2, walkRange); if (CheckMoveToDirection(tHeroPos, tHeroPos2)) { return 0; } } else { return closestDist; } } else if (spell.spellType == SpellType.Arc) { var spellPos = spell.GetCurrentSpellPosition(true, delay); var spellEndPos = spell.GetSpellEndPosition(); var pDir = spell.direction.LSPerpendicular(); spellPos = spellPos - pDir * spell.radius / 2; spellEndPos = spellEndPos - pDir * spell.radius / 2; var extendedPos = pos.ExtendDir(walkDir, ObjectCache.myHeroCache.boundingRadius); Vector2 cHeroPos; Vector2 cSpellPos; var cpa = MathUtilsCPA.CPAPointsEx(heroPos, walkDir * speed, spellPos, spell.direction * spell.info.projectileSpeed, pos, spellEndPos, out cHeroPos, out cSpellPos); var cHeroPosProjection = cHeroPos.LSProjectOn(heroPos, extendedPos); var cSpellPosProjection = cSpellPos.LSProjectOn(spellPos, spellEndPos); var checkDist = spell.radius + extraDist; if (cHeroPos.InSkillShot(spell, ObjectCache.myHeroCache.boundingRadius)) { if (cSpellPosProjection.IsOnSegment && cHeroPosProjection.IsOnSegment) { return Math.Max(0, cpa - checkDist); } else { return checkDist; } } } return 1; }
internal static Vector2[] GetCandidates(Vector2 from, Vector2 to, float radius, float range) { var middlePoint = (from + to) / 2; var intersections = Geometry.CircleCircleIntersection( from, middlePoint, radius, from.LSDistance(middlePoint)); if (intersections.Length > 1) { var c1 = intersections[0]; var c2 = intersections[1]; c1 = from + range * (to - c1).LSNormalized(); c2 = from + range * (to - c2).LSNormalized(); return new[] { c1, c2 }; } return new Vector2[] { }; }
/// <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> public static Prediction.Result GetPrediction(Obj_AI_Base target, float width, float delay, float missileSpeed, float range, bool collisionable, List<Vector2> path, float avgt, float movt, float avgp, float anglediff, Vector2 from, Vector2 rangeCheckFrom, bool arconly = true) { Prediction.AssertInitializationMode(); if (arconly) { if (target.LSDistance(from) < width || target.LSDistance(from) > range*0.75f) return CirclePrediction.GetPrediction(target, width, delay, missileSpeed, range, collisionable, path, avgt, movt, avgp, anglediff, from, rangeCheckFrom); var pred = LinePrediction.GetPrediction(target, 80f, delay, missileSpeed, range, collisionable, path, avgt, movt, avgp, anglediff, from, rangeCheckFrom); if (pred.HitChance >= EloBuddy.SDK.Enumerations.HitChance.Low) { pred.CastPosition = @from + (pred.CastPosition - @from).LSNormalized()*range /*.RotateAroundPoint(from, (1 - pred.UnitPosition.LSDistance(ObjectManager.Player.ServerPosition.LSTo2D()) / 820f) * (float)Math.PI / 2f)*/; var cos = (float) Math.Cos((1 - pred.UnitPosition.LSDistance(from)/820f)*Math.PI/2); var sin = (float) Math.Sin((1 - pred.UnitPosition.LSDistance(from)/820f)*Math.PI/2); var x = cos*(pred.CastPosition.X - from.X) - sin*(pred.CastPosition.Y - from.Y) + from.X; var y = sin*(pred.CastPosition.X - from.X) + cos*(pred.CastPosition.Y - from.Y) + from.Y; pred.CastPosition = new Vector2(x, y); } return pred; } var result = new Prediction.Result(); if (path.Count <= 1) //if target is not moving, easy to hit { result.HitChance = EloBuddy.SDK.Enumerations.HitChance.Immobile; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; return result; } if (target is AIHeroClient && ((AIHeroClient) target).IsChannelingImportantSpell()) { result.HitChance = EloBuddy.SDK.Enumerations.HitChance.Immobile; result.CastPosition = target.ServerPosition.LSTo2D(); result.UnitPosition = result.CastPosition; return result; } if (Utility.IsImmobileTarget(target)) return Prediction.GetImmobilePrediction(target, width, delay, missileSpeed, range, collisionable, SkillshotType.SkillshotCircle, @from, rangeCheckFrom); if (target.IsDashing()) return Prediction.GetDashingPrediction(target, width, delay, missileSpeed, range, collisionable, SkillshotType.SkillshotCircle, @from, rangeCheckFrom); var targetDistance = rangeCheckFrom.LSDistance(target.ServerPosition); var flyTime = 0f; if (missileSpeed != 0) { var Vt = (path[path.Count - 1] - path[0]).LSNormalized()*target.MoveSpeed; var Vs = (target.ServerPosition.LSTo2D() - rangeCheckFrom).LSNormalized()*missileSpeed; var Vr = Vs - Vt; flyTime = targetDistance/Vr.Length(); if (path.Count > 5) flyTime = targetDistance/missileSpeed; } var t = flyTime + delay + Game.Ping/2000f + ConfigMenu.SpellDelay/1000f; result.HitChance = Prediction.GetHitChance(t*1000f, avgt, movt, avgp, anglediff); #region arc collision test if (result.HitChance > EloBuddy.SDK.Enumerations.HitChance.Low) { for (var i = 1; i < path.Count; i++) { var senderPos = rangeCheckFrom; var testPos = path[i]; var multp = testPos.LSDistance(senderPos)/875.0f; var dianaArc = new Geometry.Polygon( ClipperWrapper.DefineArc(senderPos - new Vector2(875/2f, 20), testPos, (float) Math.PI*multp, 410, 200*multp), ClipperWrapper.DefineArc(senderPos - new Vector2(875/2f, 20), testPos, (float) Math.PI*multp, 410, 320*multp)); if (!dianaArc.IsOutside(target.ServerPosition.LSTo2D())) { result.HitChance = EloBuddy.SDK.Enumerations.HitChance.High; result.CastPosition = testPos; result.UnitPosition = testPos; return result; } } } #endregion return CirclePrediction.GetPrediction(target, width, delay, missileSpeed, range, collisionable, path, avgt, movt, avgp, anglediff, @from, rangeCheckFrom); }
public static bool BadaoInTheCone(this Vector2 pos, Vector2 centerconePolar, Vector2 centerconeEnd, double coneAngle) { return BadaoAngleBetween(pos, centerconePolar, centerconeEnd) < coneAngle / 2 && pos.LSDistance(centerconePolar) < centerconePolar.LSDistance(centerconeEnd); }
/// <summary> /// Returns the two intersection points between two circles. /// </summary> /// <param name="center1">The center1.</param> /// <param name="center2">The center2.</param> /// <param name="radius1">The radius1.</param> /// <param name="radius2">The radius2.</param> /// <returns></returns> public static Vector2[] ELCircleCircleIntersection(Vector2 center1, Vector2 center2, float radius1, float radius2) { var D = center1.LSDistance(center2); //The Circles dont intersect: if (D > radius1 + radius2 || (D <= Math.Abs(radius1 - radius2))) { return new Vector2[] {}; } var A = (radius1*radius1 - radius2*radius2 + D*D)/(2*D); var H = (float) Math.Sqrt(radius1*radius1 - A*A); var Direction = (center2 - center1).ELNormalized(); var PA = center1 + A*Direction; var S1 = PA + H*Direction.ELPerpendicular(); var S2 = PA - H*Direction.ELPerpendicular(); return new[] {S1, S2}; }
public static Vector2 GetCollisionPoint(Skillshot skillshot) { var collisions = new List<DetectedCollision>(); var from = skillshot.GetMissilePosition(0); skillshot.ForceDisabled = false; foreach (var cObject in skillshot.SkillshotData.CollisionObjects) { switch (cObject) { case CollisionObjectTypes.Minion: collisions.AddRange(from minion in MinionManager.GetMinions(@from.To3D(), 1200, MinionTypes.All, skillshot.Caster.Team == ObjectManager.Player.Team ? MinionTeam.NotAlly : MinionTeam.NotAllyForEnemy) let pred = FastPrediction(@from, minion, Math.Max(0, skillshot.SkillshotData.Delay - (System.Environment.TickCount - skillshot.StartTick)), skillshot.SkillshotData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SkillshotData.RawRadius + (!pred.IsMoving ? minion.BoundingRadius - 15 : 0) - pos.LSDistance(@from, skillshot.EndPosition, true) where w > 0 select new DetectedCollision { Position = pos.ProjectOn(skillshot.EndPosition, skillshot.StartPosition).LinePoint + skillshot.Direction*30, Unit = minion, Type = CollisionObjectTypes.Minion, Distance = pos.LSDistance(@from), Diff = w }); break; case CollisionObjectTypes.Champions: collisions.AddRange(from hero in ObjectManager.Get<AIHeroClient>().Where(h => h.LSIsValidTarget(1200) && h.Team == ObjectManager.Player.Team && !h.IsMe || h.Team != ObjectManager.Player.Team) let pred = FastPrediction(@from, hero, Math.Max(0, skillshot.SkillshotData.Delay - (System.Environment.TickCount - skillshot.StartTick)), skillshot.SkillshotData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SkillshotData.RawRadius + 30 - pos.LSDistance(@from, skillshot.EndPosition, true) where w > 0 select new DetectedCollision { Position = pos.ProjectOn(skillshot.EndPosition, skillshot.StartPosition).LinePoint + skillshot.Direction*30, Unit = hero, Type = CollisionObjectTypes.Minion, Distance = pos.LSDistance(@from), Diff = w }); break; case CollisionObjectTypes.YasuoWall: if ( !ObjectManager.Get<AIHeroClient>() .Any( hero => hero.LSIsValidTarget(float.MaxValue) && hero.Team == ObjectManager.Player.Team && hero.ChampionName == "Yasuo")) { break; } GameObject wall = null; foreach (var gameObject in ObjectManager.Get<GameObject>()) { if (gameObject.IsValid && Regex.IsMatch(gameObject.Name, "_w_windwall.\\.troy", RegexOptions.IgnoreCase)) { wall = gameObject; } } if (wall == null) { break; } var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = 300 + 50*Convert.ToInt32(level); var wallDirection = (wall.Position.LSTo2D() - _yasuoWallCastedPos).Normalized().Perpendicular(); var wallStart = wall.Position.LSTo2D() + wallWidth/2*wallDirection; var wallEnd = wallStart - wallWidth*wallDirection; var wallPolygon = new SkillshotGeometry.Rectangle(wallStart, wallEnd, 75).ToPolygon(); var intersection = new Vector2(); var intersections = new List<Vector2>(); for (var i = 0; i < wallPolygon.Points.Count; i++) { var inter = wallPolygon.Points[i].Intersection( wallPolygon.Points[i != wallPolygon.Points.Count - 1 ? i + 1 : 0], from, skillshot.EndPosition); if (inter.Intersects) { intersections.Add(inter.Point); } } if (intersections.Count > 0) { intersection = intersections.OrderBy(item => item.LSDistance(from)).ToList()[0]; var collisionT = System.Environment.TickCount + Math.Max( 0, skillshot.SkillshotData.Delay - (System.Environment.TickCount - skillshot.StartTick)) + 100 + 1000*intersection.LSDistance(@from)/skillshot.SkillshotData.MissileSpeed; if (collisionT - _wallCastT < 4000) { if (skillshot.SkillshotData.Type != SkillShotType.SkillshotMissileLine) { skillshot.ForceDisabled = true; } return intersection; } } break; } } Vector2 result; result = collisions.Count > 0 ? collisions.OrderBy(c => c.Distance).ToList()[0].Position : new Vector2(); return result; }
public static bool CheckMoveToDirection(Vector2 from, Vector2 movePos, float extraDelay = 0) { var dir = (movePos - from).LSNormalized(); //movePos = movePos.ExtendDir(dir, ObjectCache.myHeroCache.boundingRadius); foreach (KeyValuePair<int, Spell> entry in SpellDetector.spells) { Spell spell = entry.Value; if (!from.InSkillShot(spell, ObjectCache.myHeroCache.boundingRadius)) { Vector2 spellPos = spell.currentSpellPosition; if (spell.spellType == SpellType.Line) { if (spell.LineIntersectLinearSpell(from, movePos)) return true; } else if (spell.spellType == SpellType.Circular) { if (spell.info.spellName == "VeigarEventHorizon") { var cpa2 = MathUtilsCPA.CPAPointsEx(from, dir * ObjectCache.myHeroCache.moveSpeed, spell.endPos, new Vector2(0, 0), movePos, spell.endPos); if (from.LSDistance(spell.endPos) < spell.radius && !(from.LSDistance(spell.endPos) < spell.radius - 135 && movePos.LSDistance(spell.endPos) < spell.radius - 135)) { return true; } else if (from.LSDistance(spell.endPos) > spell.radius && cpa2 < spell.radius + 10) { return true; } } else { Vector2 cHeroPos; Vector2 cSpellPos; var cpa2 = MathUtils.GetCollisionDistanceEx( from, dir * ObjectCache.myHeroCache.moveSpeed, 1, spell.endPos, new Vector2(0, 0), spell.radius, out cHeroPos, out cSpellPos); var cHeroPosProjection = cHeroPos.LSProjectOn(from, movePos); if (cHeroPosProjection.IsOnSegment && cpa2 != float.MaxValue) { return true; } /*var cpa = MathUtilsCPA.CPAPointsEx(from, dir * ObjectCache.myHeroCache.moveSpeed, spell.endPos, new Vector2(0, 0), movePos, spell.endPos); if (cpa < spell.radius + 10) { return true; }*/ } } else if (spell.spellType == SpellType.Arc) { if (from.isLeftOfLineSegment(spell.startPos, spell.endPos)) { return MathUtils.CheckLineIntersection(from, movePos, spell.startPos, spell.endPos); } var spellRange = spell.startPos.LSDistance(spell.endPos); var midPoint = spell.startPos + spell.direction * (spellRange / 2); var cpa = MathUtilsCPA.CPAPointsEx(from, dir * ObjectCache.myHeroCache.moveSpeed, midPoint, new Vector2(0, 0), movePos, midPoint); if (cpa < spell.radius + 10) { return true; } } else if (spell.spellType == SpellType.Cone) { } } } return false; }
/// <summary> /// Gets triggered when a unit casts a spell and the unit is visible. /// </summary> private static void ObjAiHeroOnOnProcessSpellCast(Obj_AI_Base sender, GameObjectProcessSpellCastEventArgs args) { if (sender == null || !sender.IsValid) { return; } if (Config.PrintSpellData && sender is AIHeroClient) { Chat.Print(Utils.TickCount + " ProcessSpellCast: " + args.SData.Name); Console.WriteLine(Utils.TickCount + " ProcessSpellCast: " + args.SData.Name); } if (args.SData.Name == "dravenrdoublecast") { Program.DetectedSkillshots.RemoveAll( s => s.Unit.NetworkId == sender.NetworkId && s.SpellData.SpellName == "DravenRCast"); } if (!sender.IsValid || sender.Team == ObjectManager.Player.Team && !Config.TestOnAllies) { return; } //Get the skillshot data. var spellData = SpellDatabase.GetByName(args.SData.Name); //Skillshot not added in the database. if (spellData == null) { return; } var startPos = new Vector2(); if (spellData.FromObject != "") { foreach (var o in ObjectManager.Get<GameObject>()) { if (o.Name.Contains(spellData.FromObject)) { startPos = o.Position.LSTo2D(); } } } else { startPos = sender.ServerPosition.LSTo2D(); } //For now only zed support. if (spellData.FromObjects != null && spellData.FromObjects.Length > 0) { foreach (var obj in ObjectManager.Get<GameObject>()) { if (obj.IsEnemy && spellData.FromObjects.Contains(obj.Name)) { var start = obj.Position.LSTo2D(); var end = start + spellData.Range * (args.End.LSTo2D() - obj.Position.LSTo2D()).LSNormalized(); TriggerOnDetectSkillshot( DetectionType.ProcessSpell, spellData, Utils.TickCount - Game.Ping / 2, start, end, end, sender); } } } if (!startPos.IsValid()) { return; } var endPos = args.End.LSTo2D(); if (spellData.SpellName == "LucianQ" && args.Target != null && args.Target.NetworkId == ObjectManager.Player.NetworkId) { return; } //Calculate the real end Point: var direction = (endPos - startPos).LSNormalized(); if (startPos.LSDistance(endPos) > spellData.Range || spellData.FixedRange) { endPos = startPos + direction * spellData.Range; } if (spellData.ExtraRange != -1) { endPos = endPos + Math.Min(spellData.ExtraRange, spellData.Range - endPos.LSDistance(startPos)) * direction; } //Trigger the skillshot detection callbacks. TriggerOnDetectSkillshot( DetectionType.ProcessSpell, spellData, Utils.TickCount - Game.Ping / 2, startPos, endPos, args.End.LSTo2D(), sender); }
/// <summary> /// Checks wall collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <returns>true if collision found</returns> public static bool CheckWallCollision(Vector2 from, Vector2 to) { float step = from.LSDistance(to) / 20; for (var i = 0; i < 20; i++) { var p = from.LSExtend(to, step * i); if (NavMesh.GetCollisionFlags(p.X, p.Y).HasFlag(CollisionFlags.Wall)) return true; } return false; }
private static Queue<Vector2> GeneratePath(Vector2 start, Vector2 end) { //return PathGenerator.GeneratePath(start.ToWorldPoint().To2D(), end.ToWorldPoint().To2D()); var d = start.LSDistance(end); var path = new Queue<Vector2>(); if (d < 75) { path.Enqueue(end); return path; } var increment = (int) d / 30; //(2 * d / FPS) var count = 0; for (var i = 0; i < d; i += increment) { if (i > d) { break; } var point = start.LSExtend(end, i); if (count++ % 10 == 0) { point.Randomize(10, 50); if (count % 6 == 0) { point.Randomize(50, 100); } } path.Enqueue(point); } path.Enqueue(end); return path; }
/// <summary> /// Check Yasuo wall collisions /// </summary> /// <param name="from">Start position</param> /// <param name="to">End position</param> /// <param name="width">Rectangle scale</param> /// <param name="isArc">Check collision for arc spell</param> /// <returns>true if collision found</returns> public static bool CheckYasuoWallCollision(Vector2 from, Vector2 to, float width, bool isArc = false) { if (Utils.TickCount - yasuoWallCastedTick > 4000) return false; GameObject yasuoWall = ObjectManager.Get<GameObject>().Where(p => p.IsValid && Regex.IsMatch(p.Name, "_w_windwall_enemy_0.\\.troy", RegexOptions.IgnoreCase)).FirstOrDefault(); if (yasuoWall == null) return false; Vector2 yasuoWallDirection = (yasuoWall.Position.LSTo2D() - yasuoWallCastedPos).Normalized().Perpendicular(); float yasuoWallWidth = 300 + 50 * yasuoWallLevel; Vector2 yasuoWallStart = yasuoWall.Position.LSTo2D() + yasuoWallWidth / 2f * yasuoWallDirection; Vector2 yasuoWallEnd = yasuoWallStart - yasuoWallWidth * yasuoWallDirection; Geometry.Polygon yasuoWallPoly = ClipperWrapper.DefineRectangle(yasuoWallStart, yasuoWallEnd, 5); Geometry.Polygon spellHitBox = ClipperWrapper.DefineRectangle(from, to, width); if (isArc) { spellHitBox = new SPrediction.Geometry.Polygon( ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 200 * (to.LSDistance(from) / 900)), ClipperWrapper.DefineArc(from - new Vector2(900 / 2f, 20), to, (float)Math.PI * (to.LSDistance(from) / 900), 410, 320 * (to.LSDistance(from) / 900))); } return ClipperWrapper.IsIntersects(ClipperWrapper.MakePaths(yasuoWallPoly), ClipperWrapper.MakePaths(spellHitBox)); }