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) { if (!InTree) { QBCLog.Fatal("==================================================================\n" + "NOT IN TREE!!! ENTER TREE TO USE CUSTOM BEHAVIOR\n" + "=================================================================="); } else { this.UpdateGoalText(QuestId); } // Setup settings to prevent interference with your behavior -- // These settings will be automatically restored by QuestBehaviorBase when Dispose is called // by Honorbuddy, or the bot is stopped. LevelBot.BehaviorFlags &= ~(BehaviorFlags.Combat | BehaviorFlags.Loot | BehaviorFlags.Vendor); } }
public override void OnStart() { // This reports problems, and stops BT processing if there was a problem with attributes... // We had to defer this action, as the 'profile line number' is not available during the element's // constructor call. OnStart_HandleAttributeProblem(); // 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 (!IsDone) { this.UpdateGoalText(QuestId); QuestTurnIn = new ForcedQuestTurnIn(null, (uint)QuestId, QuestName, (uint)TurnInId, TurnInName, TurnInLocation); if (QuestTurnIn == null) { QBCLog.Fatal("Unable to complete {0}", this.GetType().Name); } Targeting.Instance.RemoveTargetsFilter += Instance_RemoveTargetsFilter; QuestTurnIn.OnStart(); } }
private async Task <bool> GetInVehicleLogic() { // currently we only support using an item to get into vehicle if (ItemId > 0) { if (Me.IsFalling) { return(false); } var item = Me.BagItems.FirstOrDefault(i => i.Entry == ItemId); if (item == null) { QBCLog.Fatal("No Item with ID {0} was found in bags", ItemId); return(false); } item.Use(); if (!await Coroutine.Wait(6000, Query.IsInVehicle)) { QBCLog.Warning("Could not get into vehicle by using {0}.", item.SafeName); return(false); } CycleToNearestPointInPath(); _flightTimer.Reset(); } else { QBCLog.Fatal("Not in a vehicle"); } await Ascend(3000); return(true); }
protected override Composite CreateBehavior() { return(new PrioritySelector( // If behavior is complete, nothing to do, so bail... new Decorator(ret => _isBehaviorDone, new Action(delegate { QBCLog.Info("Behavior complete"); })), // If file does not exist, notify of problem... // Support for store profiles. They are handled by HB when there is no profile with given path new Decorator(ret => !IsStoreProfile(NewProfilePath) && !File.Exists(NewProfilePath), new Action(delegate { QBCLog.Fatal("Profile '{0}' does not exist. Download or unpack problem with profile?", NewProfilePath); _isBehaviorDone = true; })), // Load the specified profile... new Sequence( new Action(delegate { TreeRoot.StatusText = "Loading profile '" + NewProfilePath + "'"; QBCLog.Info("Loading profile '{0}'", ProfileName); ProfileManager.LoadNew(NewProfilePath, RememberProfile); }), new WaitContinue(TimeSpan.FromMilliseconds(300), ret => false, new ActionAlwaysSucceed()), new Action(delegate { _isBehaviorDone = true; }) ) )); }
public override void OnStart() { // This reports problems, and stops BT processing if there was a problem with attributes... // We had to defer this action, as the 'profile line number' is not available during the element's // constructor call. OnStart_HandleAttributeProblem(); // 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 (!IsDone) { PlayerQuest quest = StyxWoW.Me.QuestLog.GetQuestById((uint)QuestId); this.UpdateGoalText(QuestId); if (quest != null) { if (!quest.IsCompleted) { QBCLog.Fatal("Quest({0}, \"{1}\") is not complete.", QuestId, QuestName); _forcedDone = true; } } else { QBCLog.Warning("Quest({0}) is not in our log--skipping turn in.", QuestId); _forcedDone = true; } } }
public override void OnStart() { var questId = GetQuestId(); if (RidingPath.Waypoints.Count <= 0) { QBCLog.Fatal("<RidingPath> sub-element is not defined, or has no waypoints."); IsAttributeProblem = true; } if (!IsBrewfestInProgress()) { var message = "Brewfest is not in progress--cannot run behavior."; QBCLog.Fatal(message); BehaviorDone(message); return; } // Locate strategies for identified quest? _ramReacquireStrategy = _ramReacquireStrategies.FirstOrDefault(s => s.QuestId == questId); _ridingStrategy = _ridingStrategies.FirstOrDefault(s => s.QuestId == questId); if (_ridingStrategy == null) { var message = $"QuestId {questId} is not supported by this behavior"; QBCLog.Fatal(message); BehaviorDone(message); return; } // HACK for "Brew for Brewfest"... // "Brew for Brewfest" is not a 'normal' quest. You can pick it up, but it does not go in the toon's // log, and there is nowhere to turn it in. Once you have the quest, if you mess up, you cannot get it // again on that day. Once you have the quest, you just "keep going" until you no longer have a ram mount. // To make this work, we need to select the appropriate riding strategy (above), yet set the QuestId // to zero, so the 'quest complete' logic works as expected (I.e., we're not doing the behavior // in a context of a quest). if ((questId == QuestId_BrewForBrewfest_Alliance) | (questId == QuestId_BrewForBrewfest_Horde)) { VariantQuestIds = new List <int>(); } // 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. TerminationChecksQuestProgress = false; var isBehaviorShouldRun = OnStart_QuestBehaviorCore(); if (!isBehaviorShouldRun) { BehaviorDone(string.Format("Behavior for Quest({0}) appears complete.", questId)); return; } // Setup the BehaviorFlags as needed -- // These settings will be automatically restored by QuestBehaviorBase when Dispose is called // by Honorbuddy, or the bot is stopped. LevelBot.BehaviorFlags &= ~(BehaviorFlags.Combat | BehaviorFlags.Loot); RidingPath.WaypointVisitStrategy = HuntingGroundsType.WaypointVisitStrategyType.InOrder; }
private async Task <bool> MainCoroutine() { if (IsDone) { return(false); } if (TookPortal) { if (Me.IsMoving) { await CommonCoroutines.StopMoving(); } await Coroutine.Sleep(_postZoningDelay); BehaviorDone("Zoned into portal"); return(true); } if (Navigator.AtLocation(StartingPoint) && await WaitToRetry()) { return(true); } // Move to portal starting position... if (!Navigator.AtLocation(StartingPoint)) { if (!await UtilityCoroutine.MoveTo(StartingPoint, "Portal", MovementBy)) { QBCLog.Fatal("Unable to Navigate to StartingPoint"); } return(true); } if (await EnterPortal()) { return(true); } // Zoning failed, do we have any retries left? _retryCount += 1; if (_retryCount > MaxRetryCount) { var message = string.Format("Unable to go through portal in {0} attempts.", MaxRetryCount); // NB: Posting a 'fatal' message will stop the bot--which is what we want. QBCLog.Fatal(message); BehaviorDone(message); return(true); } RetryDelayTimer = new Stopwatch(); return(true); }
private async Task <bool> MainCoroutine() { var activeMover = WoWMovement.ActiveMover; if (activeMover == null) { return(false); } var immediateDestination = FindImmediateDestination(); // If we've no way to reach destination, inform user and quit... if (!Flightor.CanFly && !Navigator.CanNavigateWithin(Me.Location, immediateDestination, (float)DefaultArrivalTolerance)) { QBCLog.Fatal("Toon doesn't have flying capability in this area, and there is no ground path to the destination." + " Please learn the flying skill appropriate for this area."); BehaviorDone(); return(false); } // Arrived at destination? if (AtLocation(activeMover.Location, immediateDestination)) { var completionMessage = string.Format("Arrived at destination '{0}'", RoughDestination.Name); // Land if we need to... // NB: The act of landing may cause us to exceed the ArrivalTolerance specified. if (Land && Me.Mounted) { await UtilityCoroutine.LandAndDismount(string.Format("Landing at destination '{0}'", RoughDestination.Name)); BehaviorDone(completionMessage); return(true); } // Done... BehaviorDone(completionMessage); return(false); } // Do not run FlyTo when there is a PoI set... if (BotPoi.Current.Type != PoiType.None) { await Coroutine.Sleep(TimeSpan.FromSeconds(10)); QBCLog.DeveloperInfo("FlyTo temporarily suspended due to {0}", BotPoi.Current); return(true); } // Move closer to destination... Flightor.MoveTo(immediateDestination, !IgnoreIndoors); return(true); }
protected async Task <bool> MainCoroutine() { if (IsDone) { return(false); } if (!StyxWoW.Me.HasAura(AuraId_MechasharkXSteam)) { var controler = Controller; if (controler == null) { QBCLog.Fatal("Controler could not be found in ObjectManager"); return(true); } if (!controler.WithinInteractRange) { return((await CommonCoroutines.MoveTo(controler.Location)).IsSuccessful()); } if (await CommonCoroutines.StopMoving()) { return(true); } controler.Interact(); await Coroutine.Sleep(5000); return(true); } var hammer = Hammer; if (hammer == null) { QBCLog.Fatal("Hammer could not be found in ObjectManager"); return(true); } if (hammer.IsAlive && StyxWoW.Me.CurrentTarget != hammer) { await DoQuest(hammer); return(true); } if (StyxWoW.Me.QuestLog.GetQuestById(24817).IsCompleted) { Lua.DoString("VehicleExit()"); _isBehaviorDone = true; return(true); } return(false); }
private async Task UseTalismanOfFlameAscendancy() { WoWItem item = ObjectManager.GetObjectsOfType <WoWItem>().FirstOrDefault(i => i != null && i.Entry == 54814); if (item == null) { QBCLog.Fatal("Quest item \"Talisman of Flame Ascendancy\" not in inventory."); TreeRoot.Stop(); return; } Log("Use: {0}", item.SafeName); item.Use(true); await CommonCoroutines.SleepForLagDuration(); }
private Composite StateBehaviorPS_MountingVehicle() { return(new PrioritySelector( new Decorator(context => Me.IsQuestComplete(GetQuestId()), new Action(context => { BehaviorDone(string.Format("quest complete")); })), // If we're mounted on something other than the dragon, then dismount... new Decorator(context => Me.Mounted && !Query.IsViable(DragonVehicle), new ActionRunCoroutine(context => UtilityCoroutine.ExecuteMountStrategy(MountStrategyType.Dismount))), // If we're on the dragon, get moving... new Decorator(context => Query.IsViable(DragonVehicle), new PrioritySelector( SubBehaviorPS_InitializeVehicleAbilities(), new Action(context => { BehaviorState = BehaviorStateType.RidingOutToHuntingGrounds; }) )), // If we don't posssess item to summon the dragon, that's fatal... new Decorator(context => { ItemToSummonVehicle = Me.CarriedItems.FirstOrDefault(i => i.Entry == ItemIdToSummonVehicle); return !Query.IsViable(ItemToSummonVehicle); }, new Action(context => { QBCLog.Fatal("Unable to locate ItemId({0}) in inventory.", ItemIdToSummonVehicle); })), // Wait for item to come off cooldown... new Decorator(context => ItemToSummonVehicle.Cooldown > 0, new Action(context => { TreeRoot.StatusText = string.Format("Waiting for {0} cooldown ({1} remaining)", ItemToSummonVehicle.SafeName, Utility.PrettyTime(ItemToSummonVehicle.CooldownTimeLeft)); return RunStatus.Success; })), // Use the item new Decorator(context => !Me.IsCasting, new ActionFail(context => { // If we got booted out of a vehicle for some reason, reset the weapons... Weapon_DevourHuman = null; Weapon_FrozenDeathbolt = null; ItemToSummonVehicle.UseContainerItem(); })) )); }
private async Task <bool> BuyMount(int vendorId, WoWPoint vendorLocation, int itemId) { var item = Me.BagItems.FirstOrDefault(i => i.Entry == itemId); if (item == null) { return(await UtilityCoroutine.BuyItem( vendorId, vendorLocation, itemId, 1, noVendorFrameAction : () => QBCLog.Fatal("Npc ({0}) does not offer a vendor frame", vendorId), itemNotFoundAction : () => QBCLog.Fatal("Npc ({0}) does not sell the item with ID: {1}", vendorId, itemId), insufficientFundsAction : () => QBCLog.Fatal("Toon does not have enough funds to buy {0} from {1}", itemId, vendorId))); } item.Use(); _purchasedMountTimer.Reset(); await CommonCoroutines.SleepForRandomUiInteractionTime(); return(true); }
private async Task <bool> LanceUp() { var mainHand = Me.Inventory.Equipped.MainHand; if (mainHand != null && _itemIds_Lances.Contains(mainHand.Entry)) { return(false); } var bestLance = BestLance; if (bestLance == null) { QBCLog.Fatal("No lance in bags"); } else { bestLance.UseContainerItem(); } return(true); }
private async Task <bool> LanceUp() { var mainHand = Me.Inventory.Equipped.MainHand; if (mainHand != null && mainHand.Entry == ItemId_ArgentLance) { return(false); } var lance = ArgentLance; if (lance == null) { QBCLog.Fatal("No Argent Lance in bags"); } else { lance.UseContainerItem(); } return(true); }
public BearsUpThere(Dictionary <string, string> args) : base(args) { QBCLog.BehaviorLoggingContext = this; try { // Make certain quest is one of the ones we know how to do... var questId = GetQuestId(); if (questId == QuestId_BearsUpThere) { _mobId_bearTargets = MobId_Bear; } else if (questId == QuestId_ThoseBearsUpThere) { _mobId_bearTargets = MobId_DailyBear; } else { QBCLog.Fatal("This behavior can only do QuestId({0}) or QuestId({1}). (QuestId({2}) was seen.)", QuestId_BearsUpThere, QuestId_ThoseBearsUpThere, questId); IsAttributeProblem = true; } TerminationChecksQuestProgress = false; } 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; } }
protected override Composite CreateBehavior() { return(_root ?? (_root = new PrioritySelector( // check if we have finished 10 questions (marked complete) new Decorator(ret => Me.IsQuestComplete(QuestId), new PrioritySelector( new Decorator(ret => Me.HasAura("Mental Training"), new Sequence( new Action(ret => QBCLog.Info("Mental Training complete - exiting Orb")), new Action(ret => Lua.DoString("RunMacroText(\"/click OverrideActionBarButton4\")")), CreateWaitForLagDuration() ) ), new Action(ret => _isBehaviorDone = true) ) ), // if we don't have vehicle buff, use Orb of Ascension new Decorator(ret => !Me.HasAura("Mental Training"), new Sequence( new Action(delegate { QBCLog.Info("Using Orb of Ascension"); WoWItem orb = ObjectManager.GetObjectsOfType <WoWItem>().Where(u => u.Entry == 52828).FirstOrDefault(); if (orb == null) { QBCLog.Fatal("Quest item \"Orb of Ascension\" not in inventory."); } orb.Use(true); return RunStatus.Success; }), new WaitContinue(1, ret => Me.HasAura("Mental Training"), new ActionAlwaysSucceed()) ) ), // if we have YES aura 74008, then click yes new Decorator(ret => HasAura(Me, 74008), new Sequence( new Action(ret => QBCLog.Info("Answering YES")), new WaitContinue(TimeSpan.FromMilliseconds(500), ret => false, new ActionAlwaysSucceed()), new Action(ret => Lua.DoString("RunMacroText(\"/click OverrideActionBarButton1\")")), new WaitContinue(1, ret => !HasAura(Me, 74008), new ActionAlwaysSucceed()) ) ), // if we have NO aura 74009, then click no new Decorator(ret => HasAura(Me, 74009), new Sequence( new Action(ret => QBCLog.Info("Answering NO")), new WaitContinue(TimeSpan.FromMilliseconds(500), ret => false, new ActionAlwaysSucceed()), new Action(ret => Lua.DoString("RunMacroText(\"/click OverrideActionBarButton2\")")), new WaitContinue(1, ret => !HasAura(Me, 74009), new ActionAlwaysSucceed()) ) ), new Action(delegate { return RunStatus.Success; }) ) )); }
public override async Task <bool> Execute() { // If we cannot 'see' the mob yet, move to the rough location... var gossipMob = ObjectManager.GetObjectsOfType <WoWUnit>().FirstOrDefault(u => u.Entry == GossipMobId); if (gossipMob == null) { await UtilityCoroutine.MoveTo(GossipMobRoughLocation, "Gossip mob"); return(true); } // Move into interact range of mob... if (Me.Location.Distance(gossipMob.Location) > gossipMob.InteractRange) { if (await UtilityCoroutine.MoveTo(gossipMob.Location, gossipMob.Name)) { return(true); } } WoWMovement.MoveStop(); // Pull up gossip frame, if not visible if (!IsGossipFrameVisible()) { await UtilityCoroutine.Interact(gossipMob); await Coroutine.Sleep(Delay.AfterInteraction); return(true); } TreeRoot.StatusText = string.Format("Gossiping with {0}", gossipMob.Name); var gossipPageIndex = 0; while (gossipPageIndex < GossipOptions.Length) { GossipEntry gossipEntry; if (!TryGetGossipEntry(GossipOptions[gossipPageIndex], out gossipEntry)) { QBCLog.Fatal( "{0} is not offering gossip option {1} on page {2}." + " Did competing player alter NPC state?" + " Did you stop/start Honorbuddy?" + " Terminating behavior.", gossipMob.Name, GossipOptions[gossipPageIndex] + 1, gossipPageIndex + 1); Utility.CloseAllNpcFrames(); Me.ClearTarget(); return(false); } // Log the gossip option we're about to take... QBCLog.DeveloperInfo( "Selecting Gossip Option({0}) on page {1}: \"{2}\"", gossipEntry.Index + 1, gossipPageIndex + 1, gossipEntry.Text); GossipFrame.Instance.SelectGossipOption(GossipOptions[gossipPageIndex]); ++gossipPageIndex; await Coroutine.Wait((int)Delay.AfterInteraction.TotalMilliseconds, () => !IsGossipFrameVisible()); } // Gossip is complete, claim credit... Utility.CloseAllNpcFrames(); var message = string.Format("Gossip with {0} complete.", gossipMob.Name); QBCLog.DeveloperInfo(message); TreeRoot.StatusText = message; return(true); }
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; })) )); }
private Composite CreateTradeSkillCast() { return(new PrioritySelector( new Decorator(ctx => _numOfCasts >= NumOfTimes, new Action(ctx => _isBehaviorDone = true)), new Decorator(ret => StyxWoW.Me.IsCasting, new ActionAlwaysSucceed()), new Sequence( // check we have the material to craft recipe new DecoratorContinue(ctx => GetMaxRepeat(_recipeSpell) == 0, new Action( ctx => { _isBehaviorDone = true; return RunStatus.Failure; })), new Action(ctx => _recipeSpell.Cast()), // check if we're casting on an item. new DecoratorContinue(ctx => CastOnItemId.HasValue, new Sequence(ctx => StyxWoW.Me.CarriedItems.FirstOrDefault(i => i.Entry == CastOnItemId.Value), new DecoratorContinue(ctx => ctx == null, new Action(ctx => QBCLog.Fatal("Could not find ItemId({0}).", CastOnItemId.Value))), new Action(ctx => ((WoWItem)ctx).Use()), new Sleep(Delay.BeforeButtonClick), // click the enchant confirmation botton. new Action(ctx => Lua.DoString("local _,frame = StaticPopup_Visible('REPLACE_ENCHANT') if frame then StaticPopup_OnClick(frame, 1) end")))), new WaitContinue(TimeSpan.FromMilliseconds(2000), ctx => StyxWoW.Me.IsCasting, new ActionAlwaysSucceed()), new Action(ctx => _numOfCasts++), // wait for cast to finish. new WaitContinue(TimeSpan.FromMilliseconds(6000), ctx => !StyxWoW.Me.IsCasting, new ActionAlwaysSucceed())))); }