private WoWUnit FindTarget(WoWPoint location) { WoWUnit target = null; if (_targetGuid.IsValid) { target = ObjectManager.GetObjectByGuid <WoWUnit>(_targetGuid); } if (target != null && target.IsAlive // if rescuing NPCs then we don't want to include those rescued by other players. && (DropPassengerButton == 0 || !IsRescuedByOtherPlayer(target)) && !Blacklist.Contains(target, BlacklistFlags.Combat | BlacklistFlags.Interact)) { return(target); } target = ObjectManager.GetObjectsOfType <WoWUnit>() .Where(u => !u.IsDead && NpcList.Contains((int)u.Entry) && !Blacklist.Contains(u, BlacklistFlags.Combat | BlacklistFlags.Interact) // if rescuing NPCs then we don't want to include those rescued by other players. && (DropPassengerButton == 0 || !IsRescuedByOtherPlayer(target)) && u.Location.Distance2D(location) < NpcScanRange) .OrderBy(u => location.Distance2DSqr(u.Location)) .FirstOrDefault(); if (target != null) { _targetGuid = target.Guid; } return(target); }
/// <summary>Determines whether <paramref name="myLoc" /> is within a tolerable proximity of <paramref name="location" />.</summary> /// <param name="myLoc">My loc.</param> /// <param name="location">The location.</param> /// <param name="tolerance">The tolerance. Default: <see cref="Navigator.PathPrecision"/></param> /// <returns></returns> public static bool AtLocation(WoWPoint myLoc, WoWPoint location, float?tolerance) { var tol = tolerance ?? Navigator.PathPrecision; // We are checking if point is in an upright cylinder whose center is positioned at 'location', // radius set to 'tolerance' and height set to max(4.5, 'tolerance') x 2. // This is the most suitable method when using mesh navigation because the mesh is often above or below the // actual ingame terrain so there's a need to clamp the tolerance along the Z axis to an amount that // is greater then the maximum terrain/mesh Z coord difference return(myLoc.Distance2DSqr(location) <= tol * tol && Math.Abs(myLoc.Z - location.Z) <= Math.Max(4.5f, tol)); }
/// <summary>Determines if <paramref name="myPos"/> is at <paramref name="otherPos"/></summary> private bool AtLocation(WoWPoint myPos, WoWPoint otherPos) { // We are using cylinder distance comparison because often times we want faily high precision // but need an increased tolerance in the z coord due to 'otherPos' sometimes being below terrain. if (myPos.Distance2DSqr(otherPos) > RoughDestination.ArrivalTolerance * RoughDestination.ArrivalTolerance) { return(false); } var zTolerance = Math.Max(4.5f, RoughDestination.ArrivalTolerance); return(Math.Abs(otherPos.Z - myPos.Z) < zTolerance); }
/// <summary> /// locates safe point away from enemies /// </summary> /// <param name="ptOrigin">start point for search</param> /// <param name="minSafeDist">min distance to be safe</param> /// <returns></returns> public WoWPoint FindLocationOriginal(WoWPoint ptOrigin) { WoWPoint destinationLocation = new WoWPoint(); List<WoWPoint> mobLocations = new List<WoWPoint>(); int arcIncrement = 360 / RaysToCheck; mobLocations = AllEnemyMobLocations; double minSafeDistSqr = MinSafeDistance * MinSafeDistance; double degreesFacing = (Me.RenderFacing * 180f) / Math.PI; // Logger.WriteDebug( Color.Cyan, "Facing {0:F0}d {1:F2}r Searching for {2:F1} yard mob free area", degreesFacing, Me.RenderFacing, MinSafeDistance); for (int arcIndex = 0; arcIndex < RaysToCheck ; arcIndex++) { float degreesFrom = 180; if ((arcIndex & 1) == 0) degreesFrom += (arcIndex >> 1) * arcIncrement; else degreesFrom -= (arcIndex >> 1) * arcIncrement; for (float distFromOrigin = MinScanDistance; distFromOrigin <= MaxScanDistance ; distFromOrigin += IncrementScanDistance ) { float heading = (float)(degreesFrom * Math.PI / 180f); heading -= Me.RenderFacing; destinationLocation = ptOrigin.RayCast((float)(degreesFrom * Math.PI / 180f), distFromOrigin); double mobDistSqr = destinationLocation.Distance2DSqr(NearestMobLoc(destinationLocation, mobLocations)); if (mobDistSqr <= minSafeDistSqr) continue; //if (Navigator.CanNavigateFully(Me.Location, destinationLocation)) if (Navigator.GeneratePath(Me.Location, destinationLocation).Length <= 0) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed path check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); continue; } if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(Me.Location, destinationLocation)) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); continue; } if (MobToRunFrom != null) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSpellSight(destinationLocation, MobToRunFrom.Location)) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); continue; } } Logger.WriteDebug(Color.Cyan, "Found mob-free location ({0:F1} yd radius) at degrees={1:F1} dist={2:F1}", MinSafeDistance, degreesFrom, distFromOrigin); return destinationLocation; } } Logger.WriteDebug(Color.Cyan, "No mob-free location ({0:F1} yd radius) found within {1:F1} yds", MinSafeDistance, MaxScanDistance ); return WoWPoint.Empty; }
public WoWPoint FindLocation(WoWPoint ptOrigin) { DateTime startFind = DateTime.Now; int countPointsChecked = 0; int countFailToPointNav = 0; int countFailRange = 0; int countFailSafe = 0; int countFailToPointLoS = 0; int countFailToMobLoS = 0; double furthestNearMobDistSqr = 0f; WoWPoint ptFurthest = WoWPoint.Empty; bool reallyCheckRangeToLineOfSightMob = CheckRangeToLineOfSightMob && Me.GotTarget; WoWPoint ptAdjOrigin = ptOrigin; ptAdjOrigin.Z += 1f; WoWPoint ptDestination = new WoWPoint(); List<WoWPoint> mobLocations = new List<WoWPoint>(); float arcIncrement = ((float)Math.PI * 2) / RaysToCheck; mobLocations = AllEnemyMobLocationsToCheck; double minSafeDistSqr = MinSafeDistance * MinSafeDistance; float baseDestinationFacing = MobToRunFrom == null ? Me.RenderFacing + (float)Math.PI : Styx.Helpers.WoWMathHelper.CalculateNeededFacing(MobToRunFrom.Location, Me.Location); // Logger.WriteDebug( Color.Cyan, "SafeArea: search near {0:F0}d @ {1:F1} yds for mob free area", RadiansToDegrees(baseDestinationFacing), MinSafeDistance); for (int arcIndex = 0; arcIndex < RaysToCheck; arcIndex++) { // rather than tracing around the circle, toggle between clockwise and counter clockwise for each test // .. so we favor a position furthest away from mob float checkFacing = baseDestinationFacing; if ((arcIndex & 1) == 0) checkFacing += arcIncrement * (arcIndex >> 1); else checkFacing -= arcIncrement * ((arcIndex >> 1) + 1); for (float distFromOrigin = MinScanDistance; distFromOrigin <= MaxScanDistance; distFromOrigin += IncrementScanDistance) { countPointsChecked++; ptDestination = ptOrigin.RayCast(checkFacing, distFromOrigin); if (!Navigator.CanNavigateFully(Me.Location, ptDestination)) { // Logger.WriteDebug( Color.Cyan, "Safe Location failed navigation check for degrees={0:F1} dist={1:F1}", RadiansToDegrees(checkFacing), distFromOrigin); countFailToPointNav++; continue; } WoWPoint ptNearest = NearestMobLoc(ptDestination, mobLocations); if (ptNearest == WoWPoint.Empty) { if (furthestNearMobDistSqr < minSafeDistSqr) { furthestNearMobDistSqr = minSafeDistSqr; ptFurthest = ptDestination; // set best available if others fail } } else { double mobDistSqr = ptDestination.Distance2DSqr(ptNearest); if (furthestNearMobDistSqr < mobDistSqr) { furthestNearMobDistSqr = mobDistSqr; ptFurthest = ptDestination; // set best available if others fail } if (mobDistSqr <= minSafeDistSqr) { countFailSafe++; continue; } } if (reallyCheckRangeToLineOfSightMob && RangeToLineOfSightMob < ptDestination.Distance(LineOfSightMob.Location) - LineOfSightMob.MeleeDistance()) { countFailRange++; continue; } if (CheckLineOfSightToSafeLocation) { WoWPoint ptAdjDest = ptDestination; ptAdjDest.Z += 1f; if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptAdjOrigin, ptAdjDest)) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToPointLoS++; continue; } } if (CheckSpellLineOfSightToMob && LineOfSightMob != null) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSpellSight(ptDestination, LineOfSightMob.Location)) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptDestination, LineOfSightMob.Location)) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToMobLoS++; continue; } } } Logger.WriteDebug(Color.Cyan, "SafeArea: Found mob-free location ({0:F1} yd radius) at degrees={1:F1} dist={2:F1} on point check# {3}", MinSafeDistance, WoWMathHelper.RadiansToDegrees(checkFacing), distFromOrigin, countPointsChecked); Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.Now - startFind).TotalMilliseconds); return ptDestination; } } Logger.WriteDebug(Color.Cyan, "SafeArea: No mob-free location ({0:F1} yd radius) found within {1:F1} yds ({2} checked, {3} nav, {4} not safe, {5} range, {6} pt los, {7} mob los)", MinSafeDistance, MaxScanDistance, countPointsChecked, countFailToPointNav, countFailSafe, countFailRange, countFailToPointLoS, countFailToMobLoS); if (ChooseSafestAvailable && ptFurthest != WoWPoint.Empty) { Logger.WriteDebug(Color.Cyan, "SafeArea: choosing best available spot in {0:F1} yd radius where closest mob is {1:F1} yds", MinSafeDistance, Math.Sqrt(furthestNearMobDistSqr)); Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.Now - startFind).TotalMilliseconds); return ChooseSafestAvailable ? ptFurthest : WoWPoint.Empty; } Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.Now - startFind).TotalMilliseconds); return WoWPoint.Empty; }
public WoWPoint FindLocation(WoWPoint ptOrigin) { DateTime startFind = DateTime.UtcNow; int countPointsChecked = 0; int countFailDiff = 0; int countFailTrace = 0; int countFailToPointNav = 0; int countFailRange = 0; int countFailSafe = 0; int countFailToPointLoS = 0; int countFailToMobLoS = 0; TimeSpan spanTrace = TimeSpan.Zero; TimeSpan spanNav = TimeSpan.Zero; double furthestNearMobDistSqr = 0f; WoWPoint ptFurthest = WoWPoint.Empty; float facingFurthest = 0f; bool reallyCheckRangeToLineOfSightMob = CheckRangeToLineOfSightMob && Me.GotTarget(); WoWPoint ptAdjOrigin = ptOrigin; // ptAdjOrigin.Z += 1f; // comment out origin adjustment since using GetTraceLinePos() WoWPoint ptDestination = new WoWPoint(); List<WoWPoint> mobLocations = new List<WoWPoint>(); float arcIncrement = ((float)Math.PI * 2) / RaysToCheck; mobLocations = AllEnemyMobLocationsToCheck; double minSafeDistSqr = MinSafeDistance * MinSafeDistance; #if OLD_WAY float baseDestinationFacing = MobToRunFrom == null ? Me.RenderFacing + (float)Math.PI : Styx.Helpers.WoWMathHelper.CalculateNeededFacing(MobToRunFrom.Location, Me.Location); #else float baseDestinationFacing; if (PreferredDirection == Disengage.Direction.None && MobToRunFrom != null) baseDestinationFacing = Styx.Helpers.WoWMathHelper.CalculateNeededFacing(MobToRunFrom.Location, Me.Location); else if (PreferredDirection == Disengage.Direction.Frontwards) baseDestinationFacing = Me.RenderFacing; else // if (PreferredDirection == Disengage.Direction.Backwards) baseDestinationFacing = Me.RenderFacing + (float)Math.PI; #endif Logger.WriteDebug( Color.Cyan, "SafeArea: facing {0:F0} degrees, looking for safespot towards {1:F0} degrees", WoWMathHelper.RadiansToDegrees(Me.RenderFacing), WoWMathHelper.RadiansToDegrees(baseDestinationFacing) ); for (int arcIndex = 0; arcIndex < RaysToCheck; arcIndex++) { // rather than tracing around the circle, toggle between clockwise and counter clockwise for each test // .. so we favor a position furthest away from mob float checkFacing = baseDestinationFacing; if ((arcIndex & 1) == 0) checkFacing += arcIncrement * (arcIndex >> 1); else checkFacing -= arcIncrement * ((arcIndex >> 1) + 1); checkFacing = WoWMathHelper.NormalizeRadian(checkFacing); for (float distFromOrigin = MinScanDistance; distFromOrigin <= MaxScanDistance; distFromOrigin += IncrementScanDistance) { countPointsChecked++; ptDestination = ptOrigin.RayCast(checkFacing, distFromOrigin); Logger.WriteDebug("SafeArea: checking {0:F1} degrees at {1:F1} yds", WoWMathHelper.RadiansToDegrees(checkFacing), distFromOrigin); DateTime start = DateTime.UtcNow; bool failTrace = Movement.MeshTraceline(Me.Location, ptDestination); spanTrace += DateTime.UtcNow - start; bool failNav; if (DirectPathOnly) { failNav = failTrace; spanNav = spanTrace; } else { start = DateTime.UtcNow; failNav = !Navigator.CanNavigateFully(Me.Location, ptDestination); spanNav += DateTime.UtcNow - start; } if (failTrace) countFailTrace++; if (failTrace != failNav) countFailDiff++; if (failNav) { // Logger.WriteDebug( Color.Cyan, "Safe Location failed navigation check for degrees={0:F1} dist={1:F1}", RadiansToDegrees(checkFacing), distFromOrigin); countFailToPointNav++; continue; } WoWPoint ptNearest = NearestMobLoc(ptDestination, mobLocations); if (ptNearest == WoWPoint.Empty) { if (furthestNearMobDistSqr < minSafeDistSqr) { furthestNearMobDistSqr = minSafeDistSqr; ptFurthest = ptDestination; // set best available if others fail facingFurthest = checkFacing; } } else { double mobDistSqr = ptDestination.Distance2DSqr(ptNearest); if (furthestNearMobDistSqr < mobDistSqr) { furthestNearMobDistSqr = mobDistSqr; ptFurthest = ptDestination; // set best available if others fail facingFurthest = checkFacing; } if (mobDistSqr <= minSafeDistSqr) { countFailSafe++; continue; } } if (reallyCheckRangeToLineOfSightMob && RangeToLineOfSightMob < ptDestination.Distance(LineOfSightMob.Location) - LineOfSightMob.MeleeDistance()) { countFailRange++; continue; } if (CheckLineOfSightToSafeLocation) { WoWPoint ptAdjDest = ptDestination; ptAdjDest.Z += 1f; if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptAdjOrigin, ptAdjDest)) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToPointLoS++; continue; } } if (CheckSpellLineOfSightToMob && LineOfSightMob != null) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSpellSight(ptDestination, LineOfSightMob.GetTraceLinePos())) { if (!Styx.WoWInternals.World.GameWorld.IsInLineOfSight(ptDestination, LineOfSightMob.GetTraceLinePos())) { // Logger.WriteDebug( Color.Cyan, "Mob-free location failed line of sight check for degrees={0:F1} dist={1:F1}", degreesFrom, distFromOrigin); countFailToMobLoS++; continue; } } } Logger.WriteDebug(Color.Cyan, "SafeArea: Found mob-free location ({0:F1} yd radius) at degrees={1:F1} dist={2:F1} on point check# {3} at {4}, {5}, {6}", MinSafeDistance, WoWMathHelper.RadiansToDegrees(checkFacing), distFromOrigin, countPointsChecked, ptDestination.X, ptDestination.Y, ptDestination.Z); Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); Logger.WriteDebug(Color.Cyan, "SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); Logger.WriteDebug(Color.Cyan, "SafeArea: stats for ({0:F1} yd radius) found within {1:F1} yds ({2} checked, {3} nav, {4} not safe, {5} range, {6} pt los, {7} mob los, {8} mesh trace)", MinSafeDistance, MaxScanDistance, countPointsChecked, countFailToPointNav, countFailSafe, countFailRange, countFailToPointLoS, countFailToMobLoS, countFailTrace); return ptDestination; } } Logger.WriteDebug(Color.Cyan, "SafeArea: No mob-free location ({0:F1} yd radius) found within {1:F1} yds ({2} checked, {3} nav, {4} not safe, {5} range, {6} pt los, {7} mob los, {8} mesh trace)", MinSafeDistance, MaxScanDistance, countPointsChecked, countFailToPointNav, countFailSafe, countFailRange, countFailToPointLoS, countFailToMobLoS, countFailTrace); if (ChooseSafestAvailable && ptFurthest != WoWPoint.Empty) { Logger.WriteDebug(Color.Cyan, "SafeArea: choosing best available spot in {0:F1} yd radius where closest mob is {1:F1} yds", MinSafeDistance, Math.Sqrt(furthestNearMobDistSqr)); Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); Logger.WriteDebug(Color.Cyan, "SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); return ChooseSafestAvailable ? ptFurthest : WoWPoint.Empty; } Logger.WriteDebug(Color.Cyan, "SafeArea: processing took {0:F0} ms", (DateTime.UtcNow - startFind).TotalMilliseconds); Logger.WriteDebug(Color.Cyan, "SafeArea: meshtrace took {0:F0} ms / fullynav took {1:F0} ms", spanTrace.TotalMilliseconds, spanNav.TotalMilliseconds); return WoWPoint.Empty; }
/// <summary>Finds clustered targets</summary> /// <param name="radius">radius</param> /// <param name="minDistance">minimum distance</param> /// <param name="maxDistance">maximum distance</param> /// <param name="minTargets">minimum targets to qualify</param> /// <param name="playersOnly">true for players only</param> /// <returns>The find cluster targets.</returns> public static WoWPoint FindClusterTargets(double radius, double minDistance, double maxDistance, int minTargets, bool playersOnly) { List<WoWUnit> hostile = ObjectManager.GetObjectsOfType<WoWUnit>(true, false); var avoid = new List<WoWUnit>(); var maxDistance2 = (maxDistance + radius) * (maxDistance + radius); if (playersOnly) { hostile = hostile.Where(x => x.IsPlayer && IsAttackable(x) && x.Distance2DSqr < maxDistance2).ToList(); } else { hostile = hostile.Where(x => !x.IsPlayer && IsAttackable(x) && x.Distance2DSqr < maxDistance2).ToList(); avoid = hostile.Where( x => // check for controlled units, like sheep etc UnitIsControlled(x, true)).ToList(); } if (hostile.Count < minTargets) { return WoWPoint.Empty; } var score = minTargets - 1; var best = WoWPoint.Empty; for (var x = Me.Location.X - maxDistance; x <= Me.Location.X + maxDistance; x++) { for (var y = Me.Location.Y - maxDistance; y <= Me.Location.Y + maxDistance; y++) { var spot = new WoWPoint(x, y, Me.Location.Z); var dSquare = spot.Distance2DSqr(Me.Location); if (dSquare > maxDistance * maxDistance || dSquare < minDistance * minDistance) { continue; } if (avoid.Any(t => t.Location.Distance2DSqr(spot) <= radius * radius)) { continue; } var hits = hostile.Count(t => t.Location.DistanceSqr(spot) < radius * radius); if (hits > score) { best = spot; score = hits; CLULogger.DiagnosticLog("ClusteredTargets(range=" + minDistance + "-" + maxDistance + ", radius=" + radius + ") => SCORE=" + score + " at " + spot); foreach (var u in hostile.Where(t => t.Location.DistanceSqr(spot) < radius * radius)) CLULogger.DiagnosticLog(" -> " + CLULogger.SafeName(u) + " " + u.Level); CLULogger.DiagnosticLog("---------------------"); } } } return best; }