Example #1
0
        /// <summary>
        /// Returns true, if water is within DISTANCE _below_ you.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="probeDistance"></param>
        /// <returns>true, if water is within DISTANCE _below_ you.</returns>
        /// <remarks>17Apr2011-12:16UTC chinajade</remarks>
        public static bool IsOverWater(this WoWPoint location, double probeDistance)
        {
            Contract.Requires(probeDistance >= 0.0, context => "distance >= 0.0");

            return(GameWorld.TraceLine(location.Add(0.0, 0.0, 1.0),
                                       location.Add(0.0, 0.0, -probeDistance),
                                       TraceLineHitFlags.LiquidAll));
        }
        /// <summary>
        /// Returns true, if ground is within DISTANCE _below_ you.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="distance"></param>
        /// <returns>true, if ground is within DISTANCE _below_ you.</returns>
        /// <remarks>17Apr2011-12:16UTC chinajade</remarks>
        public static bool IsOverGround(this WoWPoint location, double distance)
        {
            QuestBehaviorBase.ContractRequires(distance >= 0.0, context => "distance >= 0.0");

            return(GameWorld.TraceLine(location.Add(0.0, 0.0, 1.0),
                                       location.Add(0.0, 0.0, -distance),
                                       GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures));
        }
        /// <summary>
        /// Returns true, if ground is within DISTANCE _below_ you.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="distance"></param>
        /// <returns>true, if ground is within DISTANCE _below_ you.</returns>
        public static bool      IsOverGround(this WoWPoint location,
                                             double distance)
        {
            WoWPoint hitLocation;

            return(GameWorld.TraceLine(location.Add(0.0, 0.0, 1.0),
                                       location.Add(0.0, 0.0, -distance),
                                       GameWorld.CGWorldFrameHitFlags.HitTestGroundAndStructures,
                                       out hitLocation));
        }
Example #4
0
        // Returns WoWPoint.Empty if unable to locate water's surface
        public static WoWPoint WaterSurface(this WoWPoint location)
        {
            WoWPoint hitLocation;
            WoWPoint locationUpper = location.Add(0.0, 0.0, 2000.0);
            WoWPoint locationLower = location.Add(0.0, 0.0, -2000.0);

            var hitResult = (GameWorld.TraceLine(locationUpper,
                                                 locationLower,
                                                 TraceLineHitFlags.LiquidAll,
                                                 out hitLocation));

            return(hitResult ? hitLocation : WoWPoint.Empty);
        }
        // Returns WoWPoint.Empty if unable to locate water's surface
        public static WoWPoint WaterSurface(this WoWPoint location)
        {
            WoWPoint hitLocation;
            bool     hitResult;
            WoWPoint locationUpper = location.Add(0.0, 0.0, 2000.0);
            WoWPoint locationLower = location.Add(0.0, 0.0, -2000.0);

            hitResult = (GameWorld.TraceLine(locationUpper,
                                             locationLower,
                                             (GameWorld.CGWorldFrameHitFlags.HitTestLiquid
                                              | GameWorld.CGWorldFrameHitFlags.HitTestLiquid2),
                                             out hitLocation));

            return(hitResult ? hitLocation : WoWPoint.Empty);
        }
        /// <summary>
        /// Returns true, if water is within DISTANCE _below_ you.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="distance"></param>
        /// <returns>true, if water is within DISTANCE _below_ you.</returns>
        public static bool      IsOverWater(this WoWPoint location,
                                            double distance)
        {
            WoWPoint hitLocation;
            WoWPoint locationAbove = location.Add(0.0, 0.0, 1.0);
            WoWPoint locationBelow = location.Add(0.0, 0.0, -distance);

            return(GameWorld.TraceLine(locationAbove,
                                       locationBelow,
                                       GameWorld.CGWorldFrameHitFlags.HitTestLiquid,
                                       out hitLocation) ||
                   GameWorld.TraceLine(locationAbove,
                                       locationBelow,
                                       GameWorld.CGWorldFrameHitFlags.HitTestLiquid2,
                                       out hitLocation));
        }
Example #7
0
 public static WoWPoint AddPolarXY(this WoWPoint wowPoint,
                                   double xyHeadingInRadians,
                                   double distance,
                                   double zModifier)
 {
     return(wowPoint.Add((Math.Cos(xyHeadingInRadians) * distance),
                         (Math.Sin(xyHeadingInRadians) * distance),
                         zModifier));
 }
Example #8
0
        // 29Apr2013-09:51UTC chinajade
        public static double HeightOverGroundOrWater(this WoWPoint location, double probeDistance = 300.0)
        {
            WoWPoint hitLocation;
            WoWPoint destination = location.Add(0.0, 0.0, -probeDistance);

            var isObstructed = GameWorld.TraceLine(location, destination,
                                                   TraceLineHitFlags.Collision
                                                   | TraceLineHitFlags.LiquidAll,
                                                   out hitLocation);

            return(isObstructed
                ? location.Distance(hitLocation)
                : double.MaxValue);
        }
Example #9
0
        // 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);
        }
Example #10
0
        // Returns WoWPoint.Empty if unable to locate water's surface
        public static WoWPoint WaterSurface(WoWPoint location)
        {
            WoWPoint hitLocation;
            bool hitResult;
            WoWPoint locationUpper = location.Add(0.0f, 0.0f, 2000.0f);
            WoWPoint locationLower = location.Add(0.0f, 0.0f, -2000.0f);

            hitResult = (GameWorld.TraceLine(locationUpper, locationLower, TraceLineHitFlags.LiquidAll, out hitLocation));

            return (hitResult ? hitLocation : WoWPoint.Empty);
        }
Example #11
0
        // Returns WoWPoint.Empty if unable to locate water's surface
        public static bool IsUnderWater(WoWPoint location)
        {
            WoWPoint waterLocation;
            bool hitResult;
            WoWPoint locationUpper = location.Add(0.0f, 0.0f, 2000.0f);
            WoWPoint locationLower = location.Add(0.0f, 0.0f, -2000.0f);

            hitResult = (GameWorld.TraceLine(locationUpper, locationLower, TraceLineHitFlags.LiquidAll, out waterLocation));

            if (!hitResult) return false;

            return (location.Z < waterLocation.Z);
        }
Example #12
0
        /// <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 WoWPoint is carefully chosen.  The returned WoWPoint
        /// 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 WoWPoint FanOutRandom(this WoWPoint location, double maxRadius)
        {
            Contract.Requires(maxRadius >= 0.0, context => "maxRadius >= 0.0");

            // Optimize situations where we want the exact point...
            if (maxRadius <= Navigator.PathPrecision)
            {
                return(location);
            }

            const int    CYLINDER_LINE_COUNT  = 12;
            const int    MAX_TRIES            = 50;
            const double SAFE_DISTANCE_BUFFER = 1.75;

            WoWPoint 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;
                WoWPoint[]            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.
                int viableVectorCount = hitPoints.Sum(point => ((location.PathTraversalCost(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);
        }