public override RunStatus Tick(object context) { try { return(base.Tick(context)); } catch (Exception except) { if (except.GetType() != typeof(ThreadAbortException)) { if (QuestBehaviorCoreSettings.Instance.LogProfileContextOnExceptions) { QuestBehaviorBase.LogError("PROFILE EXCEPTION CONTEXT: {0}", QuestBehaviorBase.GetProfileReference(_questBehaviorBase.Element)); SystemSounds.Asterisk.Play(); } else { QuestBehaviorBase.LogDeveloperInfo("PROFILE EXCEPTION CONTEXT: {0}", QuestBehaviorBase.GetProfileReference(_questBehaviorBase.Element)); } } throw; } }
/// <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> /// Calculates the distance between START and DESTINATION if the travel must be conducted /// over a surface (i.e., instead of flying). This is most helpful in tunnels where a mob /// can be within X feet of you, but above or below you. For such mobs, the direct distance /// is X feet, but the path you must take through the tunnels may be much much longer. /// </summary> /// <param name="start"></param> /// <param name="destination"></param> /// <returns></returns> /// <remarks>17Apr2011-12:16UTC chinajade</remarks> public static float SurfacePathDistance(this WoWPoint start, WoWPoint destination) { WoWPoint[] groundPath = Navigator.GeneratePath(start, destination) ?? new WoWPoint[0]; // We define an invalid path to be of 'infinite' length if (groundPath.Length <= 0) { // For targets in the air, we will be unable to calculate the // surface path to them. If we're flying, we still want // a gauging of the distance, so we use half the max float range, // and tack on the line-of-site distance to the unit. // This allows sane ordering evaluations in LINQ queries, yet // still returns something close enough to 'infinite' to make // using the path highly undesirable. return((float.MaxValue / 2) + start.Distance(destination)); } // Include distance it takes us to get from start point to first point in path... float pathDistance = start.Distance(groundPath[0]); // Include distance it takes us to get from last point in path to destination... pathDistance += groundPath[groundPath.Length - 1].Distance(destination); // Include distance for each point in path... for (int i = 0; i < (groundPath.Length - 1); ++i) { pathDistance += groundPath[i].Distance(groundPath[i + 1]); } // Sanity check... QuestBehaviorBase.ContractProvides( pathDistance >= start.Distance(destination), context => "Surface path distance must be equal to or greater than straight-line distance."); return(pathDistance); }
// 30May2013-08:11UTC chinajade public static List <string> CheckCore( WoWObject wowObject, QuestBehaviorBase coreAttributes) { var exclusionReasons = new List <string>(); const BlacklistFlags interestingBlacklistFlags = BlacklistFlags.Combat | BlacklistFlags.Interact | BlacklistFlags.Pull; if (!Query.IsViable(wowObject)) { exclusionReasons.Add("[NotViable]"); return(exclusionReasons); } foreach (var blacklistEntry in Blacklist.GetEntries(wowObject.Guid)) { if ((blacklistEntry.Flags & interestingBlacklistFlags) == 0) { continue; } var blacklistInfo = new List <string>(); var blacklistTimeRemaining = blacklistEntry.Started + blacklistEntry.Length - DateTime.Now; blacklistInfo.Add(string.Format("Time({0}/{1})", Utility.PrettyTime(blacklistTimeRemaining), Utility.PrettyTime(blacklistEntry.Length))); if (blacklistEntry.Flags.HasFlag(BlacklistFlags.Combat)) { blacklistInfo.Add("ForCombat"); } if (blacklistEntry.Flags.HasFlag(BlacklistFlags.Interact)) { blacklistInfo.Add("ForInteract"); } if (blacklistEntry.Flags.HasFlag(BlacklistFlags.Loot)) { blacklistInfo.Add("ForLoot"); } if (blacklistEntry.Flags.HasFlag(BlacklistFlags.Node)) { blacklistInfo.Add("ForNode"); } if (blacklistEntry.Flags.HasFlag(BlacklistFlags.Pull)) { blacklistInfo.Add("ForPull"); } exclusionReasons.Add(string.Format("Blacklisted({0})", string.Join(",", blacklistInfo))); } if (!Query.IsStateMatch_IgnoreMobsInBlackspots(wowObject, coreAttributes.IgnoreMobsInBlackspots)) { var coveringBlackspots = from blackspot in Query.FindCoveringBlackspots(wowObject.Location) select string.Format("Blackspot({0}, r:{1})", blackspot.Location, blackspot.Radius); exclusionReasons.Add(string.Format("InBlackspot(object @{0}; {1})", wowObject.Location, string.Join(", ", coveringBlackspots))); } if (!Query.IsStateMatch_MeshNavigable(wowObject, coreAttributes.MovementBy)) { exclusionReasons.Add("NotMeshNavigable"); } if (Query.IsInCompetition(wowObject, coreAttributes.NonCompeteDistance)) { int playerCount = Query.FindPlayersNearby(wowObject.Location, coreAttributes.NonCompeteDistance).Count(); if (playerCount > 0) { exclusionReasons.Add(string.Format("InCompetition({0} players within {1:F1}, expires in {2})", playerCount, coreAttributes.NonCompeteDistance, Utility.PrettyTime(Query.InCompetitionTimeRemaining(wowObject)))); } var wowUnit = wowObject.ToUnit(); bool isTagged = (wowUnit != null) && !Query.IsSharedWorldResource(wowUnit) && !wowUnit.IsUntagged(); if (isTagged) { exclusionReasons.Add("TaggedByOtherPlayer"); } } return(exclusionReasons); }
public ExceptionCatchingWrapper(QuestBehaviorBase questBehaviorBase, Composite unwrappedChild) : base(unwrappedChild) { _questBehaviorBase = questBehaviorBase; }
/// <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) { QuestBehaviorBase.ContractRequires(maxRadius >= 0.0, context => "maxRadius >= 0.0"); 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); }
private double UtilAzimuthCurrentAbsolute() { return(QuestBehaviorBase.NormalizeAngleToPi(Lua.GetReturnVal <double>("return VehicleAimGetAngle();", 0))); }