コード例 #1
0
        // CreateBehavior supplied by QuestBehaviorBase.
        // Instead, provide CreateMainBehavior definition.

        // Dispose provided by QuestBehaviorBase.

        // IsDone provided by QuestBehaviorBase.
        // Call the QuestBehaviorBase.BehaviorDone() method when you want to indicate your behavior is complete.

        // OnFinished provided by QuestBehaviorBase.

        public override void OnStart()
        {
            // Acquisition and checking of any sub-elements go here.
            // A common example:
            //     HuntingGrounds = HuntingGroundsType.GetOrCreate(Element, "HuntingGrounds", HuntingGroundCenter);
            //     IsAttributeProblem |= HuntingGrounds.IsAttributeProblem;

            // Let QuestBehaviorBase do basic initialization of the behavior, deal with bad or deprecated attributes,
            // capture configuration state, install BT hooks, etc.  This will also update the goal text.
            var isBehaviorShouldRun = OnStart_QuestBehaviorCore();

            // If the quest is complete, this behavior is already done...
            // So we don't want to falsely inform the user of things that will be skipped.
            if (isBehaviorShouldRun)
            {
                // The BotStop handler will remove the "use when" activities...
                // Note, we only want to hook BotStopped once for this behavior.
                if (!s_persistedIsOnBotStopHooked)
                {
                    BotEvents.OnBotStopped      += BotEvents_OnBotStopped;
                    s_persistedIsOnBotStopHooked = true;
                }

                if (!s_persistedIsOnNewProfileLoadedHooked)
                {
                    BotEvents.Profile.OnNewProfileLoaded += BotEvents_OnNewProfileLoaded;
                    s_persistedIsOnNewProfileLoadedHooked = true;
                }

                switch (Command)
                {
                case CommandType.Disable:
                    ActionSetEnableState(false);
                    break;

                case CommandType.Enable:
                    ActionSetEnableState(true);
                    break;

                case CommandType.ShowActivities:
                    ActionShowActivities();
                    break;

                case CommandType.Remove:
                    ActionRemove();
                    break;

                case CommandType.Update:
                    IUseWhenPredicate useWhenPredicate =
                        (UseAtInterval > TimeSpan.Zero)
                            ? (IUseWhenPredicate) new UseWhenPredicate_TimeElapse(UseAtInterval,
                                                                                  AllowUseDuringCombat,
                                                                                  AllowUseInVehicle,
                                                                                  AllowUseWhileFlying,
                                                                                  AllowUseWhileMounted)
                            : (IUseWhenPredicate) new UseWhenPredicate_FuncEval(UseWhen,
                                                                                AllowUseDuringCombat,
                                                                                AllowUseInVehicle,
                                                                                AllowUseWhileFlying,
                                                                                AllowUseWhileMounted);

                    ActionUpdate(useWhenPredicate, StopMovingToConductActivity);
                    break;

                default:
                    QBCLog.MaintenanceError("Unhandled action type of '{0}'.", Command);
                    TreeRoot.Stop();
                    return;
                }

                // Install or remove behavior as needed...
                // We need to install the hook when its not present, AND there is something to execute.
                // We remove the hook if there is nothing left to execute.  This betters the user's experience,
                // by maximizing performance.
                // NB: We cannot simply override the methods provided by QuestBehaviorBase, because this behavior
                // is unusual.  We want these hooks to remain after this behavior terminates.  If we use the
                // QuestBehaviorBase-provide facilities (e.g., override the methods), then the hooks would be
                // cleaned up (e.g., removed) when this behavior exits.
                if (s_persistedActivities.Count > 0)
                {
                    DoWhenHookInstall();
                }

                if (s_persistedActivities.Count <= 0)
                {
                    DoWhenHookRemove();
                }

                BehaviorDone();
            }
        }
コード例 #2
0
 private void BotEvents_OnNewProfileLoaded(EventArgs args)
 {
     QBCLog.DeveloperInfo(CfbContextForHook, "OnNewProfileLoaded cleanup...");
     // Uninstall the behavior from the tree...
     DoWhenHookRemove();
 }
コード例 #3
0
        public void Loopstuff()
        {
            while (true)
            {
                ObjectManager.Update();
                if (Me.IsQuestComplete(QuestId))
                {
                    _isBehaviorDone = true;
                    break;
                }

                try
                {
                    if (!Query.IsInVehicle())
                    {
                        var turret = GetTurret();
                        if (turret != null)
                        {
                            if (turret.DistanceSqr > 5 * 5)
                            {
                                //Navigator.MoveTo(turret.Location);
                            }
                            else
                            {
                                turret.Interact();
                            }
                        }
                        else
                        {
                            QBCLog.Info("Unable to find turret");
                        }
                    }
                    else
                    {
                        if (Me.CurrentTarget != null &&
                            (Me.CurrentTarget.Distance < 60 || Me.CurrentTarget.InLineOfSight))
                        {
                            WoWMovement.ClickToMove(Me.CurrentTarget.Location);
                            //WoWMovement.ClickToMove(Me.CurrentTarget.Location.RayCast(Me.CurrentTarget.Rotation, 20));
                            var x = ObjectManager.GetObjectsOfType <WoWUnit>().FirstOrDefault(z => z.CharmedByUnit == Me);

                            Tripper.Tools.Math.Vector3 v = Me.CurrentTarget.Location - Me.Location;
                            v.Normalize();
                            Lua.DoString(
                                string.Format(
                                    "VehicleAimIncrement(({0} - VehicleAimGetAngle())); CastPetAction(1);CastPetAction(2);",
                                    Math.Asin(v.Z).ToString()));
                        }
                        else
                        {
                            if (!Me.IsQuestObjectiveComplete(QuestId, 1))
                            {
                                if (Marksmen != null)
                                {
                                    Marksmen.Target();
                                }
                            }
                            else if (!Me.IsQuestObjectiveComplete(QuestId, 2))
                            {
                                if (Cannoner != null)
                                {
                                    Cannoner.Target();
                                }
                            }
                            else if (!Me.IsQuestObjectiveComplete(QuestId, 3))
                            {
                                if (Cannon != null)
                                {
                                    Cannon.Target();
                                }
                            }
                        }
                    }
                }
                catch (Exception except)
                {
                    QBCLog.Exception(except);
                }
            }
        }
コード例 #4
0
        private async Task <bool> MoveToEnd(bool exitVehicle, WoWUnit passenger = null)
        {
            if (!Query.IsInVehicle())
            {
                return(false);
            }

            if (Vehicle.Location.DistanceSqr(EndLocation) >= PrecisionSqr)
            {
                await UseSpeedBuff();

                Flightor.MoveTo(EndLocation);
                return(true);
            }

            if (exitVehicle)
            {
                Lua.DoString("VehicleExit()");
                await Coroutine.Sleep(2000);

                await Coroutine.Wait(20000, () => !Me.IsFalling);

                if (Me.Combat)
                {
                    QBCLog.Info("Getting in vehicle to drop combat");
                    return(await GetInVehicleLogic());
                }
                return(true);
            }

            if (!Query.IsViable(passenger))
            {
                return(false);
            }

            if (Vehicle.IsMoving)
            {
                await CommonCoroutines.StopMoving("Dropping off passenger.");

                await CommonCoroutines.SleepForLagDuration();
            }

            await Coroutine.Sleep(StyxWoW.Random.Next(5000, 6000));

            UseVehicleButton(DropPassengerButton);

            await CommonCoroutines.SleepForLagDuration();

            if (!await Coroutine.Wait(10000, () => !Query.IsViable(passenger) || !UnitIsRidingMyVehicle(passenger)))
            {
                QBCLog.Warning("Failed to drop passenger off");
                return(false);
            }
            if (Query.IsViable(passenger))
            {
                Blacklist.Add(passenger, BlacklistFlags.Interact, TimeSpan.FromMinutes(10), "Rescued");
            }

            // pause a sec to see if quest completes.
            if (await Coroutine.Wait(2000, () => Quest.IsCompleted))
            {
                return(true);
            }

            CycleToNearestPointInPath();
            return(true);
        }
