public void DrawPath(List <Vector3> nodes, Transform org) { worldLine = this.GetComponent <WorldLine> (); this.org = org; worldLine.line.Clear(); foreach (Vector3 node in nodes) { worldLine.line.Push(node, Vector3.zero, Vector3.zero, .05f); } }
private bool FindPoolPoint(WoWGameObject pool) { int traceStep = AutoAngler.Instance.MySettings.TraceStep; const float pIx2 = 3.14159f * 2f; var traceLine = new WorldLine[traceStep]; PoolPoints.Clear(); // scans starting at 15 yards from player for water at every 18 degress float range = 15; int min = AutoAngler.Instance.MySettings.MinPoolRange; int max = AutoAngler.Instance.MySettings.MaxPoolRange; float step = AutoAngler.Instance.MySettings.PoolRangeStep; float delta = step; float avg = (min + max) / 2; while (true) { for (int i = 0; i < traceStep; i++) { WoWPoint p = pool.Location.RayCast((i * pIx2) / traceStep, range); WoWPoint hPoint = p; hPoint.Z += 45; WoWPoint lPoint = p; lPoint.Z -= 1; traceLine[i].Start = hPoint; traceLine[i].End = lPoint; } WoWPoint[] hitPoints; bool[] tracelineRetVals; GameWorld.MassTraceLine(traceLine, GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out tracelineRetVals, out hitPoints); // what I'm doing here is compare the elevation of 4 corners around a point with // that point's elevation to determine if that point is too steep to stand on. var slopetraces = new List <WorldLine>(); var testPoints = new List <WoWPoint>(); for (int i = 0; i < traceStep; i++) { if (tracelineRetVals[i]) { slopetraces.AddRange(GetQuadSloopTraceLines(hitPoints[i])); testPoints.Add(hitPoints[i]); } else if (WaterWalking.CanCast) { traceLine[i].End.Z = pool.Z + 1; PoolPoints.Add(traceLine[i].End); } } // fire tracelines.. bool[] lavaRetVals = null; WoWPoint[] slopeHits; using (new FrameLock()) { bool[] slopelinesRetVals; GameWorld.MassTraceLine(slopetraces.ToArray(), GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out slopelinesRetVals, out slopeHits); if (AutoAngler.Instance.MySettings.AvoidLava) { GameWorld.MassTraceLine(slopetraces.ToArray(), GameWorld.CGWorldFrameHitFlags.HitTestLiquid2, out lavaRetVals); } } // process results PoolPoints.AddRange(ProcessSlopeAndLavaResults(testPoints, slopeHits, lavaRetVals)); // perform LOS checks if (PoolPoints.Count > 0) { var losLine = new WorldLine[PoolPoints.Count]; for (int i2 = 0; i2 < PoolPoints.Count; i2++) { WoWPoint point = PoolPoints[i2]; point.Z += 2; losLine[i2].Start = point; losLine[i2].End = pool.Location; } GameWorld.MassTraceLine(losLine, GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out tracelineRetVals); for (int i2 = PoolPoints.Count - 1; i2 >= 0; i2--) { if (tracelineRetVals[i2]) { PoolPoints.RemoveAt(i2); } } } // sort pools by distance to player PoolPoints.Sort((p1, p2) => p1.Distance(_me.Location).CompareTo(p2.Distance(_me.Location))); if (!_me.IsFlying) { // if we are not flying check if we can genorate a path to points. for (int i = 0; i < PoolPoints.Count;) { WoWPoint[] testP = Navigator.GeneratePath(_me.Location, PoolPoints[i]); if (testP.Length > 0) { return(true); } PoolPoints.RemoveAt(i); PoolPoints.Sort((a, b) => a.Distance(_me.Location).CompareTo(b.Distance(_me.Location))); } } if (PoolPoints.Count > 0) { return(true); } bool minCaped = (15 - delta) < min; bool maxCaped = (15 + delta) > max; if (minCaped && maxCaped) { break; } if ((range <= 15 && (15 + delta) <= max) || minCaped) { range = 15 + delta; if (avg < 15 || minCaped) { delta += step; } continue; } if ((range > 15 && (15 - delta) >= min) || maxCaped) { range = 15 - delta; if (avg >= 15 || maxCaped) { delta += step; } } } return(false); }
private bool FindPoolPoint(WoWGameObject pool) { int traceStep = AutoAngler.Instance.MySettings.TraceStep; const float pIx2 = 3.14159f*2f; var traceLine = new WorldLine[traceStep]; PoolPoints.Clear(); // scans starting at 15 yards from player for water at every 18 degress float range = 15; int min = AutoAngler.Instance.MySettings.MinPoolRange; int max = AutoAngler.Instance.MySettings.MaxPoolRange; float step = AutoAngler.Instance.MySettings.PoolRangeStep; float delta = step; float avg = (min + max)/2; while (true) { for (int i = 0; i < traceStep; i++) { WoWPoint p = pool.Location.RayCast((i*pIx2)/traceStep, range); WoWPoint hPoint = p; hPoint.Z += 45; WoWPoint lPoint = p; lPoint.Z -= 1; traceLine[i].Start = hPoint; traceLine[i].End = lPoint; } WoWPoint[] hitPoints; bool[] tracelineRetVals; GameWorld.MassTraceLine(traceLine, GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out tracelineRetVals, out hitPoints); // what I'm doing here is compare the elevation of 4 corners around a point with // that point's elevation to determine if that point is too steep to stand on. var slopetraces = new List<WorldLine>(); var testPoints = new List<WoWPoint>(); for (int i = 0; i < traceStep; i++) { if (tracelineRetVals[i]) { slopetraces.AddRange(GetQuadSloopTraceLines(hitPoints[i])); testPoints.Add(hitPoints[i]); } else if (WaterWalking.CanCast) { traceLine[i].End.Z = pool.Z + 1; PoolPoints.Add(traceLine[i].End); } } // fire tracelines.. bool[] lavaRetVals = null; WoWPoint[] slopeHits; using (StyxWoW.Memory.AcquireFrame()) { bool[] slopelinesRetVals; GameWorld.MassTraceLine(slopetraces.ToArray(), GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out slopelinesRetVals, out slopeHits); if (AutoAngler.Instance.MySettings.AvoidLava) { GameWorld.MassTraceLine(slopetraces.ToArray(), GameWorld.CGWorldFrameHitFlags.HitTestLiquid2, out lavaRetVals); } } // process results PoolPoints.AddRange(ProcessSlopeAndLavaResults(testPoints, slopeHits, lavaRetVals)); // perform LOS checks if (PoolPoints.Count > 0) { var losLine = new WorldLine[PoolPoints.Count]; for (int i2 = 0; i2 < PoolPoints.Count; i2++) { WoWPoint point = PoolPoints[i2]; point.Z += 2; losLine[i2].Start = point; losLine[i2].End = pool.Location; } GameWorld.MassTraceLine(losLine, GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out tracelineRetVals); for (int i2 = PoolPoints.Count - 1; i2 >= 0; i2--) { if (tracelineRetVals[i2]) PoolPoints.RemoveAt(i2); } } // sort pools by distance to player PoolPoints.Sort((p1, p2) => p1.Distance(_me.Location).CompareTo(p2.Distance(_me.Location))); if (!_me.IsFlying) { // if we are not flying check if we can genorate a path to points. for (int i = 0; i < PoolPoints.Count;) { WoWPoint[] testP = Navigator.GeneratePath(_me.Location, PoolPoints[i]); if (testP.Length > 0) { return true; } PoolPoints.RemoveAt(i); PoolPoints.Sort((a, b) => a.Distance(_me.Location).CompareTo(b.Distance(_me.Location))); } } if (PoolPoints.Count > 0) return true; bool minCaped = (15 - delta) < min; bool maxCaped = (15 + delta) > max; if (minCaped && maxCaped) break; if ((range <= 15 && (15 + delta) <= max) || minCaped) { range = 15 + delta; if (avg < 15 || minCaped) delta += step; continue; } if ((range > 15 && (15 - delta) >= min) || maxCaped) { range = 15 - delta; if (avg >= 15 || maxCaped) delta += step; } } return false; }
// Finds another point near the destination. Useful when toon is 'waiting' for something // (e.g., boat, mob repops, etc). This allows multiple people running // the same profile to not stand on top of each other while waiting for // something. public static WoWPoint FanOutRandom(this WoWPoint location, double maxRadius) { const int CYLINDER_LINE_COUNT = 12; const int MAX_TRIES = 50; const double SAFE_DISTANCE_BUFFER = 1.75; WoWPoint candidateDestination = location; int tryCount; // Most of the time we'll find a viable spot in less than 2 tries... // However, if you're standing on a pier, or small platform a // viable alternative may take 10-15 tries--its all up to the // random number generator. for (tryCount = MAX_TRIES; tryCount > 0; --tryCount) { WoWPoint circlePoint; bool[] hitResults; WoWPoint[] hitPoints; int index; WorldLine[] traceLines = new WorldLine[CYLINDER_LINE_COUNT + 1]; candidateDestination = location.AddPolarXY((TAU * StyxWoW.Random.NextDouble()), (maxRadius * StyxWoW.Random.NextDouble()), 0.0); // Build set of tracelines that can evaluate the candidate destination -- // We build a cone of lines with the cone's base at the destination's 'feet', // and the cone's point at maxRadius over the destination's 'head'. We also // include the cone 'normal' as the first entry. // 'Normal' vector index = 0; traceLines[index].Start = candidateDestination.Add(0.0, 0.0, maxRadius); traceLines[index].End = candidateDestination.Add(0.0, 0.0, -maxRadius); // Cylinder vectors for (double turnFraction = 0.0; turnFraction < TAU; turnFraction += (TAU / CYLINDER_LINE_COUNT)) { ++index; circlePoint = candidateDestination.AddPolarXY(turnFraction, SAFE_DISTANCE_BUFFER, 0.0); traceLines[index].Start = circlePoint.Add(0.0, 0.0, maxRadius); traceLines[index].End = circlePoint.Add(0.0, 0.0, -maxRadius); } // Evaluate the cylinder... // The result for the 'normal' vector (first one) will be the location where the // destination meets the ground. Before this MassTrace, only the candidateDestination's // X/Y values were valid. GameWorld.MassTraceLine(traceLines.ToArray(), TraceLineHitFlags.Collision, out hitResults, out hitPoints); candidateDestination = hitPoints[0]; // From 'normal', Destination with valid Z coordinate // Sanity check... // We don't want to be standing right on the edge of a drop-off (say we'e on // a plaform or pier). If there is not solid ground all around us, we reject // the candidate. Our test for validity is that the walking distance must // not be more than 20% greater than the straight-line distance to the point. int viableVectorCount = hitPoints.Sum(point => ((Me.Location.SurfacePathDistance(point) < (Me.Location.Distance(point) * 1.20)) ? 1 : 0)); if (viableVectorCount < (CYLINDER_LINE_COUNT + 1)) { continue; } // If new destination is 'too close' to our current position, try again... if (Me.Location.Distance(candidateDestination) <= SAFE_DISTANCE_BUFFER) { continue; } break; } // If we exhausted our tries, just go with simple destination -- if (tryCount <= 0) { candidateDestination = location; } return(candidateDestination); }
// Finds another point near the destination. Useful when toon is 'waiting' for something // (e.g., boat, mob repops, etc). This allows multiple people running // the same profile to not stand on top of each other while waiting for // something. public static WoWPoint FanOutRandom(this WoWPoint location, double maxRadius) { const int CYLINDER_LINE_COUNT = 12; const int MAX_TRIES = 50; const double SAFE_DISTANCE_BUFFER = 1.75; WoWPoint candidateDestination = location; int tryCount; // Most of the time we'll find a viable spot in less than 2 tries... // However, if you're standing on a pier, or small platform a // viable alternative may take 10-15 tries--its all up to the // random number generator. for (tryCount = MAX_TRIES; tryCount > 0; --tryCount) { WoWPoint circlePoint; bool[] hitResults; WoWPoint[] hitPoints; int index; WorldLine[] traceLines = new WorldLine[CYLINDER_LINE_COUNT +1]; candidateDestination = location.AddPolarXY((TAU * _random.NextDouble()), (maxRadius * _random.NextDouble()), 0.0); // Build set of tracelines that can evaluate the candidate destination -- // We build a cone of lines with the cone's base at the destination's 'feet', // and the cone's point at maxRadius over the destination's 'head'. We also // include the cone 'normal' as the first entry. // 'Normal' vector index = 0; traceLines[index].Start = candidateDestination.Add(0.0, 0.0, maxRadius); traceLines[index].End = candidateDestination.Add(0.0, 0.0, -maxRadius); // Cylinder vectors for (double turnFraction = 0.0; turnFraction < TAU; turnFraction += (TAU / CYLINDER_LINE_COUNT)) { ++index; circlePoint = candidateDestination.AddPolarXY(turnFraction, SAFE_DISTANCE_BUFFER, 0.0); traceLines[index].Start = circlePoint.Add(0.0, 0.0, maxRadius); traceLines[index].End = circlePoint.Add(0.0, 0.0, -maxRadius); } // Evaluate the cylinder... // The result for the 'normal' vector (first one) will be the location where the // destination meets the ground. Before this MassTrace, only the candidateDestination's // X/Y values were valid. GameWorld.MassTraceLine(traceLines.ToArray(), GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures, out hitResults, out hitPoints); candidateDestination = hitPoints[0]; // From 'normal', Destination with valid Z coordinate // Sanity check... // We don't want to be standing right on the edge of a drop-off (say we'e on // a plaform or pier). If there is not solid ground all around us, we reject // the candidate. Our test for validity is that the walking distance must // not be more than 20% greater than the straight-line distance to the point. int viableVectorCount = hitPoints.Sum(point => ((Me.Location.SurfacePathDistance(point) < (Me.Location.Distance(point) * 1.20)) ? 1 : 0)); if (viableVectorCount < (CYLINDER_LINE_COUNT +1)) { continue; } // If new destination is 'too close' to our current position, try again... if (Me.Location.Distance(candidateDestination) <= SAFE_DISTANCE_BUFFER) { continue; } break; } // If we exhausted our tries, just go with simple destination -- if (tryCount <= 0) { candidateDestination = location; } return (candidateDestination); }
float?GetFaceWaterDirection() { WoWPoint playerLoc = _me.Location; var sonar = new List <int>(TraceStep); var tracelines = new WorldLine[TraceStep * 3]; bool[] tracelineRetVals; for (int i = 0; i < TraceStep; i++) { // scans 10,15 and 20 yards from player for water at every 18 degress for (int n = 0; n < 3; n++) { WoWPoint p = (playerLoc.RayCast((i * PIx2) / TraceStep, 10 + (n * 5))); WoWPoint highPoint = p; highPoint.Z += 5; WoWPoint lowPoint = p; lowPoint.Z -= 55; tracelines[(i * 3) + n].Start = highPoint; tracelines[(i * 3) + n].End = lowPoint; } } GameWorld.MassTraceLine(tracelines, GameWorld.CGWorldFrameHitFlags.HitTestLiquid | GameWorld.CGWorldFrameHitFlags.HitTestLiquid2, out tracelineRetVals); for (int i = 0; i < TraceStep; i++) { int scan = 0; for (int n = 0; n < 3; n++) { if (tracelineRetVals[(i * 3) + n]) { scan++; } } sonar.Add(scan); } int widest = 0; for (int i = 0; i < TraceStep; i++) { if (sonar[i] > widest) { widest = sonar[i]; } } bool counting = false; int startIndex = 0, bigestStartIndex = 0, startLen = 0, endLen = 0, bigestStretch = 0; // if we found water find the largest area and face towards the center of it. if (widest > 0) { for (int i = 0; i < TraceStep; i++) { if (sonar[i] == widest && !counting) { startIndex = i; if (i == 0) { startLen = 1; } counting = true; } if (sonar[i] != widest && counting) { if ((i) - startIndex > bigestStretch) { bigestStretch = (i) - startIndex; bigestStartIndex = startIndex; } if (startIndex == 0) { startLen = i; } counting = false; } if (sonar[i] == widest && counting && i == 19) { endLen = i - startIndex; } } int index; if (startLen + endLen > bigestStretch) { if (startLen >= endLen) { index = startLen > endLen ? startLen - endLen : endLen - startLen; } else { index = (TraceStep - 1) - (endLen - startLen); } } else { index = bigestStartIndex + (bigestStretch / 2); } float direction = (index * PIx2) / 20; return(direction); } return(null); }
/// <summary> /// <para>Finds another point near the destination. Useful when toon is 'waiting' for something /// (e.g., boat, mob repops, etc). This allows multiple people running /// the same profile to not stand on top of each other while waiting for /// something.</para> /// <para>Notes:<list type="bullet"> /// <item><description><para> * The returned Vector3 is carefully chosen. The returned Vector3 /// will not cause you to fall off a boat dock or Zeppelin landing.</para></description></item> /// </list></para> /// </summary> /// <param name="location"></param> /// <param name="maxRadius"></param> /// <returns></returns> /// <remarks>17Apr2011-12:16UTC chinajade</remarks> public static Vector3 FanOutRandom(this Vector3 location, double maxRadius) { Contract.Requires(maxRadius >= 0.0, context => "maxRadius >= 0.0"); // Optimize situations where we want a very close-by point... if (maxRadius <= 1) { return(location); } const int CYLINDER_LINE_COUNT = 12; const int MAX_TRIES = 50; const double SAFE_DISTANCE_BUFFER = 1.75; Vector3 candidateDestination = location; int tryCount; // ActiveMover is null in some cases where player is not in control of movement, // such as when on a taxi like the one for the // 'Mission: The Murketh and Shaadraz Gateways' quest (http://www.wowhead.com/quest=10146) var me = WoWMovement.ActiveMover ?? StyxWoW.Me; Contract.Requires(me != null, context => "me != null"); var myLoc = me.Location; // Most of the time we'll find a viable spot in less than 2 tries... // However, if you're standing on a pier, or small platform a // viable alternative may take 10-15 tries--its all up to the // random number generator. for (tryCount = MAX_TRIES; tryCount > 0; --tryCount) { bool[] hitResults; Vector3[] hitPoints; Func <double, double> weightedRandomRadius = (radiusMaximum) => { return ((StyxWoW.Random.Next(101) < 80) // We want a large number of the candidate magnitudes to be near the max range. // This encourages toons to 'spread out'. ? ((radiusMaximum * 0.70) + (radiusMaximum * 0.30 * StyxWoW.Random.NextDouble())) : (radiusMaximum * StyxWoW.Random.NextDouble())); }; var traceLines = new WorldLine[CYLINDER_LINE_COUNT + 1]; candidateDestination = location.AddPolarXY((TAU * StyxWoW.Random.NextDouble()), weightedRandomRadius(maxRadius), 0.0); // If destination is in the air... if (!IsOverGround(candidateDestination, 3.0)) { // If we don't have clear LoS between the specified and candidate destinations, the candidate is unsuitable... if (GameWorld.TraceLine(location, candidateDestination, TraceLineHitFlags.Collision)) { continue; } // Otherwise, we have our candidate destination... break; } // Ground-based destinations... // Build set of tracelines that can evaluate the candidate destination -- // We build a cone of lines with the cone's base at the destination's 'feet', // and the cone's point at maxRadius over the destination's 'head'. We also // include the cone 'normal' as the first entry. // 'Normal' vector var index = 0; traceLines[index].Start = candidateDestination.Add(0.0, 0.0, maxRadius); traceLines[index].End = candidateDestination.Add(0.0, 0.0, -maxRadius); // Cylinder vectors for (double turnFraction = 0.0; turnFraction < TAU; turnFraction += (TAU / CYLINDER_LINE_COUNT)) { ++index; var circlePoint = candidateDestination.AddPolarXY(turnFraction, SAFE_DISTANCE_BUFFER, 0.0); traceLines[index].Start = circlePoint.Add(0.0, 0.0, maxRadius); traceLines[index].End = circlePoint.Add(0.0, 0.0, -maxRadius); } // Evaluate the cylinder... // The result for the 'normal' vector (first one) will be the location where the // destination meets the ground. Before this MassTrace, only the candidateDestination's // X/Y values were valid. GameWorld.MassTraceLine(traceLines.ToArray(), TraceLineHitFlags.Collision, out hitResults, out hitPoints); candidateDestination = hitPoints[0]; // From 'normal', Destination with valid Z coordinate // Sanity check... // We don't want to be standing right on the edge of a drop-off (say we'e on // a plaform or pier). If there is not solid ground all around us, we reject // the candidate. Our test for validity is that the walking distance must // not be more than 20% greater than the straight-line distance to the point. // TODO: FanOutRandom PathTraversalCost on point (replace with HB's SampleMesh method instead) int viableVectorCount = hitPoints.Sum(point => ((location./*PathTraversalCost*/ Distance(point) < (location.Distance(point) * 1.20)) ? 1 : 0)); if (viableVectorCount < (CYLINDER_LINE_COUNT * 0.8)) { continue; } // If new destination is 'too close' to our current position, try again... if (myLoc.Distance(candidateDestination) <= SAFE_DISTANCE_BUFFER) { continue; } break; } // If we exhausted our tries, just go with simple destination -- if (tryCount <= 0) { candidateDestination = location; } return(candidateDestination); }
// Use this for initialization void Start() { worldLine = this.GetComponent <WorldLine> (); worldLine.MakeNewMesh(); transform.position = new Vector3(0, .25f, 0); }
float? GetFaceWaterDirection() { WoWPoint playerLoc = _me.Location; var sonar = new List<int>(TraceStep); var tracelines = new WorldLine[TraceStep * 3]; bool[] tracelineRetVals; for (int i = 0; i < TraceStep; i++) { // scans 10,15 and 20 yards from player for water at every 18 degress for (int n = 0; n < 3; n++) { WoWPoint p = (playerLoc.RayCast((i * PIx2) / TraceStep, 10 + (n * 5))); WoWPoint highPoint = p; highPoint.Z += 5; WoWPoint lowPoint = p; lowPoint.Z -= 55; tracelines[(i * 3) + n].Start = highPoint; tracelines[(i * 3) + n].End = lowPoint; } } GameWorld.MassTraceLine(tracelines, GameWorld.CGWorldFrameHitFlags.HitTestLiquid | GameWorld.CGWorldFrameHitFlags.HitTestLiquid2, out tracelineRetVals); for (int i = 0; i < TraceStep; i++) { int scan = 0; for (int n = 0; n < 3; n++) { if (tracelineRetVals[(i * 3) + n]) scan++; } sonar.Add(scan); } int widest = 0; for (int i = 0; i < TraceStep; i++) { if (sonar[i] > widest) widest = sonar[i]; } bool counting = false; int startIndex = 0, bigestStartIndex = 0, startLen = 0, endLen = 0, bigestStretch = 0; // if we found water find the largest area and face towards the center of it. if (widest > 0) { for (int i = 0; i < TraceStep; i++) { if (sonar[i] == widest && !counting) { startIndex = i; if (i == 0) startLen = 1; counting = true; } if (sonar[i] != widest && counting) { if ((i) - startIndex > bigestStretch) { bigestStretch = (i) - startIndex; bigestStartIndex = startIndex; } if (startIndex == 0) startLen = i; counting = false; } if (sonar[i] == widest && counting && i == 19) endLen = i - startIndex; } int index; if (startLen + endLen > bigestStretch) { if (startLen >= endLen) index = startLen > endLen ? startLen - endLen : endLen - startLen; else index = (TraceStep - 1) - (endLen - startLen); } else index = bigestStartIndex + (bigestStretch / 2); float direction = (index * PIx2) / 20; return direction; } return null; }
private static bool FindPoolPoint(WoWGameObject pool, out List <WoWPoint> poolPoints) { int traceStep = AutoAnglerSettings.Instance.TraceStep; const float pIx2 = 3.14159f * 2f; var traceLine = new WorldLine[traceStep]; poolPoints = new List <WoWPoint>(); // scans starting at OptimumPoolDistance2D from player for water at every 18 degress float range = OptimumPoolDistance2D; var poolRadius = GetPoolRadius(pool); var min = MinCastDistance2D - poolRadius + PoolDistTolerance; var max = MaxCastDistance2D + poolRadius - PoolDistTolerance; float step = AutoAnglerSettings.Instance.PoolRangeStep; float delta = step; float avg = (min + max) / 2f; while (true) { for (int i = 0; i < traceStep; i++) { WoWPoint p = pool.Location.RayCast((i * pIx2) / traceStep, range); WoWPoint hPoint = p; hPoint.Z += 45; WoWPoint lPoint = p; lPoint.Z -= 1; traceLine[i].Start = hPoint; traceLine[i].End = lPoint; } WoWPoint[] hitPoints; bool[] tracelineRetVals; GameWorld.MassTraceLine(traceLine, TraceLineHitFlags.Collision, out tracelineRetVals, out hitPoints); // what I'm doing here is compare the elevation of 4 corners around a point with // that point's elevation to determine if that point is too steep to stand on. var slopetraces = new List <WorldLine>(); var testPoints = new List <WoWPoint>(); for (int i = 0; i < traceStep; i++) { if (tracelineRetVals[i]) { slopetraces.AddRange(GetQuadSloopTraceLines(hitPoints[i])); testPoints.Add(hitPoints[i]); } else if (WaterWalking.IsActive || WaterWalking.CanCast) { traceLine[i].End.Z = pool.Z + 1; poolPoints.Add(traceLine[i].End); } } // fire tracelines.. bool[] lavaRetVals = null; WoWPoint[] slopeHits; using (StyxWoW.Memory.AcquireFrame()) { bool[] slopelinesRetVals; GameWorld.MassTraceLine(slopetraces.ToArray(), TraceLineHitFlags.Collision, out slopelinesRetVals, out slopeHits); if (AutoAnglerSettings.Instance.AvoidLava) { GameWorld.MassTraceLine(slopetraces.ToArray(), TraceLineHitFlags.LiquidAll, out lavaRetVals); } } // process results poolPoints.AddRange(ProcessSlopeAndLavaResults(testPoints, slopeHits, lavaRetVals)); // perform LOS checks if (poolPoints.Any()) { var losLine = new WorldLine[poolPoints.Count]; for (int i2 = 0; i2 < poolPoints.Count; i2++) { WoWPoint point = poolPoints[i2]; point.Z += 2; losLine[i2].Start = point; losLine[i2].End = pool.Location; } GameWorld.MassTraceLine(losLine, TraceLineHitFlags.Collision, out tracelineRetVals); for (int i2 = poolPoints.Count - 1; i2 >= 0; i2--) { if (tracelineRetVals[i2]) { poolPoints.RemoveAt(i2); } } } // sort pools by distance to player poolPoints.Sort((p1, p2) => p1.Distance(StyxWoW.Me.Location).CompareTo(p2.Distance(StyxWoW.Me.Location))); if (!StyxWoW.Me.IsFlying) { // if we are not flying check if we can genorate a path to points. for (int i = 0; i < poolPoints.Count;) { WoWPoint[] testP = Navigator.GeneratePath(StyxWoW.Me.Location, poolPoints[i]); if (testP.Length > 0) { return(true); } poolPoints.RemoveAt(i); poolPoints.Sort((a, b) => a.Distance(StyxWoW.Me.Location).CompareTo(b.Distance(StyxWoW.Me.Location))); } } if (poolPoints.Any()) { return(true); } bool minCaped = (OptimumPoolDistance2D - delta) < min; bool maxCaped = (OptimumPoolDistance2D + delta) > max; if (minCaped && maxCaped) { break; } if ((range <= OptimumPoolDistance2D && (OptimumPoolDistance2D + delta) <= max) || minCaped) { range = OptimumPoolDistance2D + delta; if (avg < OptimumPoolDistance2D || minCaped) { delta += step; } continue; } if ((range > OptimumPoolDistance2D && (OptimumPoolDistance2D - delta) >= min) || maxCaped) { range = OptimumPoolDistance2D - delta; if (avg >= OptimumPoolDistance2D || maxCaped) { delta += step; } } } return(false); }