public SafePathResult IsSafePath(List<Vector2> path, int timeOffset, int speed = -1, int delay = 0)
{
var distance = 0f;
timeOffset += Game.Ping / 2;
speed = speed == -1 ? (int)ObjectManager.Player.MoveSpeed : speed;
var allIntersections = new List<FoundIntersection>();
for (var i = 0; i <= path.Count - 2; i++)
{
var from = path[i];
var to = path[i + 1];
var segmentIntersections = new List<FoundIntersection>();
for (var j = 0; j <= this.Polygon.Points.Count - 1; j++)
{
var sideStart = this.Polygon.Points[j];
var sideEnd = this.Polygon.Points[j == (this.Polygon.Points.Count - 1) ? 0 : j + 1];
var intersection = from.Intersection(to, sideStart, sideEnd);
if (intersection.Intersects)
{
segmentIntersections.Add(
new FoundIntersection(
distance + intersection.Point.Distance(from),
(int)((distance + intersection.Point.Distance(from)) * 1000 / speed),
intersection.Point,
from));
}
}
allIntersections.AddRange(segmentIntersections.OrderBy(o => o.Distance));
distance += from.Distance(to);
}
if (this.SpellData.Type == SkillShotType.SkillshotMissileLine
|| this.SpellData.Type == SkillShotType.SkillshotMissileCone
|| this.SpellData.Type == SkillShotType.SkillshotArc)
{
if (this.IsSafePoint(ObjectManager.Player.ServerPosition.To2D()))
{
if (allIntersections.Count == 0)
{
return new SafePathResult(true, new FoundIntersection());
}
if (this.SpellData.DontCross)
{
return new SafePathResult(false, allIntersections[0]);
}
for (var i = 0; i <= allIntersections.Count - 1; i = i + 2)
{
var enterIntersection = allIntersections[i];
var enterIntersectionProjection =
enterIntersection.Point.ProjectOn(this.Start, this.End).SegmentPoint;
if (i == allIntersections.Count - 1)
{
return
new SafePathResult(
(this.End.Distance(this.GetMissilePosition(enterIntersection.Time - timeOffset))
+ 50 <= this.End.Distance(enterIntersectionProjection))
&& ObjectManager.Player.MoveSpeed < this.SpellData.MissileSpeed,
allIntersections[0]);
}
var exitIntersection = allIntersections[i + 1];
var exitIntersectionProjection =
exitIntersection.Point.ProjectOn(this.Start, this.End).SegmentPoint;
if (this.GetMissilePosition(enterIntersection.Time - timeOffset).Distance(this.End) + 50
> enterIntersectionProjection.Distance(this.End)
&& this.GetMissilePosition(exitIntersection.Time + timeOffset).Distance(this.End)
<= exitIntersectionProjection.Distance(this.End))
{
return new SafePathResult(false, allIntersections[0]);
}
}
return new SafePathResult(true, allIntersections[0]);
}
if (allIntersections.Count == 0)
{
return new SafePathResult(false, new FoundIntersection());
}
if (allIntersections.Count > 0)
{
var exitIntersection = allIntersections[0];
var exitIntersectionProjection = exitIntersection.Point.ProjectOn(this.Start, this.End).SegmentPoint;
if (this.GetMissilePosition(exitIntersection.Time + timeOffset).Distance(this.End)
<= exitIntersectionProjection.Distance(this.End))
{
return new SafePathResult(false, allIntersections[0]);
}
}
}
if (allIntersections.Count == 0)
{
return new SafePathResult(false, new FoundIntersection());
}
if (this.IsSafePoint(ObjectManager.Player.ServerPosition.To2D()) && this.SpellData.DontCross)
{
return new SafePathResult(false, allIntersections[0]);
}
var timeToExplode = (this.SpellData.DontAddExtraDuration ? 0 : this.SpellData.ExtraDuration)
+ this.SpellData.Delay
+ (int)(1000 * this.Start.Distance(this.End) / this.SpellData.MissileSpeed)
- (Extensions.GameTimeTickCount - this.StartTick);
return !this.IsSafePoint(path.PositionAfter(timeToExplode, speed, delay))
? new SafePathResult(false, allIntersections[0])
: new SafePathResult(
this.IsSafePoint(path.PositionAfter(timeToExplode, speed, timeOffset)),
allIntersections[0]);
}