コード例 #5
0
        public Composite CreateMainBehavior()
        {
            // NB: We need to allow lower BT nodes to run when the behavior is finished; otherwise, HB will not
            // process the change of _isBehaviorDone state.
            return(new PrioritySelector(

                       // If quest is done, behavior is done...
                       new Decorator(context => IsDone,
                                     new Action(context =>
            {
                _isBehaviorDone = true;
                QBCLog.Info("Finished");
            })),

                       // If using cannon, start spanking targets...
                       new Decorator(context => Query.IsInVehicle(),
                                     // Ready, Aim, Fire!
                                     new Action(context =>
            {
                // If ejected from vehicle, try to re-locate it...
                if ((CannonVehicle == null) || !CannonVehicle.IsValid)
                {
                    CannonVehicle = FindUnitsFromId(VehicleId_NurongsCannon).FirstOrDefault();
                    return;
                }

                // If target is no longer valid, select another...
                if (!IsViableTarget(CannonVehicle, SelectedTarget))
                {
                    SelectedTarget = ChooseTarget(CannonVehicle, SelectedTarget);
                    if (SelectedTarget == null)
                    {
                        return;
                    }
                    SelectedTarget.Target();
                }

                AimAndFireCannon(CannonVehicle, SelectedTarget);
            })),

                       // If not using cannon, get in cannon vehicle...
                       new Decorator(context => !Query.IsInVehicle(),
                                     new PrioritySelector(cannonContext => FindUnitsFromId(MobId_NurongsCannon).FirstOrDefault(),

                                                          // If unable to locate cannon, warn user and stop...
                                                          new Decorator(cannonContext => cannonContext == null,
                                                                        new PrioritySelector(
                                                                            // The Wait is a defensive bumper against a WoWclient/HBcore race condition...
                                                                            // Sometimes, the toon is ejected from the vehicle before the quest is marked as 'complete'.
                                                                            // We don't want this situation to cause the profile to stop, so we wait for a short while
                                                                            // before declaring a profile problem.
                                                                            new Wait(TimeSpan.FromMilliseconds(5000), cannonContext => IsDone, new ActionAlwaysSucceed()),
                                                                            new Action(cannonContext =>
            {
                QBCLog.Error("PROFILE ERROR: Nurong's Cannon is not in the area--please repair profile");
                TreeRoot.Stop();
                _isBehaviorDone = true;
            })
                                                                            )),

                                                          // Move close enough, and interact with cannon...
                                                          new Decorator(cannonContext => ((WoWUnit)cannonContext).Distance > ((WoWUnit)cannonContext).InteractRange,
                                                                        new Action(cannonContext => { Navigator.MoveTo(((WoWUnit)cannonContext).Location); })),
                                                          new Decorator(cannonContext => !Me.IsFacing((WoWUnit)cannonContext),
                                                                        new Action(cannonContext => { ((WoWUnit)cannonContext).Face(); })),
                                                          new Decorator(cannonContext => Me.IsMoving,
                                                                        new Action(cannonContext => { WoWMovement.MoveStop(); })),
                                                          new Decorator(cannonContext => !Query.IsInVehicle(),
                                                                        new Action(cannonContext =>
            {
                ((WoWUnit)cannonContext).Interact();
                CannonVehicle = null;
            })),
                                                          new Wait(TimeSpan.FromMilliseconds(5000), cannonContext => Query.IsInVehicle(), new ActionAlwaysSucceed())
                                                          ))
                       ));
        }
