public static Vector2 GetCollisionPoint(Skillshot skillshot) { var collisions = new List <DetectedCollision>(); var from = skillshot.GetMissilePosition(0); skillshot.ForceDisabled = false; if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.Minions)) { var minions = new List <Obj_AI_Minion>(); minions.AddRange(GameObjects.Jungle.Where(i => i.IsValidTarget(1200, true, from.ToVector3()))); minions.AddRange( GameObjects.Minions.Where( i => i.IsValidTarget(1200, false, @from.ToVector3()) && (skillshot.Unit.Team == Program.Player.Team ? i.Team != Program.Player.Team : i.Team == Program.Player.Team) && (i.IsMinion() || i.IsPet()))); collisions.AddRange( from minion in minions let pred = FastPrediction( @from, minion, Math.Max(0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SpellData.RawRadius + (!pred.IsMoving ? minion.BoundingRadius - 15 : 0) - pos.Distance(@from, skillshot.End, true) where w > 0 select new DetectedCollision { Position = pos.LSProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = minion, Type = CollisionableObjects.Minions, Distance = pos.Distance(@from), Diff = w }); } if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.Heroes)) { collisions.AddRange( from hero in GameObjects.AllyHeroes.Where(i => i.IsValidTarget(1200, false) && !i.IsMe) let pred = FastPrediction( @from, hero, Math.Max(0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SpellData.RawRadius + 30 - pos.Distance(@from, skillshot.End, true) where w > 0 select new DetectedCollision { Position = pos.LSProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = hero, Type = CollisionableObjects.Heroes, Distance = pos.Distance(@from), Diff = w }); } if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall) && GameObjects.AllyHeroes.Any(i => i.ChampionName == "Yasuo")) { var wall = GameObjects.AllGameObjects.FirstOrDefault( i => i.IsValid && Regex.IsMatch(i.Name, "_w_windwall.\\.troy", RegexOptions.IgnoreCase)); if (wall != null) { var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = 300 + 50 * Convert.ToInt32(level); var wallPos = wall.Position.ToVector2(); var wallDirection = (wallPos - wallCastedPos).LSNormalized().Perpendicular(); var wallStart = wallPos + wallWidth / 2f * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; var wallPolygon = new Geometry.Rectangle(wallStart, wallEnd, 75).ToPolygon(); 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.End); if (inter.Intersects) { intersections.Add(inter.Point); } } if (intersections.Count > 0) { var intersection = intersections.OrderBy(item => item.Distance(@from)).ToList()[0]; var collisionT = Variables.TickCount + Math.Max( 0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)) + 100 + 1000 * (Math.Abs(skillshot.SpellData.MissileSpeed - int.MaxValue) > 0 ? intersection.Distance(@from) / skillshot.SpellData.MissileSpeed : 0); if (collisionT - wallCastT < 4000) { if (skillshot.SpellData.Type != SkillShotType.SkillshotMissileLine) { skillshot.ForceDisabled = true; } return(intersection); } } } } return(collisions.Count > 0 ? collisions.OrderBy(i => i.Distance).First().Position : new Vector2()); }
public void OnUpdate() { if (this.SpellData.CollisionObjects.GetFlags().Any() && Variables.TickCount - this.lastCollisionCalc > 50) { this.lastCollisionCalc = Variables.TickCount; this.collisionEnd = Collision.GetCollisionPoint(this); } if (this.SpellData.Type == SkillShotType.SkillshotMissileLine) { this.Rectangle = new Geometry.Rectangle( this.GetMissilePosition(0), this.CollisionEnd, this.SpellData.Radius); this.UpdatePolygon(); } if (this.SpellData.MissileFollowsUnit && this.Unit.IsVisible) { this.End = this.Unit.ServerPosition.ToVector2(); this.Direction = (this.End - this.Start).LSNormalized(); this.UpdatePolygon(); } if (this.SpellData.SpellName == "TaricE") { this.Start = this.Unit.ServerPosition.ToVector2(); this.End = this.Start + this.Direction * this.SpellData.Range; this.Rectangle = new Geometry.Rectangle(this.Start, this.End, this.SpellData.Radius); this.UpdatePolygon(); } if (this.SpellData.SpellName == "SionR") { if (this.helperTick == 0) { this.helperTick = this.StartTick; } this.SpellData.MissileSpeed = (int)this.Unit.MoveSpeed; if (this.Unit.LSIsValidTarget(float.MaxValue, false)) { if (!this.Unit.HasBuff("SionR") && Variables.TickCount - this.helperTick > 600) { this.StartTick = 0; } else { this.StartTick = Variables.TickCount - this.SpellData.Delay; this.Start = this.Unit.ServerPosition.ToVector2(); this.End = this.Unit.ServerPosition.ToVector2() + 1000 * this.Unit.Direction.ToVector2().Perpendicular(); this.Direction = (this.End - this.Start).LSNormalized(); this.UpdatePolygon(); } } else { this.StartTick = 0; } } if (this.SpellData.FollowCaster) { this.Circle.Center = this.Unit.ServerPosition.ToVector2(); this.UpdatePolygon(); } }
public void OnUpdate() { if (this.SpellData.CollisionObjects.GetFlags().Any() && Variables.TickCount - this.lastCollisionCalc > 50) { this.lastCollisionCalc = Variables.TickCount; this.collisionEnd = Collision.GetCollisionPoint(this); } if (this.SpellData.Type == SkillShotType.SkillshotMissileLine) { this.Rectangle = new Geometry.Rectangle( this.GetMissilePosition(0), this.CollisionEnd, this.SpellData.Radius); this.UpdatePolygon(); } if (this.SpellData.MissileFollowsUnit && this.Unit.IsVisible) { this.End = this.Unit.ServerPosition.ToVector2(); this.Direction = (this.End - this.Start).LSNormalized(); this.UpdatePolygon(); } if (this.SpellData.SpellName == "TaricE") { this.Start = this.Unit.ServerPosition.ToVector2(); this.End = this.Start + this.Direction * this.SpellData.Range; this.Rectangle = new Geometry.Rectangle(this.Start, this.End, this.SpellData.Radius); this.UpdatePolygon(); } if (this.SpellData.SpellName == "SionR") { if (this.helperTick == 0) { this.helperTick = this.StartTick; } this.SpellData.MissileSpeed = (int)this.Unit.MoveSpeed; if (this.Unit.IsValidTarget(float.MaxValue, false)) { if (!this.Unit.HasBuff("SionR") && Variables.TickCount - this.helperTick > 600) { this.StartTick = 0; } else { this.StartTick = Variables.TickCount - this.SpellData.Delay; this.Start = this.Unit.ServerPosition.ToVector2(); this.End = this.Unit.ServerPosition.ToVector2() + 1000 * this.Unit.Direction.ToVector2().Perpendicular(); this.Direction = (this.End - this.Start).LSNormalized(); this.UpdatePolygon(); } } else { this.StartTick = 0; } } if (this.SpellData.FollowCaster) { this.Circle.Center = this.Unit.ServerPosition.ToVector2(); this.UpdatePolygon(); } }
public Skillshot( DetectionType detectionType, SpellData spellData, int startT, Vector2 start, Vector2 end, Obj_AI_Base unit, MissileClient missile = null) { this.DetectionType = detectionType; this.SpellData = spellData; this.StartTick = startT; this.Start = start; this.End = end; this.Direction = (end - start).LSNormalized(); this.Unit = unit; this.Missile = missile; switch (spellData.Type) { case SkillShotType.SkillshotCircle: this.Circle = new Geometry.Circle(this.CollisionEnd, spellData.Radius); break; case SkillShotType.SkillshotLine: this.Rectangle = new Geometry.Rectangle(this.Start, this.CollisionEnd, spellData.Radius); break; case SkillShotType.SkillshotMissileLine: this.Rectangle = new Geometry.Rectangle(this.Start, this.CollisionEnd, spellData.Radius); break; case SkillShotType.SkillshotCone: this.Sector = new Geometry.Sector( start, this.CollisionEnd - start, spellData.Radius * (float)Math.PI / 180, spellData.Range); break; case SkillShotType.SkillshotRing: this.Ring = new Geometry.Ring(this.CollisionEnd, spellData.Radius, spellData.RingRadius); break; case SkillShotType.SkillshotArc: this.Arc = new Geometry.Arc( start, end, Config.SkillShotsExtraRadius + (int)Program.Player.BoundingRadius); break; } this.UpdatePolygon(); }
public static Vector2 GetCollisionPoint(Skillshot skillshot) { var collisions = new List<DetectedCollision>(); var from = skillshot.GetMissilePosition(0); skillshot.ForceDisabled = false; if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.Minions)) { var minions = new List<Obj_AI_Minion>(); minions.AddRange(GameObjects.Jungle.Where(i => i.IsValidTarget(1200, true, from.ToVector3()))); minions.AddRange( GameObjects.Minions.Where( i => i.IsValidTarget(1200, false, @from.ToVector3()) && (skillshot.Unit.Team == ObjectManager.Player.Team ? i.Team != ObjectManager.Player.Team : i.Team == ObjectManager.Player.Team) && (i.IsMinion() || i.IsPet()))); collisions.AddRange( from minion in minions let pred = FastPrediction( @from, minion, Math.Max(0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SpellData.RawRadius + (!pred.IsMoving ? minion.BoundingRadius - 15 : 0) - pos.Distance(@from, skillshot.End, true) where w > 0 select new DetectedCollision { Position = pos.ProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = minion, Type = CollisionableObjects.Minions, Distance = pos.Distance(@from), Diff = w }); } if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.Heroes)) { collisions.AddRange( from hero in GameObjects.AllyHeroes.Where(i => i.IsValidTarget(1200, false) && !i.IsMe) let pred = FastPrediction( @from, hero, Math.Max(0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)), skillshot.SpellData.MissileSpeed) let pos = pred.PredictedPos let w = skillshot.SpellData.RawRadius + 30 - pos.Distance(@from, skillshot.End, true) where w > 0 select new DetectedCollision { Position = pos.ProjectOn(skillshot.End, skillshot.Start).LinePoint + skillshot.Direction * 30, Unit = hero, Type = CollisionableObjects.Heroes, Distance = pos.Distance(@from), Diff = w }); } if (skillshot.SpellData.CollisionObjects.HasFlag(CollisionableObjects.YasuoWall) && GameObjects.AllyHeroes.Any(i => i.ChampionName == "Yasuo")) { var wall = GameObjects.AllGameObjects.FirstOrDefault( i => i.IsValid && Regex.IsMatch(i.Name, "_w_windwall.\\.troy", RegexOptions.IgnoreCase)); if (wall != null) { var level = wall.Name.Substring(wall.Name.Length - 6, 1); var wallWidth = 300 + 50 * Convert.ToInt32(level); var wallDirection = (wall.Position.ToVector2() - wallCastedPos).Normalized().Perpendicular(); var wallStart = wall.Position.ToVector2() + wallWidth / 2f * wallDirection; var wallEnd = wallStart - wallWidth * wallDirection; var wallPolygon = new Geometry.Rectangle(wallStart, wallEnd, 75).ToPolygon(); 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.End); if (inter.Intersects) { intersections.Add(inter.Point); } } if (intersections.Count > 0) { var intersection = intersections.OrderBy(item => item.Distance(@from)).ToList()[0]; var collisionT = Variables.TickCount + Math.Max( 0, skillshot.SpellData.Delay - (Variables.TickCount - skillshot.StartTick)) + 100 + 1000 * intersection.Distance(@from) / skillshot.SpellData.MissileSpeed; if (collisionT - wallCastT < 4000) { if (skillshot.SpellData.Type != SkillShotType.SkillshotMissileLine) { skillshot.ForceDisabled = true; } return intersection; } } } } return collisions.Count > 0 ? collisions.OrderBy(i => i.Distance).First().Position : new Vector2(); }