コード例 #6
0
        public ChangeSet(Dictionary <string, object> changes)
        {
            var changeSet          = new List <Tuple <SettingDescriptor, object> >();
            var isProblemAttribute = false;

            foreach (var change in changes)
            {
                try
                {
                    var name  = change.Key;
                    var value = change.Value;

                    // Setting name cannot be null or empty...
                    if (string.IsNullOrEmpty(name))
                    {
                        QBCLog.Error("Name may not be null or empty");
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting exists...
                    var settingDescriptor = RecognizedSettings.FirstOrDefault(s => s.Name == name);
                    if (settingDescriptor == null)
                    {
                        QBCLog.Error("Unable to locate setting for '{0}'.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Is changing attribute allowed?
                    if (settingDescriptor.IsAccessDisallowed)
                    {
                        QBCLog.Error("Accessing attribute '{0}' is not allowed.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Check that setting doesn't already exist in the changeset...
                    if (changeSet.Any(t => t.Item1.Name == name))
                    {
                        QBCLog.Error("Setting '{0}' already exists in the changeset.", name);
                        isProblemAttribute = true;
                        continue;
                    }

                    // If user specified 'original' value, go look it up and substitute it for 'value'...
                    if ((value is string) && ((string)value == "original"))
                    {
                        object originalValue;

                        if (!OriginalConfiguration.TryGetValue(settingDescriptor.Name, out originalValue))
                        {
                            // A missing 'original configuration' is a maintenance issue, not a user error...
                            QBCLog.MaintenanceError("For setting '{0}', there is no original configuration value.",
                                                    settingDescriptor.Name);
                            isProblemAttribute = true;
                            continue;
                        }

                        value = originalValue;
                    }

                    // Check that setting is an appropriate type...
                    var newValue = settingDescriptor.ToCongruentObject(value);

                    if (!settingDescriptor.ConstraintChecker.IsWithinConstraints(newValue))
                    {
                        QBCLog.Error("For setting '{0}', the provided value '{1}' is not within the required constraints of {2}.",
                                     name, value, settingDescriptor.ConstraintChecker.Description);
                        isProblemAttribute = true;
                        continue;
                    }

                    // Setting change is acceptable...
                    changeSet.Add(Tuple.Create(settingDescriptor, value));
                }

                catch (Exception ex)
                {
                    QBCLog.Exception(ex, "MAINTENANCE ERROR: Error processing attribute '{0}.'", change.Key);
                    isProblemAttribute = true;
                }
            }

            // If problem encountered with any change, we're unable to build the ChangeSet...
            if (isProblemAttribute)
            {
                _changeSet = null;
                throw new ArgumentException("Problems encountered with provided argument");
            }

            Count      = changeSet.Count;
            _changeSet = new ReadOnlyCollection <Tuple <SettingDescriptor, object> >(changeSet);
        }
コード例 #7
0
        private Composite CreateBehavior_Antistuck()
        {
            return(new PrioritySelector(
                       new Decorator(context => _stuckTimer.IsFinished,
                                     new Sequence(context => _antiStuckMyLoc = WoWMovement.ActiveMover.Location,

                                                  // Check if stuck...
                                                  new DecoratorContinue(context => _antiStuckMyLoc.DistanceSqr(_antiStuckPrevPosition) < (3 * 3),
                                                                        new Sequence(context => _antiStuckPerformSimpleSequence = _antiStuckStuckSucceedTimer.IsFinished,
                                                                                     new DecoratorContinue(context => Me.IsMounted() && !Me.IsFlying,
                                                                                                           new ActionRunCoroutine(context => CommonCoroutines.Dismount("Stuck"))),

                                                                                     // Perform simple unstuck proceedure...
                                                                                     new DecoratorContinue(context => _antiStuckPerformSimpleSequence,
                                                                                                           new Sequence(
                                                                                                               new Action(context => QBCLog.Debug("Stuck. Trying to jump")),
                                                                                                               new Action(context =>
            {
                // ensure bot is moving forward when jumping (Wow will sometimes automatically
                // stop moving if running against a wall)
                if (ShouldPerformCTM)
                {
                    WoWMovement.ClickToMove(Destination);
                }
                WoWMovement.Move(WoWMovement.MovementDirection.JumpAscend);
            }),
                                                                                                               new Sleep(1000),
                                                                                                               new Action(context => WoWMovement.MoveStop(WoWMovement.MovementDirection.JumpAscend))
                                                                                                               )),

                                                                                     // perform less simple unstuck proceedure
                                                                                     new DecoratorContinue(context => !_antiStuckPerformSimpleSequence,
                                                                                                           new Sequence(context => _antiStuckMoveDirection = GetRandomMovementDirection(),
                                                                                                                        new Action(context => QBCLog.Debug("Stuck. Movement Directions: {0}", _antiStuckMoveDirection)),
                                                                                                                        new Action(context => WoWMovement.Move(_antiStuckMoveDirection)),
                                                                                                                        new Sleep(2000),
                                                                                                                        new Action(context => WoWMovement.MoveStop(_antiStuckMoveDirection)))),

                                                                                     new Action(context => _antiStuckStuckSucceedTimer.Reset()))),

                                                  new Action(context => _antiStuckPrevPosition = _antiStuckMyLoc),
                                                  new Action(context => _stuckTimer.Reset())
                                                  ))));
        }
コード例 #8
0
        private Composite SubBehavior_CombatWithViableMob()
        {
            return(new PrioritySelector(context => SelectedTarget = Me.CurrentTarget,
                                        // Recall pet, if necessary...
                                        new Decorator(context => (SelectedTarget.HealthPercent < RecallPetAtMobPercentHealth) &&
                                                      (Me.GotAlivePet && Me.Pet.GotTarget),
                                                      new ActionFail(context =>
            {
                QBCLog.Info("Recalling Pet from '{0}' (health: {1:F1})",
                            SelectedTarget.SafeName, SelectedTarget.HealthPercent);
                PetControl.SetStance_Passive();
                PetControl.Follow();
            })),

                                        // If we are beyond the max range allowed to use the item, move within range...
                                        new Decorator(context => SelectedTarget.Distance > MaxRangeToUseItem,
                                                      new ActionRunCoroutine(
                                                          interactUnitContext => UtilityCoroutine.MoveTo(
                                                              SelectedTarget.Location,
                                                              string.Format("within {0} feet of {1}", MaxRangeToUseItem, SelectedTarget.SafeName),
                                                              MovementBy,
                                                              (float)MaxRangeToUseItem))),

                                        // If time to use the item, do so...
                                        new Decorator(context => IsUseItemNeeded(SelectedTarget),
                                                      new PrioritySelector(
                                                          new ActionRunCoroutine(context => CommonCoroutines.StopMoving()),

                                                          // Halt combat until we are able to use the item...
                                                          new Decorator(context => ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                                                                                    (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)),
                                                                        new ActionFail(context =>
            {
                // We use LUA to stop casting, since SpellManager.StopCasting() doesn't seem to work...
                if (Me.IsCasting)
                {
                    Lua.DoString("SpellStopCasting()");
                }

                if (Me.IsAutoAttacking)
                {
                    Lua.DoString("StopAttack()");
                }

                TreeRoot.StatusText = string.Format("Combat halted--waiting for {0} to become usable.",
                                                    Utility.GetItemNameFromId(ItemId));
            })),

                                                          new Sequence(
                                                              new ActionRunCoroutine(ctx =>
                                                                                     UtilityCoroutine.UseItemOnTarget(
                                                                                         ItemId,
                                                                                         SelectedTarget,
                                                                                         () => BehaviorDone(string.Format("Terminating behavior due to missing {0}",
                                                                                                                          Utility.GetItemNameFromId(ItemId))))),
                                                              // Allow a brief time for WoWclient to apply aura to mob...
                                                              new WaitContinue(TimeSpan.FromMilliseconds(5000),
                                                                               context => ItemUseAlwaysSucceeds || SelectedTarget.HasAura(ItemAppliesAuraId),
                                                                               new ActionAlwaysSucceed()),
                                                              new ActionFail(context =>
            {
                _waitTimerAfterUsingItem.Reset();

                if (ItemUseAlwaysSucceeds || SelectedTarget.HasAura(ItemAppliesAuraId))
                {
                    // Count our success if no associated quest...
                    if (!VariantQuestIds.Any())
                    {
                        ++Counter;
                    }

                    // If we can only use the item once per target, blacklist this target from subsequent selection...
                    if ((UseItemStrategy == UseItemStrategyType.UseItemOncePerTarget) ||
                        (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend))
                    {
                        SelectedTarget.BlacklistForInteracting(TimeSpan.FromSeconds(InteractBlacklistTimeInSeconds));
                    }

                    // If we can't defend ourselves from the target, blacklist it for combat and move on...
                    if (Query.IsViable(SelectedTarget) &&
                        ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                         (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)))
                    {
                        SelectedTarget.BlacklistForCombat(TimeSpan.FromSeconds(InteractBlacklistTimeInSeconds));
                        BotPoi.Clear();
                        Me.ClearTarget();
                        SelectedTarget = null;
                    }
                }

                if ((ItemAppliesAuraId > 0) && !SelectedTarget.HasAura(ItemAppliesAuraId))
                {
                    var auraNamesOnMob = ((SelectedTarget.Auras.Keys.Count > 0)
                                                            ? string.Join(", ", SelectedTarget.Auras.Keys)
                                                            : "none");

                    QBCLog.Warning("{1} did not acquire expected AuraId, \"{2}\"--retrying.{0}"
                                   + "    Auras on {1}: {3}",
                                   Environment.NewLine,
                                   SelectedTarget.SafeName,
                                   Utility.GetSpellNameFromId(ItemAppliesAuraId),
                                   auraNamesOnMob);
                }
            }),

                                                              // Prevent combat, if we're not supposed to defend...
                                                              new Decorator(context => ((UseItemStrategy == UseItemStrategyType.UseItemContinuouslyOnTargetDontDefend) ||
                                                                                        (UseItemStrategy == UseItemStrategyType.UseItemOncePerTargetDontDefend)),
                                                                            new ActionAlwaysSucceed())
                                                              )))
                                        ));
        }
コード例 #9
0
        public TwoBySea(Dictionary <string, string> args)
            : base(args)
        {
            QBCLog.BehaviorLoggingContext = this;

            try
            {
                // Quest handling...
                QuestId = 14382; // http://wowhead.com/quest=14382
                QuestRequirementComplete = QuestCompleteRequirement.NotComplete;
                QuestRequirementInLog    = QuestInLogRequirement.InLog;

                Task_CaptainAnson = new TaskDetail(
                    "Captain Anson",
                    36397,                                         // Captain Anson:  http://wowhead.com/npc=36397
                    new Vector3(-2073.466f, 2632.036f, 2.717113f), // Launch Position
                    new Vector3(-2124.181f, 2662.547f, 8.256202f), // Target Position
                    0.22,                                          // Needed Azimuth (in radians)
                    new Vector3(-2105.5f, 2655.504f, 0.5987438f),  // Jump down off boat point
                    c => IsQuestObjectiveComplete(QuestId, 1)
                    );

                Task_CaptainMorris = new TaskDetail(
                    "Captain Morris",
                    36399,                                         // Captain Morris:  http://wowhead/npc=36399
                    new Vector3(-2182.197f, 2549.495f, 2.720596f), // Launch Position
                    new Vector3(-2225.435f, 2565.901f, 8.664543f), // Target Position
                    0.18,                                          // Needed Azimuth (in radians)
                    new Vector3(-2207.448f, 2558.94f, 0.950241f),  // Jump down off boat point
                    c => IsQuestObjectiveComplete(QuestId, 2));

                MobId_ForsakenMachinist    = 36292; // http://wowhead.com/npc=36292
                VehicleId_ForsakenCatapult = 36283; // http://www.wowhead.com/npc=36283

                Location_CatapultFarm = new Vector3(-2052.313f, 2577.324f, 1.39316f).FanOutRandom(20.0);

                Lua_LaunchCommand = "if GetPetActionCooldown(1) == 0 then CastPetAction(1) end"; // http://www.wowhead.com/spell=66251

                // Tunables...
                CombatMaxEngagementRangeDistance = 23.0;
                NonCompeteDistanceForCatapults   = 25.0;
                VehicleLocationPathPrecision     = 3.5;

                // Blackspots...
                Blackspots = new List <Blackspot>()
                {
                    new Blackspot(new Vector3(-2126.297f, 2536.12f, 7.228605f), 12.0f, 1.0f)
                };

                // Semantic coherency / covariant dependency checks --
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                QBCLog.Exception(except);
                IsAttributeProblem = true;
            }
        }
コード例 #10
0
        protected override Composite CreateBehavior_CombatMain()
        {
            return(new PrioritySelector(
                       new Decorator(context => !IsDone && !Me.IsActuallyInCombat,
                                     new PrioritySelector(

                                         // Update Location if relative coord is used...
                                         // N.B. Relative locations are only used while on transports and because
                                         // transports are usually moving around 'Location' needs to be updated on every frame.
                                         new Decorator(context => UseRelativeLocation,
                                                       new Action(context => Destination = CalculateRelativeLocation(OrigDestination))),

                                         // Initialize the timer...
                                         new Decorator(context => _runTimer == null,
                                                       new Action(context =>
            {
                _runTimer = new WaitTimer(Destination.MaximumTraversalTime(2.5, TimeSpan.FromSeconds(20), UpperLimitOnMovementTime));
                QBCLog.DeveloperInfo("Maximum allowed time to reach destination: {0} seconds",
                                     _runTimer.WaitTime.TotalSeconds);
                _runTimer.Reset();
                return RunStatus.Failure;
            })),

                                         // Stop HB if _runTimer finishes...
                                         new Decorator(context => _runTimer.IsFinished,
                                                       new Action(context =>
            {
                WoWMovement.MoveStop();

                // N.B. set the runtimer to null so if player manually correct
                // problem and starts bot up it restarts the timer.
                _runTimer = null;

                QBCLog.Fatal("MyCTM is not able to reach {0} from {1}",
                             DestinationName,
                             WoWMovement.ActiveMover.Location);
            })),

                                         // Run stuckhandler
                                         CreateBehavior_Antistuck(),
                                         // Default anti-stuck has issues.
                                         // new Decorator(context => Navigator.NavigationProvider.StuckHandler.IsStuck(),
                                         //     new Action(context => Navigator.NavigationProvider.StuckHandler.Unstick())),

                                         // check if bot has reached the destination.
                                         new Decorator(context => Destination.DistanceSqr(Me.Location) <= (3 * 3),
                                                       new Action(context =>
            {
                BehaviorDone(string.Format("Finished moving to {0}", DestinationName));

                // Drop down to 'CreateBehavior_PerformCTM' to ensure ctm is performed
                // at least once if start and destination locations are very close on start
                return RunStatus.Failure;
            })),
                                         CreateBehavior_PerformCTM()
                                         )),

                       // _runTimer needs to be recalculated after combat is over and stuck timer needs to rest.
                       new Decorator(context => Me.IsActuallyInCombat,
                                     new Action(context =>
            {
                _runTimer = null;
                _stuckTimer.Reset();
                return RunStatus.Failure;
            }))
                       ));
        }
コード例 #11
0
        private Composite CreateMainBehavior()
        {
            return(new PrioritySelector(

                       // If a mob targets us, kill it...
                       // We don't want to blindly move to destination and drag a bunch of mobs behind us...
                       new Decorator(context => (SelectedTarget = FindMobTargetingMeOrPet()) != null,
                                     UtilityBehavior_SpankMob(context => SelectedTarget)),


                       // Stateful Operation:
                       new Switch <StateType_MainBehavior>(context => State_MainBehavior,
                                                           #region State: DEFAULT
                                                           new Action(context => // default case
            {
                QBCLog.Error("BEHAVIOR MAINTENANCE PROBLEM: StateType_MainBehavior({0}) is unhandled", State_MainBehavior);
                TreeRoot.Stop();
                _isBehaviorDone = true;
            }),
                                                           #endregion


                                                           #region State: Assigning Task
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.AssigningTask,
                                                                                                       new PrioritySelector(
                                                                                                           // Captain Anson...
                                                                                                           new Decorator(context => !Task_CaptainAnson.IsTaskComplete(context),
                                                                                                                         new Action(context =>
            {
                CurrentTask = Task_CaptainAnson;
                State_MainBehavior = StateType_MainBehavior.AcquiringCatapult;
            })),

                                                                                                           // Captain Morris...
                                                                                                           new Decorator(context => !Task_CaptainMorris.IsTaskComplete(context),
                                                                                                                         new Action(context =>
            {
                CurrentTask = Task_CaptainMorris;
                State_MainBehavior = StateType_MainBehavior.AcquiringCatapult;
            })),

                                                                                                           // Done with all tasks, move back to sane position to continue profile...
                                                                                                           new Decorator(context => !Navigator.AtLocation(Location_CatapultFarm),
                                                                                                                         new Action(context => { Navigator.MoveTo(Location_CatapultFarm); })),

                                                                                                           new Action(context =>
            {
                QBCLog.Info("Finished");
                _isBehaviorDone = true;
            })
                                                                                                           )),
                                                           #endregion


                                                           #region State: Acquiring Catapult
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.AcquiringCatapult,
                                                                                                       new PrioritySelector(
                                                                                                           // If task complete, go get next task...
                                                                                                           new Decorator(context => CurrentTask.IsTaskComplete(context),
                                                                                                                         new Action(context => { State_MainBehavior = StateType_MainBehavior.AssigningTask; })),

                                                                                                           // If we're in the catapult, start using it...
                                                                                                           new Decorator(context => Query.IsInVehicle(),
                                                                                                                         new Action(context => { State_MainBehavior = StateType_MainBehavior.UsingCatapultToBoardBoat; })),

                                                                                                           // Notify user...
                                                                                                           new Action(context =>
            {
                QBCLog.Info("Appropriating a Catapult");
                return RunStatus.Failure;
            }),

                                                                                                           // If available catapult, take advantage of it...
                                                                                                           new Decorator(context => IsViable(SelectedCatapult) &&
                                                                                                                         (FindPlayersNearby(SelectedCatapult.Location, NonCompeteDistanceForCatapults).Count() <= 0),
                                                                                                                         UtilityBehavior_InteractWithMob(context => SelectedCatapult)),

                                                                                                           // Otherwise, spank machinist and take his catapult...
                                                                                                           new Decorator(context => IsViable(SelectedMachinist) &&
                                                                                                                         (FindPlayersNearby(SelectedMachinist.Location, NonCompeteDistanceForCatapults).Count() <= 0),
                                                                                                                         UtilityBehavior_SpankMob(context => SelectedMachinist)),

                                                                                                           // Find next catapult or machinist...
                                                                                                           // NB: Since it takes a couple of seconds for the catapult to appear after
                                                                                                           // we kill the machinist, we want to wait briefly.   Without this delay,
                                                                                                           // the toon will run off to another machinist, and come back when the Catapult
                                                                                                           // spawns from the machinist we just killed.  This makes us look very bottish,
                                                                                                           // and the delay prevents that.
                                                                                                           new Wait(TimeSpan.FromSeconds(3),
                                                                                                                    context => ((SelectedCatapult = FindCatapult()) != null),
                                                                                                                    new ActionAlwaysSucceed()),

                                                                                                           new Decorator(context => (SelectedMachinist = FindMachinist()) != null,
                                                                                                                         new ActionAlwaysSucceed()),

                                                                                                           // No catapults to be had, move to center of catapult farm and wait for respawns...
                                                                                                           new Decorator(context => !Navigator.AtLocation(Location_CatapultFarm),
                                                                                                                         new Action(context => { Navigator.MoveTo(Location_CatapultFarm); })),
                                                                                                           new Action(context => { QBCLog.Info("Waiting on more Catapults to respawn"); })
                                                                                                           )),
                                                           #endregion


                                                           #region State: Using Catapult to Board Boat
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.UsingCatapultToBoardBoat,
                                                                                                       new PrioritySelector(
                                                                                                           // If task complete, go fetch another...
                                                                                                           new Decorator(context => CurrentTask.IsTaskComplete(context),
                                                                                                                         new Action(context => { State_MainBehavior = StateType_MainBehavior.AssigningTask; })),

                                                                                                           // If we're no longer in catapult, either launch succeeded or we need to fetch another Catapult...
                                                                                                           new Decorator(context => !Query.IsInVehicle(),
                                                                                                                         new PrioritySelector(
                                                                                                                             // Allow time for Launch completion, and toon to land on boat...
                                                                                                                             new Wait(TimeSpan.FromSeconds(5),
                                                                                                                                      // TODO: Rewrite to use something else (probably IsOnTransport?)
                                                                                                                                      context => true /*Navigator.CanNavigateFully(Me.Location, CurrentTask.PositionToLand)*/,
                                                                                                                                      new ActionAlwaysFail()),

                                                                                                                             new Action(context =>
            {
                // If we can navigate to intended landing spot, we successfully boarded boat...
                // TODO: Rewrite to use something else (probably IsOnTransport?)
                if (/*Navigator.CanNavigateFully(Me.Location, CurrentTask.PositionToLand)*/ true)
                {
                    State_MainBehavior = StateType_MainBehavior.KillingCaptain;
                    return;
                }

                // Otherwise, we missed boarding boat, and need to try again...
                QBCLog.Warning("Failed in boarding {0}'s boat--trying again", CurrentTask.MobName);
                State_MainBehavior = StateType_MainBehavior.AcquiringCatapult;
            })
                                                                                                                             )),

                                                                                                           // If Catapult no longer viable, find a new one...
                                                                                                           new Decorator(context => !IsViable(SelectedCatapult),
                                                                                                                         new Decorator(context => (SelectedCatapult = FindCatapult()) == null,
                                                                                                                                       new Action(context => { State_MainBehavior = StateType_MainBehavior.AcquiringCatapult; }))),

                                                                                                           // Try to board boat...
                                                                                                           new ActionRunCoroutine(ctx => UtilityCoroutine_MoveAndUseCatapult())
                                                                                                           )),
                                                           #endregion


                                                           #region State: Kill the Captain
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.KillingCaptain,
                                                                                                       new PrioritySelector(
                                                                                                           // If task complete, exit boat...
                                                                                                           new Decorator(context => CurrentTask.IsTaskComplete(context),
                                                                                                                         new Action(context => { State_MainBehavior = StateType_MainBehavior.ExitingBoat; })),

                                                                                                           // Kill the Captain...
                                                                                                           new PrioritySelector(captainContext => FindUnitsFromIds(CurrentTask.MobId).FirstOrDefault(),
                                                                                                                                new Decorator(captainContext => captainContext != null,
                                                                                                                                              UtilityBehavior_SpankMob(captainContext => (WoWUnit)captainContext)),
                                                                                                                                new Decorator(captainContext => captainContext == null,
                                                                                                                                              new Action(captainContext => { QBCLog.Info("Waiting for {0} to respawn", CurrentTask.MobName); }))
                                                                                                                                )
                                                                                                           )),
                                                           #endregion


                                                           #region State: Exiting Boat
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.ExitingBoat,
                                                                                                       new PrioritySelector(
                                                                                                           new Action(context =>
            {
                QBCLog.Info("Exiting {0}'s boat", CurrentTask.MobName);
                return RunStatus.Failure;
            }),
                                                                                                           new Decorator(context => !Navigator.AtLocation(CurrentTask.PositionToLand),
                                                                                                                         new Action(context => { Navigator.MoveTo(CurrentTask.PositionToLand); })),

                                                                                                           new Action(context => { State_MainBehavior = StateType_MainBehavior.ExitBoatJumpDown; })
                                                                                                           )),
                                                           #endregion


                                                           #region State: Exit Boat Jump Down
                                                           new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.ExitBoatJumpDown,
                                                                                                       new PrioritySelector(
                                                                                                           new Action(context =>
            {
                QBCLog.Info("Jumping down off of {0}'s boat", CurrentTask.MobName);
                return RunStatus.Failure;
            }),
                                                                                                           // NB: There appear to be no mesh "jump links" in the mesh to get off boat.
                                                                                                           // So, we're left with using ClickToMove to jump down from boat decks.
                                                                                                           new Decorator(context => !Navigator.AtLocation(CurrentTask.PositionToJumpDownOffBoat),
                                                                                                                         new Action(context => { WoWMovement.ClickToMove(CurrentTask.PositionToJumpDownOffBoat); })),

                                                                                                           new Action(context => { State_MainBehavior = StateType_MainBehavior.AssigningTask; })
                                                                                                           ))
                                                           #endregion
                                                           )));
        }
コード例 #12
0
        protected override Composite CreateBehavior()
        {
            return(_Root ?? (_Root =
                                 new PrioritySelector(context => !s_isBehaviorDone,

                                                      #region MyHotSpot
                                                      // Store our current location.
                                                      new Decorator(context => MyHotSpot == Vector3.Zero,
                                                                    new Sequence(
                                                                        new DecoratorContinue(context => Me.IsMoving,
                                                                                              new WaitContinue(TimeSpan.FromMilliseconds(2000), context => false, new ActionAlwaysSucceed())
                                                                                              ),
                                                                        new DecoratorContinue(context => !Me.IsMoving,
                                                                                              new Action(context => MyHotSpot = Me.Location)
                                                                                              )
                                                                        )
                                                                    ),
                                                      #endregion

                                                      #region MinLevel
                                                      // Should we check for partymember minumum level ?
                                                      new Decorator(context => (MinLevel > 0),
                                                                    new Sequence(
                                                                        // Someone is below MinLevel.
                                                                        new DecoratorContinue(context => !CheckLevel(),
                                                                                              new Sequence(
                                                                                                  new Action(context => QBCLog.Info("Someone in your party is below level {0}.", MinLevel)),
                                                                                                  new Action(context => s_isBehaviorDone = true)
                                                                                                  )
                                                                                              ),
                                                                        // Everyone is equal or above MinLevel.
                                                                        new DecoratorContinue(context => CheckLevel(),
                                                                                              new Action(context => MinLevel = 0)
                                                                                              )
                                                                        )
                                                                    ),
                                                      #endregion

                                                      #region CheckRange
                                                      // Should we wait for party members to be in range ?
                                                      new Decorator(context => (CheckRange != 0),
                                                                    new Sequence(
                                                                        // Everyone isn't within interact range, lets wait abit before checking again.
                                                                        new DecoratorContinue(context => !CheckPartyRange(),
                                                                                              new Sequence(
                                                                                                  new DecoratorContinue(context => !Navigator.AtLocation(MyHotSpot),
                                                                                                                        new Sequence(
                                                                                                                            new Action(context => Navigator.MoveTo(MyHotSpot))
                                                                                                                            )
                                                                                                                        ),
                                                                                                  new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed())
                                                                                                  )
                                                                                              ),
                                                                        // Everyone is within interact range.
                                                                        new DecoratorContinue(context => CheckPartyRange(),
                                                                                              new Sequence(
                                                                                                  new Action(context => QBCLog.Info("Everyone is within range.")),
                                                                                                  new Action(context => CheckRange = 0)
                                                                                                  )
                                                                                              )
                                                                        )
                                                                    ),
                                                      #endregion

                                                      #region ChkExp
                                                      // Disabled until I can find out a safer way to to it.

                                                      /*
                                                       * new Decorator(context => (ChkExp != 0),
                                                       *  new Sequence(
                                                       *      new DecoratorContinue(context => !AreWeDone(),
                                                       *          new Action(context => CheckExpansions())
                                                       *      ),
                                                       *      new DecoratorContinue(context => AreWeDone(),
                                                       *          new Sequence(
                                                       *              new DecoratorContinue(context => !DoAllHaveExp(),
                                                       *                  new Sequence(
                                                       *                      new Action(context => QBCLog.Info("Everyone in your group doesn't have ExpansionLevel '{0}'", ChkExp)),
                                                       *                      new Action(context => _isBehaviorDone = true)
                                                       *                  )
                                                       *              ),
                                                       *              new DecoratorContinue(context => DoAllHaveExp(),
                                                       *                  new Sequence(
                                                       *                      new Action(context => QBCLog.Info("Everyone has atleast ExpansionLevel '{0}'", ChkExp)),
                                                       *                      new Action(context => ChkExp = 0)
                                                       *                  )
                                                       *              )
                                                       *          )
                                                       *      )
                                                       *  )
                                                       * ),
                                                       */
                                                      #endregion

                                                      #region RemotePath
                                                      // Load the remote profile...
                                                      new Decorator(context => RemotePath != "",
                                                                    new Sequence(
                                                                        // You have included a RemotePath but not a ProfileName.
                                                                        new DecoratorContinue(context => ProfileName == "",
                                                                                              new Sequence(
                                                                                                  new Action(context => QBCLog.Error("You need to include a ProfileName.")),
                                                                                                  new Action(context => s_isBehaviorDone = true)
                                                                                                  )
                                                                                              ),
                                                                        // Remote Profile doesn't exist.
                                                                        new DecoratorContinue(context => (ProfileName != "" && !UrlExists(NewRemoteProfilePath)),
                                                                                              new Sequence(
                                                                                                  new Action(context => QBCLog.Error("Profile '{0}' does not exist.", ProfileName)),
                                                                                                  new Action(context => s_isBehaviorDone = true)
                                                                                                  )
                                                                                              ),
                                                                        // Everything is ok, Load the remote Profile
                                                                        new DecoratorContinue(context => (ProfileName != "" && UrlExists(NewRemoteProfilePath)),
                                                                                              new Sequence(
                                                                                                  new Action(context => TreeRoot.StatusText = "Loading profile '" + ProfileName + "'"),
                                                                                                  new Action(context => QBCLog.Info("Loading profile '{0}'", ProfileName)),
                                                                                                  new Action(context => ProfileManager.LoadNew(new MemoryStream(new WebClient().DownloadData(NewRemoteProfilePath)))),
                                                                                                  new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed()),
                                                                                                  new Action(context => s_isBehaviorDone = true)
                                                                                                  )
                                                                                              )
                                                                        )
                                                                    ),
                                                      #endregion

                                                      #region ProfileName
                                                      // Load the local profile...
                                                      new Decorator(context => (ProfileName != "" && RemotePath == ""),
                                                                    new PrioritySelector(
                                                                        // Local Profile doesn't exist.
                                                                        new Decorator(context => !IsStoreProfile && !File.Exists(NewLocalProfilePath),
                                                                                      new Sequence(
                                                                                          new Action(context => QBCLog.Error("Profile '{0}' does not exist.", ProfileName)),
                                                                                          new Action(context => s_isBehaviorDone = true)
                                                                                          )
                                                                                      ),
                                                                        // Everything is ok, Load the local Profile.
                                                                        new Sequence(
                                                                            new Action(context => TreeRoot.StatusText = "Loading profile '" + ProfileName + "'"),
                                                                            new Action(context => QBCLog.Error("Loading profile '{0}'", ProfileName)),
                                                                            new Action(context => ProfileManager.LoadNew(NewLocalProfilePath, false)),
                                                                            new WaitContinue(TimeSpan.FromMilliseconds(300), context => false, new ActionAlwaysSucceed()),
                                                                            new Action(context => s_isBehaviorDone = true)
                                                                            )
                                                                        )
                                                                    ),
                                                      #endregion

                                                      #region Behavior Done
                                                      // Everyone is within interact range and we shouldn't load a profile, then end the Quest Behavior.
                                                      new Decorator(context => !s_isBehaviorDone,
                                                                    new Action(context => s_isBehaviorDone = true)
                                                                    )
                                                      #endregion
                                                      )
                             ));
        }
コード例 #13
0
        private Composite StateBehaviorPS_PathIngressing()
        {
            return(new PrioritySelector(
                       // If no Ingress path exists, build it...
                       new Decorator(context => Path_Ingress == null,
                                     new Action(context => { Path_Ingress = FollowPath.FindPath_Ingress(); })),

                       // If we've consumed our Ingress path (or the one we initially built is empty), we're done...
                       new Decorator(context => !Path_Ingress.Any(),
                                     new Action(context => { State_MainBehavior = StateType_MainBehavior.DestinationReached; })),

                       // If Mob_ToAvoid is too close or we get in combat, abandon current ingress, and retreat back to safespot...
                       new Decorator(context => Query.IsViable(Mob_ToAvoid) &&
                                     ((Mob_ToAvoid.Distance < FollowPath.EgressDistance) || Me.Combat),
                                     new Action(context =>
            {
                Path_Ingress = null;
                Path_Egress = null;
                State_MainBehavior = StateType_MainBehavior.PathRetreating;
            })),

                       new Switch <SafePathType.StrategyType>(context => FollowPath.Strategy,
                                                              new Action(context => // default case
            {
                var message = string.Format("FollowPathStrategyType({0}) is unhandled", FollowPath.Strategy);
                QBCLog.MaintenanceError(message);
                TreeRoot.Stop();
                BehaviorDone(message);
            }),

                                                              new SwitchArgument <SafePathType.StrategyType>(SafePathType.StrategyType.StalkMobAtAvoidDistance,
                                                                                                             new Decorator(context => Query.IsViable(Mob_ToAvoid) && (Mob_ToAvoid.Distance < AvoidDistance),
                                                                                                                           new PrioritySelector(
                                                                                                                               new ActionRunCoroutine(context => CommonCoroutines.StopMoving()),
                                                                                                                               new ActionAlwaysSucceed()
                                                                                                                               ))),

                                                              new SwitchArgument <SafePathType.StrategyType>(SafePathType.StrategyType.WaitForAvoidDistance,
                                                                                                             new PrioritySelector(
                                                                                                                 // No addition action needed to implement strategy for now
                                                                                                                 ))
                                                              ),

                       // If we've arrived at the current ingress waypoint, dequeue it...
                       new Decorator(context => Navigator.AtLocation(Path_Ingress.Peek().Location),
                                     new Action(context =>
            {
                FollowPath.DismissPetIfNeeded();
                Path_Ingress.Dequeue();
            })),

                       // Follow the prescribed ingress path, if its still safe to proceed...
                       new Decorator(context => IsSafeToMoveToDestination(Mob_ToAvoid),
                                     new ActionRunCoroutine(
                                         context => UtilityCoroutine.MoveTo(
                                             Path_Ingress.Peek().Location,
                                             "follow ingress path",
                                             MovementBy))),

                       // If mob is heading our direction, hold position...
                       new Decorator(context => !IsSafeToMoveToDestination(Mob_ToAvoid),
                                     new Sequence(
                                         new Action(context =>
            {
                TreeRoot.StatusText = string.Format("Holding position to evaluate {0}'s actions.", Mob_ToAvoid.SafeName);
            }),
                                         new ActionRunCoroutine(context => CommonCoroutines.StopMoving())
                                         ))
                       ));
        }
コード例 #14
0
        public PursuitListType(XElement xElement)
            : base(xElement)
        {
            try
            {
                PursueObjects = new List <PursueObjectTypeBase>();

                if (xElement != null)
                {
                    var pursueObjectElementsQuery =
                        from element in xElement.Elements()
                        where
                        (element.Name == "PursueObject") ||
                        (element.Name == "PursueUnit") ||
                        (element.Name == "PursueGameObject") ||
                        (element.Name == "PursueSelf")
                        select element;

                    foreach (XElement childElement in pursueObjectElementsQuery)
                    {
                        PursueObjectTypeBase pursueObj;
                        if (childElement.Name == "PursueObject")
                        {
                            pursueObj = new PursueObjectType <WoWObject>(childElement);
                        }
                        else if (childElement.Name == "PursueUnit")
                        {
                            pursueObj = new PursueObjectType <WoWUnit>(childElement);
                        }
                        else if (childElement.Name == "PursueGameObject")
                        {
                            pursueObj = new PursueObjectType <WoWGameObject>(childElement);
                        }
                        else if (childElement.Name == "PursueSelf")
                        {
                            pursueObj = new PursueObjectType <LocalPlayer>(childElement);
                        }
                        else
                        {
                            throw new InvalidDataException(string.Format("{0} is not a recognized type", childElement.Name));
                        }

                        if (!pursueObj.IsAttributeProblem)
                        {
                            PursueObjects.Add(pursueObj);
                        }

                        IsAttributeProblem |= pursueObj.IsAttributeProblem;
                    }
                }

                HandleAttributeProblem();
            }

            catch (Exception except)
            {
                if (Query.IsExceptionReportingNeeded(except))
                {
                    QBCLog.Exception(except, "PROFILE PROBLEM with \"{0}\"", xElement.ToString());
                }
                IsAttributeProblem = true;
            }
        }
コード例 #15
0
        private object UtilGetAttributeAsWoWPoints(string attributeName, bool isAttributeRequired, string[] attributeNameAliases)
        {
            bool            isError   = false;
            string          keyName   = UtilLocateKey(isAttributeRequired, attributeName, attributeNameAliases);
            List <WoWPoint> pointList = new List <WoWPoint>();

            char[] separatorCoordinate = { ' ', ',' };
            char[] separatorTriplet    = { '|', ';' };


            if ((keyName == null) || !Attributes.ContainsKey(keyName))
            {
                pointList.Clear();
                return(pointList.ToArray());
            }


            foreach (string tripletAsString in Attributes[keyName].Split(separatorTriplet, StringSplitOptions.RemoveEmptyEntries))
            {
                string[] coordinatesAsString = tripletAsString.Split(separatorCoordinate, StringSplitOptions.RemoveEmptyEntries);

                if (coordinatesAsString.Length != 3)
                {
                    QBCLog.Error(QBCLog.BuildMessageWithContext(Element,
                                                                "The '{1}' attribute's value contribution (saw '{2}')"
                                                                + " doesn't have three coordinates (counted {3}).{0}"
                                                                + "Expect entries of the form \"x1,y1,z1 | x2,y2,z2 | x3,...\", or \"x1,y1,z1; x2,y2,z2; x3,...\"",
                                                                Environment.NewLine,
                                                                keyName,
                                                                tripletAsString,
                                                                coordinatesAsString.Length));
                    isError = true;
                    continue;
                }

                double?tmpValueX = null;
                try { tmpValueX = UtilTo <double>(keyName, coordinatesAsString[0]); }
                catch (Exception) { isError = true; }

                double?tmpValueY = null;
                try { tmpValueY = UtilTo <double>(keyName, coordinatesAsString[1]); }
                catch (Exception) { isError = true; }

                double?tmpValueZ = null;
                try { tmpValueZ = UtilTo <double>(keyName, coordinatesAsString[2]); }
                catch (Exception) { isError = true; }

                if (tmpValueX.HasValue && tmpValueY.HasValue && tmpValueZ.HasValue)
                {
                    pointList.Add(new WoWPoint(tmpValueX.Value, tmpValueY.Value, tmpValueZ.Value));
                }
            }

            if (isError)
            {
                pointList.Clear();
                IsAttributeProblem = true;
            }

            return(pointList.ToArray());
        }
コード例 #16
0
        public CombatUseItemOnV2(Dictionary <string, string> args)
            : base(args)
        {
            try
            {
                // NB: Core attributes are parsed by QuestBehaviorBase parent (e.g., QuestId, NonCompeteDistance, etc)

                // Primary attributes...
                ItemId = GetAttributeAsNullable <int>("ItemId", true, ConstrainAs.ItemId, null) ?? 0;

                string itemUseAlwaysSucceeds = GetAttributeAs <string>("ItemAppliesAuraId", false, ConstrainAs.StringNonEmpty, null) ?? string.Empty;
                if (itemUseAlwaysSucceeds == "AssumeItemUseAlwaysSucceeds")
                {
                    ItemAppliesAuraId = 0;
                }
                else
                {
                    ItemAppliesAuraId = GetAttributeAsNullable <int>("ItemAppliesAuraId", false, ConstrainAs.AuraId, null) ?? 0;
                }

                MobIds                     = GetNumberedAttributesAsArray <int>("MobId", 1, ConstrainAs.MobId, null);
                UseWhenMeHasAuraId         = GetAttributeAsNullable <int>("UseWhenMeHasAuraId", false, ConstrainAs.AuraId, null) ?? 0;
                UseWhenMeMissingAuraId     = GetAttributeAsNullable <int>("UseWhenMeMissingAuraId", false, ConstrainAs.AuraId, null) ?? 0;
                UseWhenMobCastingSpellId   = GetAttributeAsNullable <int>("UseWhenMobCastingSpellId", false, ConstrainAs.SpellId, null) ?? 0;
                UseWhenMobHasAuraId        = GetAttributeAsNullable <int>("UseWhenMobHasAuraId", false, ConstrainAs.AuraId, null) ?? 0;
                UseWhenMobMissingAuraId    = GetAttributeAsNullable <int>("UseWhenMobMissingAuraId", false, ConstrainAs.AuraId, null) ?? 0;
                UseWhenMobHasHealthPercent = GetAttributeAsNullable <double>("UseWhenMobHasHealthPercent", false, ConstrainAs.Percent, null) ?? 0;

                // Either HuntingGroundCenter or <HuntingGrounds> subelement must be provided...
                // The sanity check for this is done in OnStart() since that's where we must do
                // all sub-element processing due to the way CustomForcedBehavior is architected.
                HuntingGroundCenter = GetAttributeAsNullable <Vector3>("", false, ConstrainAs.Vector3NonEmpty, null);

                // Tunables...
                CollectionDistance             = GetAttributeAsNullable <double>("CollectionDistance", false, ConstrainAs.Range, null) ?? 100;
                InteractBlacklistTimeInSeconds = GetAttributeAsNullable <int>("InteractBlacklistTimeInSeconds", false, ConstrainAs.CollectionCount, null) ?? 180;
                MaxRangeToUseItem           = GetAttributeAsNullable <double>("MaxRangeToUseItem", false, ConstrainAs.Range, null) ?? 25.0;
                NumOfTimes                  = GetAttributeAsNullable <int>("NumOfTimesToUseItem", false, ConstrainAs.RepeatCount, null) ?? 1;
                RecallPetAtMobPercentHealth = GetAttributeAsNullable <double>("RecallPetAtMobPercentHealth", false, ConstrainAs.Percent, null) ?? UseWhenMobHasHealthPercent;
                UseItemStrategy             = GetAttributeAsNullable <UseItemStrategyType>("UseItemStrategy", false, null, null) ?? UseItemStrategyType.UseItemOncePerTarget;
                WaitTimeAfterItemUse        = GetAttributeAsNullable <int>("WaitTimeAfterItemUse", false, ConstrainAs.Milliseconds, null) ?? 0;

                // Hunting ground processing...
                HuntingGrounds =
                    HuntingGroundsType.GetOrCreate(Element,
                                                   "HuntingGrounds",
                                                   (HuntingGroundCenter.HasValue
                                                        ? new WaypointType(HuntingGroundCenter.Value, "hunting ground center")
                                                        : null));
                IsAttributeProblem |= HuntingGrounds.IsAttributeProblem;
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                QBCLog.Exception(except);
                IsAttributeProblem = true;
            }
        }
コード例 #17
0
        private T UtilTo <T>(string attributeName, string attributeValueAsString)
        {
            Type concreteType = typeof(T);

            // Booleans require special handling...
            if (concreteType == typeof(bool))
            {
                int tmpInt;

                if (int.TryParse(attributeValueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out tmpInt))
                {
                    attributeValueAsString = (tmpInt != 0) ? "true" : "false";

                    QBCLog.Warning(QBCLog.BuildMessageWithContext(Element,
                                                                  "Attribute's '{1}' value was provided as an integer (saw '{2}')--a boolean was expected.{0}"
                                                                  + "The integral value '{2}' was converted to Boolean({3}).{0}"
                                                                  + "Please update to provide '{3}' for this value.",
                                                                  Environment.NewLine,
                                                                  attributeName,
                                                                  tmpInt,
                                                                  attributeValueAsString));
                }

                // Fall through for normal boolean conversion
            }


            // Enums require special handling...
            else if (concreteType.IsEnum)
            {
                T tmpValue = default(T);

                try
                {
                    tmpValue = (T)Enum.Parse(concreteType, attributeValueAsString);

                    if (!Enum.IsDefined(concreteType, tmpValue))
                    {
                        throw new ArgumentException();
                    }

                    // If the provided value is a number instead of Enum name, ask the profile writer to fix it...
                    // This is not fatal, so we let it go without flagging IsAttributeProblem.
                    int tmpInt;
                    if (int.TryParse(attributeValueAsString, NumberStyles.Integer, CultureInfo.InvariantCulture, out tmpInt))
                    {
                        QBCLog.Warning(QBCLog.BuildMessageWithContext(Element,
                                                                      "The '{1}' attribute's value '{2}' has been implicitly converted"
                                                                      + " to the corresponding enumeration '{3}'.{0}"
                                                                      + "Please use the enumeration name '{3}' instead of a number.",
                                                                      Environment.NewLine,
                                                                      attributeName,
                                                                      tmpInt,
                                                                      tmpValue.ToString()));
                    }
                }
                catch (Exception)
                {
                    QBCLog.Error(QBCLog.BuildMessageWithContext(Element,
                                                                "The value '{1}' is not a member of the {2} enumeration."
                                                                + "  Allowed values: {3}",
                                                                Environment.NewLine,
                                                                attributeValueAsString,
                                                                concreteType.Name,
                                                                string.Join(", ", Enum.GetNames(concreteType))));
                    throw;
                }

                return(tmpValue);
            }



            try
            { return((T)Convert.ChangeType(attributeValueAsString, concreteType, CultureInfo.InvariantCulture)); }
            catch (Exception except)
            {
                QBCLog.Error(QBCLog.BuildMessageWithContext(Element,
                                                            "The '{1}' attribute's value (saw '{2}') is malformed. ({3})",
                                                            Environment.NewLine,
                                                            attributeName,
                                                            attributeValueAsString,
                                                            except.GetType().Name));
                throw;
            }
        }
コード例 #18
0
        /// <summary>
        /// Behavior for forcing train/mail/vendor/repair
        /// Example usage: <CustomBehavior QuestId="14324" File="ForceSetVendor" VendorType="Train" />
        /// QuestId is optional, if you don't use it make sure you put this tag inside an 'If'
        /// </summary>
        public ForceSetVendor(Dictionary <string, string> args)
            : base(args)
        {
            QBCLog.BehaviorLoggingContext = this;

            try
            {
                // Deprecation warnings...
                if (args.ContainsKey("VendorType"))
                {
                    QBCLog.Warning("The VendorType attribute has been deprecated.\n"
                                   + "Please replace it with DoMail/DoRepair/DoSell/DoTrain='true'");
                }

                // QuestRequirement* attributes are explained here...
                //    http://www.thebuddyforum.com/mediawiki/index.php?title=Honorbuddy_Programming_Cookbook:_QuestId_for_Custom_Behaviors
                // ...and also used for IsDone processing.
                DoMail   = GetAttributeAsNullable <bool>("DoMail", false, null, null) ?? false;
                DoRepair = GetAttributeAsNullable <bool>("DoRepair", false, null, null) ?? false;
                DoSell   = GetAttributeAsNullable <bool>("DoSell", false, null, null) ?? false;
                DoTrain  = GetAttributeAsNullable <bool>("DoTrain", false, null, null) ?? false;
                QuestId  = GetAttributeAsNullable <int>("QuestId", false, ConstrainAs.QuestId(this), null) ?? 0;
                QuestRequirementComplete = GetAttributeAsNullable <QuestCompleteRequirement>("QuestCompleteRequirement", false, null, null) ?? QuestCompleteRequirement.NotComplete;
                QuestRequirementInLog    = GetAttributeAsNullable <QuestInLogRequirement>("QuestInLogRequirement", false, null, null) ?? QuestInLogRequirement.InLog;

                // "VendorType" attribute is required if no Do* attribute is specified
                VendorType?type = GetAttributeAsNullable <VendorType>("VendorType", !(DoMail || DoRepair || DoSell || DoTrain), null, null);
                if (type.HasValue)
                {
                    switch (type.Value)
                    {
                    case VendorType.Mail:
                        DoMail = true;
                        break;

                    case VendorType.Repair:
                        DoRepair = true;
                        break;

                    case VendorType.Sell:
                        DoSell = true;
                        break;

                    case VendorType.Train:
                        DoTrain = true;
                        break;

                    default:
                        IsAttributeProblem = true;
                        throw (new NotImplementedException("Unexpected VendorType"));
                    }
                }
            }

            catch (Exception except)
            {
                // Maintenance problems occur for a number of reasons.  The primary two are...
                // * Changes were made to the behavior, and boundary conditions weren't properly tested.
                // * The Honorbuddy core was changed, and the behavior wasn't adjusted for the new changes.
                // In any case, we pinpoint the source of the problem area here, and hopefully it
                // can be quickly resolved.
                QBCLog.Exception(except);
                IsAttributeProblem = true;
            }
        }
コード例 #19
0
        private string UtilLocateKey(bool isAttributeRequired, string primaryName, string[] aliasNames)
        {
            // Register keys as recognized
            UtilRecognizeAttributeNames(primaryName, aliasNames);

            // Make sure the key was only specified once --
            // The 'dictionary' nature of Args assures that a key name will only be in the dictionary once.
            // However, if the key has been renamed, and an alias maintained for backward-compatibility,
            // then the user could specify the primary key name and one or more aliases as attributes.
            // If all the aliases provided the same value, then it is harmless, but we don't make the
            // distinction.  Instead, we encourage the user to use the preferred name of the key.  This
            // eliminates any possibility of the user specifying conflicting values for the 'same' attribute.
            if (UtilCountKeyNames(primaryName, aliasNames) > 1)
            {
                var keyNames = new List <string> {
                    primaryName
                };

                keyNames.AddRange(aliasNames);
                keyNames.Sort();

                QBCLog.Error(QBCLog.BuildMessageWithContext(Element,
                                                            "The attributes [{1}] are aliases for each other, and thus mutually exclusive.{0}"
                                                            + "Please specify the attribute by its preferred name '{2}'.",
                                                            Environment.NewLine,
                                                            ("'" + string.Join("', '", keyNames.ToArray()) + "'"),
                                                            primaryName));
                IsAttributeProblem = true;
                return(null);
            }


            // Prefer the primary name...
            if (!string.IsNullOrEmpty(primaryName) && Attributes.ContainsKey(primaryName))
            {
                return(primaryName);
            }

            if (aliasNames != null)
            {
                string keyName = (from aliasName in aliasNames
                                  where !string.IsNullOrEmpty(aliasName) && Attributes.ContainsKey(aliasName)
                                  select aliasName).FirstOrDefault();

                if (!string.IsNullOrEmpty(keyName))
                {
                    QBCLog.Warning(QBCLog.BuildMessageWithContext(Element,
                                                                  "Found attribute via its alias name '{1}'.{0}"
                                                                  + "Please update to use its primary name '{2}', instead.",
                                                                  Environment.NewLine,
                                                                  keyName,
                                                                  primaryName));
                    return(keyName);
                }
            }


            // Attribute is required, but cannot be located...
            if (isAttributeRequired)
            {
                QBCLog.Error(QBCLog.BuildMessageWithContext(Element,
                                                            "Attribute '{1}' is required, but was not provided.",
                                                            Environment.NewLine,
                                                            primaryName));
                IsAttributeProblem = true;
            }

            return(null);
        }
コード例 #20
0
        public override void OnStart()
        {
            // Let QuestBehaviorBase do basic initialization of the behavior, deal with bad or deprecated attributes,
            // capture configuration state, install BT hooks, etc.  This will also update the goal text.
            var isBehaviorShouldRun = OnStart_QuestBehaviorCore();

            // If the quest is complete, this behavior is already done...
            // So we don't want to falsely inform the user of things that will be skipped.
            if (isBehaviorShouldRun)
            {
                var logInfo          = new StringBuilder();
                var logDeveloperInfo = new StringBuilder();

                // The BotStop handler will put the original configuration settings back in place...
                // Note, we only want to hook it once for this behavior.
                if (!s_persistedIsBotStopHooked)
                {
                    BotEvents.OnBotStopped    += BotEvents_OnBotStopped;
                    s_persistedIsBotStopHooked = true;
                }

                // First, process Preset request, if any...
                if (!string.IsNullOrEmpty(PresetName))
                {
                    var presetChangeSet =
                        (from preset in _presetChangeSets
                         where preset.Key == PresetName
                         select preset.Value)
                        .FirstOrDefault();

                    if (presetChangeSet == null)
                    {
                        QBCLog.Error("Unable to locate any preset named '{0}'", PresetName);
                        TreeRoot.Stop();
                        BehaviorDone();
                        return;
                    }

                    var appliedChanges = presetChangeSet.Apply("    ");

                    var appliedChangesBuilder = s_persistedDebugShowChangesApplied ? logInfo : logDeveloperInfo;
                    appliedChangesBuilder.AppendFormat("Using preset '{0}'...{1}", PresetName, appliedChanges);
                    appliedChangesBuilder.Append(Environment.NewLine);
                }

                // Second, apply any change requests...
                if (_userChangeRequest.Count > 0)
                {
                    string appliedChanges = _userChangeRequest.Apply("    ");

                    var appliedChangesBuilder = s_persistedDebugShowChangesApplied ? logInfo : logDeveloperInfo;
                    appliedChangesBuilder.AppendFormat("Applied changes...{0}", appliedChanges);
                    appliedChangesBuilder.Append(Environment.NewLine);
                }

                // Third, show state, if requested...
                if (DebugShowDetails)
                {
                    var currentConfiguration = ChangeSet.FromCurrentConfiguration();

                    logInfo.AppendFormat("Details...{0}", currentConfiguration.BuildDetails("    "));
                    logInfo.Append(Environment.NewLine);
                }

                var diffBuilder = DebugShowDiff ? logInfo : logDeveloperInfo;
                diffBuilder.AppendFormat("Difference from user's original settings...{0}",
                                         ChangeSet.BuildDifferencesFromOriginalSettings("    "));
                diffBuilder.Append(Environment.NewLine);

                // Forth, stop the bot, if requested...
                if (IsStopBot)
                {
                    const string message = "Stopping the bot per profile request.";
                    logInfo.AppendFormat(message);
                    logInfo.Append(Environment.NewLine);

                    var logInfoString = logInfo.ToString();
                    if (!string.IsNullOrEmpty(logInfoString))
                    {
                        QBCLog.Info(logInfoString);
                    }

                    var logDeveloperString = logDeveloperInfo.ToString();
                    if (!string.IsNullOrEmpty(logDeveloperString))
                    {
                        QBCLog.DeveloperInfo(logDeveloperString);
                    }

                    TreeRoot.Stop(message);
                    BehaviorDone();
                    return;
                }

                else
                {
                    var logInfoString = logInfo.ToString();
                    if (!string.IsNullOrEmpty(logInfoString))
                    {
                        QBCLog.Info(logInfoString);
                    }

                    var logDeveloperString = logDeveloperInfo.ToString();
                    if (!string.IsNullOrEmpty(logDeveloperString))
                    {
                        QBCLog.DeveloperInfo(logDeveloperString);
                    }
                }

                BehaviorDone();
            }
        }
コード例 #21
0
        private async Task TargetLogic(WoWUnit target)
        {
            if (!Query.IsViable(target))
            {
                return;
            }

            var targetDistSqr = target.Location.DistanceSqr(Vehicle.Location);

            if (PickUpPassengerButton == 0)
            {
                TreeRoot.StatusText = string.Format("Blowing stuff up. {0} mins before resummon is required",
                                                    _flightTimer.TimeLeft.TotalMinutes);

                if (HealButton > 0 && targetDistSqr < 60 * 60 &&
                    (Vehicle.HealthPercent <= HealPercent || Vehicle.ManaPercent <= HealPercent) &&
                    UseVehicleButton(HealButton))
                {
                    QBCLog.Info("Used heal button {0} on NPC:{1}", HealButton, target.SafeName);
                    return;
                }

                // return when a button is used.
                foreach (var button in Buttons)
                {
                    if (UseVehicleButton(button))
                    {
                        return;
                    }
                }
                return;
            }

            TreeRoot.StatusText = string.Format("Rescuing {0}", target.SafeName);
            var pickTimer = new WaitTimer(TimeSpan.FromSeconds(20));

            pickTimer.Reset();
            while (target.IsValid && target.IsAlive && !UnitIsRidingMyVehicle(target) && Query.IsInVehicle() && !pickTimer.IsFinished)
            {
                WoWPoint clickLocation = target.Location.RayCast(target.Rotation, 6);
                clickLocation.Z += 3;
                if (Vehicle.Location.DistanceSqr(clickLocation) > 3 * 3)
                {
                    Flightor.MoveTo(clickLocation);
                }
                else
                {
                    if (Vehicle.IsMoving)
                    {
                        await CommonCoroutines.StopMoving(string.Format("Picking up {0}", target.SafeName));
                    }
                    UseVehicleButton(PickUpPassengerButton);
                    if (await Coroutine.Wait(4000, () => UnitIsRidingMyVehicle(target)))
                    {
                        QBCLog.Info("Successfully picked up passenger {0}", target.SafeName);
                        return;
                    }
                    QBCLog.Info("Failed to picked up passenger {0}", target.SafeName);
                }
                await Coroutine.Yield();
            }
        }
        protected async Task <bool> CombatMainLogic()
        {
            if (IsDone)
            {
                return(false);
            }
            _combatContext.Update(MobId_Kobai, MobId_MalevolentFury);
            if (Me.Combat)
            {
                // If the Blind Rage Trap is not on cooldown, move right next to Kobai and use it...
                // NB: We don't want to drop the trap unless we're pounding on Kobai
                if ((_combatContext.Kobai != null) &&
                    (Me.CurrentTarget == _combatContext.Kobai) &&
                    (_combatContext.BlindingRageTrap != null) &&
                    (_combatContext.BlindingRageTrap.CooldownTimeLeft <= TimeSpan.Zero))
                {
                    QBCLog.Info("Using Blinding Rage Trap");

                    if (!_combatContext.Kobai.IsWithinMeleeRange)
                    {
                        return(await UtilityCoroutine.MoveTo(_combatContext.Kobai.Location, "Kobai", MovementByType.NavigatorOnly));
                    }

                    if (Me.IsMoving)
                    {
                        await CommonCoroutines.StopMoving();
                    }

                    if (!Me.IsSafelyFacing(_combatContext.Kobai))
                    {
                        _combatContext.Kobai.Face();
                        await Coroutine.Sleep(Delay.LagDuration.Milliseconds);
                    }
                    await Coroutine.Sleep(Delay.BeforeButtonClick.Milliseconds);

                    _combatContext.BlindingRageTrap.Use();
                    await Coroutine.Sleep(Delay.AfterItemUse.Milliseconds);

                    return(true);
                }
                // "Steal Mask" aura...
                // If Kobai is blinded by rage, and the Malevolent Fury is not on the battlefield,
                // move right next to Kobai, and steal the mask...
                // NB: We only want to cause one Malevolet Fury to spawn.  If we click multiple times
                // then we get more.  So, only click if Fury is not already up.
                if ((_combatContext.Kobai != null) &&
                    Me.HasAura(AuraId_StealMask) &&
                    (_combatContext.MalevolentFury == null))
                {
                    QBCLog.Info("Pilfering Mask");

                    if (!_combatContext.Kobai.IsWithinMeleeRange)
                    {
                        return(await UtilityCoroutine.MoveTo(_combatContext.Kobai.Location, "Kobai", MovementByType.NavigatorOnly));
                    }

                    if (Me.CurrentTargetGuid != _combatContext.Kobai.Guid)
                    {
                        _combatContext.Kobai.Target();
                        if (!await Coroutine.Wait(
                                2000,
                                () => _combatContext.Kobai.IsValid &&
                                Me.CurrentTarget == _combatContext.Kobai))
                        {
                            return(false);
                        }
                    }
                    Lua.DoString("ExtraActionButton1:Click()");
                    await Coroutine.Sleep(Delay.AfterItemUse.Milliseconds);

                    return(true);
                }
            }
            // If we're not in combat, but have found Kobai, move to engage him...
            else
            {
                if (_combatContext.Kobai != null)
                {
                    // If Kobai is not in kill zone...
                    if (_combatContext.Kobai.Location.Distance(KobaiSafePullAreaAnchor) > KobaiSafePullAreaRadius)
                    {
                        if (await UtilityCoroutine_MoveToStartPosition())
                        {
                            return(true);
                        }

                        // Wait for Kobai to arrive...
                        QBCLog.Info("Waiting for Kobai to move into kill zone (dist: {0:F1})",
                                    Math.Max(_combatContext.Kobai.Location.Distance(KobaiSafePullAreaAnchor) - KobaiSafePullAreaRadius, 0.0));
                        await Coroutine.Wait(5000, () => Me.Combat);

                        return(true);
                    }

                    // Kobai in kill zone, pull him...
                    if (_combatContext.Kobai.Location.Distance(KobaiSafePullAreaAnchor) <= KobaiSafePullAreaRadius)
                    {
                        if (BotPoi.Current.Type != PoiType.Kill)
                        {
                            QBCLog.Info("Engaging Kobai");
                            BotPoi.Current = new BotPoi(_combatContext.Kobai, PoiType.Kill);
                            if (Me.CurrentTarget != _combatContext.Kobai)
                            {
                                _combatContext.Kobai.Target();
                                await Coroutine.Sleep(Delay.LagDuration.Milliseconds);

                                return(true);
                            }
                        }
                        return(false);
                    }

                    // Can't find Kobai--must've just been killed--wait for repop...
                    if (_combatContext.Kobai == null && Navigator.AtLocation(WaitPoint))
                    {
                        QBCLog.Info("Waiting for Kobai to respawn");
                        await Coroutine.Wait(5000, () => Me.Combat);

                        return(true);
                    }
                }

                if (!UtilIsProgressRequirementsMet(QuestId, QuestRequirementInLog, QuestRequirementComplete))
                {
                    BehaviorDone("Finished");
                    return(true);
                }

                // Move to start position, if needed...
                return(await UtilityCoroutine_MoveToStartPosition());
            }

            return(false);
        }
コード例 #23
0
 public void DLog(string format, params object[] args)
 {
     // following linecount hack is to stop dup suppression of Log window
     QBCLog.DeveloperInfo(format + (++s_lineCount % 2 == 0 ? "" : " "), args);
 }