private Composite StateBehaviorPS_PathRetreating() { return(new PrioritySelector( // If no Egress path, build it... new Decorator(context => Path_Egress == null, new Action(context => { Path_Egress = FollowPath.FindPath_Egress(Mob_ToAvoid); QBCLog.Info("Retreating back to safespot due to {0}.", Me.Combat ? "combat" : string.Format("{0} too close (dist: {1:F1})", Mob_ToAvoid.SafeName, Mob_ToAvoid.Distance)); })), // If we've come to the end of our egress path, move back to safe spot... new Decorator(context => !Path_Egress.Any(), new Action(context => { Path_Ingress = null; Path_Egress = null; State_MainBehavior = StateType_MainBehavior.MovingToSafespot; })), // If we've arrived at the current waypoint, dequeue it... new Decorator(context => Navigator.AtLocation(Path_Egress.Peek().Location), new Action(context => { Path_Egress.Dequeue(); })), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( Path_Egress.Peek().Location, "retreat", MovementBy)) )); }
public override async Task <bool> Execute() { // If we have the quest, drop it... if (HasQuest(QuestId)) { Me.QuestLog.AbandonQuestById((uint)QuestId); await Coroutine.Wait(Delay.LagDuration, () => !HasQuest(QuestId)); return(true); } // If we cannot 'see' the mob yet, move to the rough location... var questGiver = ObjectManager.GetObjectsOfType <WoWUnit>().FirstOrDefault(u => u.Entry == QuestGiverId); if (questGiver == null) { await UtilityCoroutine.MoveTo(QuestGiverRoughLocation, "Quest Giver"); return(true); } if (!Navigator.AtLocation(questGiver.Location)) { return(await UtilityCoroutine.MoveTo(questGiver.Location, questGiver.Name)); } await ScriptHelpers.PickupQuest(questGiver, (uint)QuestId); await Coroutine.Wait(Delay.LagDuration, () => HasQuest(QuestId)); return(false); }
private async Task <bool> UtilityCoroutine_MoveToStartPosition() { if (Navigator.AtLocation(WaitPoint)) { return(false); } return(await UtilityCoroutine.MoveTo(WaitPoint, "Moving to start position", MovementByType.NavigatorOnly)); }
protected override Composite CreateMainBehavior() { return(new PrioritySelector( // If we don't have a selected target, find one... new Decorator(context => !IsMobQualified(SelectedTarget), new PrioritySelector( new ActionFail(context => { SelectedTarget = FindQualifiedMob(); }), // No qualifed mobs in immediate vicinity... new Decorator(context => !IsMobQualified(SelectedTarget), new PrioritySelector( new Decorator(context => Me.GotTarget, new Action(context => { Me.ClearTarget(); })), // NB: if the terminateBehaviorIfNoTargetsProvider argument evaluates to 'true', calling // this sub-behavior will terminate the overall behavior. new ActionRunCoroutine(context => _noMobsAtCurrentWaypoint ?? (_noMobsAtCurrentWaypoint = new UtilityCoroutine.NoMobsAtCurrentWaypoint( () => HuntingGrounds, () => MovementBy, null, () => { if (!WaitForNpcs) { BehaviorDone("Terminating--\"WaitForNpcs\" is false."); } }, () => TargetExclusionAnalysis.Analyze( Element, () => Query.FindMobsAndFactions(MobIds), TargetExclusionChecks)))))) )), // If qualified mob was found, move within range, if needed... // NB: A mob can lose its 'qualified' status for several reasons. For instance, // another player moves close to or tags the mob while we're on our way to it. new Decorator(context => IsMobQualified(SelectedTarget), new PrioritySelector( new ActionFail(context => { Utility.Target(SelectedTarget); }), new Decorator(context => IsDistanceCloseNeeded(SelectedTarget), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( SelectedTarget.Location, SelectedTarget.SafeName, MovementBy))), new ActionRunCoroutine(context => CommonCoroutines.StopMoving()), new Action(context => { Utility.Target(SelectedTarget, true); BehaviorDone(); }) )) )); }
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> MainLogic() { if (!Me.IsAlive) { return(false); } var bomb = Me.BagItems.FirstOrDefault(i => Query.IsViable(i) && i.Entry == 60849 || i.Entry == 60678); var bunny = ObjectManager.GetObjectsOfType <WoWUnit>() .Where(r => r.Entry == 44360) .OrderBy(r => r.Distance2D) .FirstOrDefault(); //Remove hook once were done with the quest if (bomb == null) { RemoveHook(); return(true); } if (bunny != null) { var bunnyDist = bunny.DistanceSqr; if (bunnyDist < 5 * 5) { bomb.Use(); SpellManager.ClickRemoteLocation(bunny.Location); await Coroutine.Sleep(Delay.AfterItemUse.Milliseconds); return(true); } if (bunnyDist < 35 * 35) { return(await UtilityCoroutine.MoveTo(bunny.Location, "Bunny", MovementByType.NavigatorOnly)); } } var stickbone = ObjectManager.GetObjectsOfType <WoWUnit>() .Where(r => r.Entry == 44329 && r.IsAlive) .OrderBy(r => r.Distance2D) .FirstOrDefault(); if (stickbone != null && stickbone.DistanceSqr < 5 * 5) { bomb.Use(); SpellManager.ClickRemoteLocation(stickbone.Location); await Coroutine.Sleep(Delay.AfterItemUse.Milliseconds); return(true); } return(false); }
private async Task <bool> MainLogic() { if (GetOffLocation != Vector3.Zero && Me.Location.DistanceSquared(GetOffLocation) < 2 * 2) { BehaviorDone("Successfully used the transport."); return(true); } if (Me.IsOnTransport || _usedTransport) { if (TransportLocation != Vector3.Zero && TransportLocation.DistanceSquared(EndLocation) < 1.5 * 1.5) { TreeRoot.StatusText = "Moving out of transport"; Navigator.PlayerMover.MoveTowards(GetOffLocation); return(true); } _usedTransport = true; TreeRoot.StatusText = "Waiting for the end location"; return(true); } if (Me.IsMoving) { return(false); } if (TransportLocation != Vector3.Zero && TransportLocation.DistanceSquared(StartLocation) < 1.5 * 1.5 && WaitAtLocation.DistanceSquared(Me.Location) < 2 * 2) { // don't do anything that can cause toon to move off course LevelBot.BehaviorFlags &= ~(BehaviorFlags.Vendor | BehaviorFlags.FlightPath | BehaviorFlags.Combat | BehaviorFlags.Loot); TreeRoot.StatusText = "Moving inside transport"; Navigator.PlayerMover.MoveTowards(StandLocation); return(true); } if (WaitAtLocation.DistanceSquared(Me.Location) > 2 * 2) { await UtilityCoroutine.MoveTo(WaitAtLocation, DestName, MovementBy); return(true); } await CommonCoroutines.LandAndDismount(); TreeRoot.StatusText = "Waiting for transport"; return(true); }
private async Task <bool> MoveFromEKToSilvermoonCityHorde() { var portal = ObjectManager.GetObjectsOfType <WoWGameObject>() .FirstOrDefault(g => g.Entry == GameObjectId_OrbOfTranslocation); if (portal == null || !portal.WithinInteractRange) { return(await(UtilityCoroutine.MoveTo(portal?.Location ?? _silvermoonCityPortalLoc, "Silvermoon City portal"))); } await CommonCoroutines.StopMoving(); portal.Interact(); await Coroutine.Sleep(3000); return(true); }
private Composite StateBehaviorPS_ReturningToBase() { // If we are not returning home... return(new PrioritySelector( new Decorator(context => IsInTank(), new CompositeThrottle(Throttle.UserUpdate, new ActionFail(context => { TreeRoot.StatusText = "Returning to base"; }) )), new Decorator(context => !Navigator.AtLocation(Location_ReturnToSchnottz), new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( Location_ReturnToSchnottz, "Commander Schnottz", MovementBy))), new Decorator(context => Me.IsQuestComplete(QuestId), new Action(context => BehaviorDone("quest complete"))) )); }
// 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. protected override Composite CreateMainBehavior() { return(new PrioritySelector( new Decorator(ret => Counter >= NumOfTimes, new Action(ret => BehaviorDone(string.Format("Object used {0} times.", Counter)))), new Decorator( ret => Location.Distance(StyxWoW.Me.Location) > 2, new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( Location, "destination", MovementBy))), new Decorator(ret => StyxWoW.Me.IsMoving, new Action(ret => { Navigator.PlayerMover.MoveStop(); })), new Decorator(ret => TargetNearest, new Sequence( new Action(context => Lua.DoString("TargetNearest()")), new SleepForLagDuration(), new ActionAlwaysFail())), // fall through new Decorator(ret => (Item != null) && (Item.Cooldown <= 0), new Sequence( new Action(ret => { TreeRoot.StatusText = string.Format("Using {0} (count: {1}/{2})", Item.SafeName, Counter, NumOfTimes); Item.UseContainerItem(); Counter++; }), new SleepForLagDuration(), new Sleep(WaitTime))) )); }
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()) ))) )); }
private Composite StateBehaviorPS_MountingVehicle() { return(new PrioritySelector( new Decorator(context => Me.IsQuestComplete(QuestId), new Action(context => { BehaviorDone(); })), // If we're in the vehicle, wait for the ride out to hunting grounds to complete... new Decorator(context => IsInTank(), new PrioritySelector( SubBehaviorPS_InitializeVehicleAbilities(), new Action(context => { BehaviorState = BehaviorStateType.RidingOutToHuntingGrounds; }) )), // If vehicle is in "enter vehicle" animation, wait for the animation to complete... new Decorator(context => FindVehicle_OwnedByMe(MobId_SchnottzSiegeTankInstanced) != null, new PrioritySelector( new CompositeThrottle(Throttle.UserUpdate, new Action(context => { TreeRoot.StatusText = string.Format("Waiting for {0} to become ready.", Utility.GetObjectNameFromId(MobId_SchnottzSiegeTankInstanced)); })), new ActionAlwaysSucceed() )), // Locate a vehicle to mount... new Decorator(context => !Query.IsViable(Vehicle), new PrioritySelector( new Action(context => { Vehicle = Query.FindMobsAndFactions(Utility.ToEnumerable(MobId_SchnottzSiegeTank)) .FirstOrDefault() as WoWUnit; if (Query.IsViable(Vehicle)) { Utility.Target(Vehicle); return RunStatus.Success; } return RunStatus.Failure; // fall through }), // No vehicle found, move to staging area... new Decorator(ctx => !Navigator.AtLocation(Location_VehicleStagingArea), new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( Location_VehicleStagingArea, "Vehicle Staging Area", MovementBy))), // Wait for vehicle to respawn... new CompositeThrottle(Throttle.UserUpdate, new Action(context => { TreeRoot.StatusText = string.Format("Waiting for {0} to respawn.", Utility.GetObjectNameFromId(MobId_SchnottzSiegeTank)); })) )), // Move to vehicle and enter... new CompositeThrottle(Throttle.UserUpdate, new Action(context => { TreeRoot.StatusText = string.Format("Moving to {0}", Vehicle.SafeName); })), new Decorator(context => !Vehicle.WithinInteractRange, new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( Vehicle.Location, Vehicle.SafeName, MovementBy))), new Decorator(context => Me.IsMoving, new Action(context => { Navigator.PlayerMover.MoveStop(); })), new Decorator(context => Me.Mounted, new ActionRunCoroutine(context => UtilityCoroutine.ExecuteMountStrategy(MountStrategyType.DismountOrCancelShapeshift))), new ActionFail(context => { // If we got booted out of a vehicle for some reason, reset the weapons... WeaponFireCannon = null; Utility.Target(Vehicle); Vehicle.Interact(); }), new Wait(TimeSpan.FromMilliseconds(10000), context => IsInTank(), new ActionAlwaysSucceed()), new ActionAlwaysSucceed() )); }
protected override Composite CreateMainBehavior() { return(new PrioritySelector( // PvP server considerations... // Combat is disabled while on the Taxi. If on the ground, we want it enabled // in case we get attacked on a PvP server. new Decorator(context => !LevelBot.BehaviorFlags.HasFlag(BehaviorFlags.Combat), new Action(context => { LevelBot.BehaviorFlags |= BehaviorFlags.Combat; })), // Move to flight master, and interact to take taxi ride... new Decorator(context => !Me.OnTaxi, new PrioritySelector(context => { FlightMaster = Query.FindMobsAndFactions(Utility.ToEnumerable <int>(MobId_FlightMaster)) .FirstOrDefault() as WoWUnit; return context; }, // If flight master not in view, move to where he should be... new Decorator(context => FlightMaster == null, new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( WaitLocation, "FlightMaster location", MovementBy))), // Make certain the bombs are in our backpack... new ActionRunCoroutine( ctx => _waitForInventoryItem ?? (_waitForInventoryItem = new UtilityCoroutine.WaitForInventoryItem( () => ItemId_Bomb, () => { QBCLog.ProfileError( "Cannot continue without required item: {0}", Utility.GetItemNameFromId(ItemId_Bomb)); BehaviorDone(); }))), // Move to flightmaster, and gossip to hitch a ride... new Decorator(context => FlightMaster != null, new PrioritySelector( new Decorator(context => !FlightMaster.WithinInteractRange, new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( FlightMaster.Location, FlightMaster.SafeName, MovementBy))), new ActionRunCoroutine(context => CommonCoroutines.StopMoving()), new Decorator(ctx => Me.Mounted, new ActionRunCoroutine(ctx => CommonCoroutines.LandAndDismount())), new Decorator(context => !GossipFrame.Instance.IsVisible, new Action(context => { FlightMaster.Interact(); })), new Action(context => { GossipFrame.Instance.SelectGossipOption(GossipOption); }) )) )) )); }
protected override Composite CreateMainBehavior() { return(_root ?? (_root = new PrioritySelector( // don't drop down while wait timer is running new Decorator(ctx => !_waitTimer.IsFinished, new ActionAlwaysSucceed()), new Decorator(ret => Counter > NumOfTimes, new Action(ret => BehaviorDone(string.Format("Used the item {0} times", NumOfTimes)))), // If item is not in our backpack, behavior is done... new Decorator(context => Item == null, new Action(context => { QBCLog.Error("ItemId({0}) is not in our backpack", ItemId); TreeRoot.Stop(); BehaviorDone("Item is not in our backpack"); })), // Wait for item to come off of cooldown... new Decorator(context => Item.CooldownTimeLeft > TimeSpan.Zero, new Action(context => QBCLog.Info("Waiting for {0} to leave cooldown (time remaining: {1})", Item.SafeName, Item.CooldownTimeLeft))), new Decorator( ret => UseType == QBType.PointToPoint, new PrioritySelector( new Decorator( ret => Me.Location.Distance(MoveToLocation) > 3, new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy))), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Quest Item: {0} Out of {1} Times", Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(ClickToLocation)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new SleepForLagDuration(), new Action(ret => Counter++), new Action(ret => SpellManager.ClickRemoteLocation(ClickToLocation)), new Action(ctx => _waitTimer.Reset()) ))), new Decorator( ret => UseType == QBType.PointToObject, new PrioritySelector( new Decorator( ret => UseObject == null && Me.Location.DistanceSqr(MoveToLocation) >= 2 * 2, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to location"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy)))), new Decorator( ret => UseObject != null, new PrioritySelector( new Decorator( ret => UseObject.DistanceSqr >= Range * Range, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving closer to the object"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(UseObject.Location, "UseObject location", MovementBy)))), new Decorator( ret => UseObject.DistanceSqr < MinRange * MinRange, new Sequence( new Action(ret => TreeRoot.StatusText = "Too Close, Backing Up"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo( WoWMathHelper.CalculatePointFrom(Me.Location, UseObject.Location, (float)MinRange + 2f), "Backing up", MovementBy)) )), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Item: {0} {1} Out of {2} Times", UseObject.SafeName, Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(UseObject.Location)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new Action(ret => Counter++), new SleepForLagDuration(), new Action(ret => SpellManager.ClickRemoteLocation(UseObject.Location)), new Action(ret => _npcBlacklist.Add(UseObject.Guid)), new Action(ctx => _waitTimer.Reset())))), new Action(ret => TreeRoot.StatusText = "No objects around. Waiting") )), new Decorator( ret => UseType == QBType.ToObject, new PrioritySelector( new Decorator( ret => UseObject != null, new PrioritySelector( new Decorator( ret => UseObject.DistanceSqr >= Range * Range, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to object's range"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(UseObject.Location, "UseObject location", MovementBy)))), new Decorator( ret => UseObject.DistanceSqr < MinRange * MinRange, new Sequence( new Action(ret => TreeRoot.StatusText = "Too Close, Backing Up"), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( WoWMathHelper.CalculatePointFrom(Me.Location, UseObject.Location, (float)MinRange + 2f), "Backing up", MovementBy)) )), new Sequence( new Action(ret => TreeRoot.StatusText = string.Format("Using Item: {0} {1} Out of {2} Times", UseObject.SafeName, Counter, NumOfTimes)), new Action(ret => Navigator.PlayerMover.MoveStop()), new Action(ret => Me.SetFacing(UseObject.Location)), new SleepForLagDuration(), new Action(ret => Item.UseContainerItem()), new Action(ret => Counter++), new SleepForLagDuration(), new Action(ret => SpellManager.ClickRemoteLocation(UseObject.Location)), new Action(ret => _npcBlacklist.Add(UseObject.Guid)), new Action(ctx => _waitTimer.Reset())))), new Decorator( ret => Me.Location.DistanceSqr(MoveToLocation) > 2 * 2, new Sequence( new Action(ret => TreeRoot.StatusText = "Moving to location"), new ActionRunCoroutine(context => UtilityCoroutine.MoveTo(MoveToLocation, "Destination", MovementBy)))) )) ))); }
private async Task <bool> TrainMount() { if (!TrainInOutland && !TrainInOldWorld) { return(false); } var trainerId = GetTrainerId(); if (trainerId == 0) { return(false); } var trainer = ObjectManager.GetObjectsOfType <WoWUnit>() .Where(u => u.Entry == trainerId && !u.IsDead) .OrderBy(u => u.DistanceSqr).FirstOrDefault(); WoWPoint trainerLoc; string trainerName; if (trainer == null) { var traderEntry = Styx.CommonBot.ObjectDatabase.Query.GetNpcById((uint)trainerId); if (traderEntry == null) { return(false); } trainerLoc = traderEntry.Location; trainerName = traderEntry.Name; } else { trainerLoc = trainer.Location; trainerName = trainer.SafeName; } if (trainer == null || !trainer.WithinInteractRange) { return(await UtilityCoroutine.MoveTo(trainerLoc, "Riding Trainer: " + trainerName)); } if (await CommonCoroutines.StopMoving()) { return(true); } // Turnin any quests since they can interfer with training. if (trainer.HasQuestTurnin()) { return(await UtilityCoroutine.TurninQuest(trainer, trainer.Location)); } if (!TrainerFrame.Instance.IsVisible) { trainer.Interact(); await CommonCoroutines.SleepForLagDuration(); return(true); } TrainerFrame.Instance.BuyAll(); await CommonCoroutines.SleepForRandomUiInteractionTime(); return(true); }
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); }
private async Task <bool> StateCoroutine_MountingVehicle() { if (Me.IsQuestComplete(QuestId)) { BehaviorDone(); return(true); } if (IsInBalloon()) { await SubCoroutine_InitializeVehicleAbilities(); BehaviorState = BehaviorStateType.RidingOutToHuntingGrounds; return(true); } // Locate a vehicle to mount... if (!Query.IsViable(Vehicle)) { Vehicle = Query.FindMobsAndFactions(Utility.ToEnumerable(MobId_SteamwheedleRescueBalloon)) .FirstOrDefault() as WoWUnit; if (Query.IsViable(Vehicle)) { Utility.Target(Vehicle); return(true); } // No vehicle found, move to staging area... if (!Navigator.AtLocation(VehicleStagingArea)) { return(await UtilityCoroutine.MoveTo(VehicleStagingArea, "Vehicle Staging Area", MovementBy)); } await(_updateUser_MountingVehicle_waitingForSpawn ?? (_updateUser_MountingVehicle_waitingForSpawn = new ThrottleCoroutineTask( Throttle.UserUpdate, async() => TreeRoot.StatusText = string.Format("Waiting for {0} to respawn.", Utility.GetObjectNameFromId(MobId_SteamwheedleRescueBalloon))))); // Wait for vehicle to respawn... return(true); } // Wait for vehicle to respawn... await(_updateUser_MountingVehicle_movingToVehicle ?? (_updateUser_MountingVehicle_movingToVehicle = new ThrottleCoroutineTask( Throttle.UserUpdate, async() => TreeRoot.StatusText = string.Format("Moving to {0}", Vehicle.SafeName)))); if (!Vehicle.WithinInteractRange) { return(await UtilityCoroutine.MoveTo(Vehicle.Location, Vehicle.SafeName, MovementBy)); } if (Me.IsMoving) { await CommonCoroutines.StopMoving(); } if (Me.Mounted && await UtilityCoroutine.ExecuteMountStrategy( MountStrategyType.DismountOrCancelShapeshift)) { return(true); } // If we got booted out of a vehicle for some reason, reset the weapons... WeaponLifeRocket = null; WeaponPirateDestroyingBomb = null; WeaponEmergencyRocketPack = null; Utility.Target(Vehicle); await Coroutine.Sleep((int)Delay.AfterInteraction.TotalMilliseconds); Vehicle.Interact(); await Coroutine.Wait(10000, IsInBalloon); return(true); }
private async Task <bool> PurchaseGroundMount_Alliance() { switch (Me.Race) { case WoWRace.Human: return(await TurninQuestAndBuyMount( MobId_RandalHunter, _randalHunterLoc, QuestId_LearnToRide_Human, MobId_KatieHunter, _katieHunterLoc, ItemId_PintoBridle)); case WoWRace.Pandaren: return(await TurninQuestAndBuyMount( MobId_MeiLin, _meiLinLoc, QuestId_LearnToRide_Pandaren, MobId_OldWhitenose, _oldWhitenoseLoc, ItemId_ReinsOfTheBlackDragonTurtle)); case WoWRace.Gnome: return(await TurninQuestAndBuyMount( MobId_BinjyFeatherwhistle, _binjyFeatherwhistleLoc, QuestId_LearnToRide_Gnome, MobId_MilliFeatherwhistle, _milliFeatherwhistleLoc, ItemId_BlueMechanostrider)); case WoWRace.Dwarf: return(await TurninQuestAndBuyMount( MobId_UlthamIronhorn, _ulthamIronhornLoc, QuestId_LearnToRide_Dwarf, MobId_VeronAmberstill, _veronAmberstillLoc, ItemId_WhiteRam)); case WoWRace.NightElf: if (InEasternKingdoms) { return(await UtilityCoroutine.UseTransport( GameObjectId_Ship_TheBravery, _theBraveryStartLoc, _theBraveryEndLoc, _theBraveryWaitAtLoc, _theBraveryStandAtLoc, _theBraveryGetOffAtLoc)); } if (!InKalimdor) { return(false); } return(await TurninQuestAndBuyMount( MobId_Jartsam, _jartsamLoc, QuestId_LearnToRide_NightElf, MobId_Lelanai, _lelanaiLoc, ItemId_ReinsOfTheStripedNightsaber)); case WoWRace.Draenei: if (InEasternKingdoms) { return(await UtilityCoroutine.UseTransport( GameObjectId_Ship_TheBravery, _theBraveryStartLoc, _theBraveryEndLoc, _theBraveryWaitAtLoc, _theBraveryStandAtLoc, _theBraveryGetOffAtLoc)); } // port over to Exodar if (InKalimdor && Me.ZoneId != 3557) { var portal = ObjectManager.GetObjectsOfType <WoWGameObject>() .FirstOrDefault(g => g.Entry == GameObjectId_PortalToExodar); if (portal == null || !portal.WithinInteractRange) { return(await(UtilityCoroutine.MoveTo(portal != null ? portal.Location : _exodarPortalLoc, "Exodar portal"))); } portal.Interact(); await CommonCoroutines.SleepForLagDuration(); return(true); } if (Me.ZoneId != 3557) { return(false); } // Turnin the 'Learn To Ride At The Exodar' quest if in log if (_profileHelpers.HasQuest(QuestId_LearnToRideAtTheExodar) && _profileHelpers.IsQuestCompleted(QuestId_LearnToRideAtTheExodar)) { return(await UtilityCoroutine.TurninQuest(MobId_Aalun, _aalunLoc, QuestId_LearnToRideAtTheExodar)); } return(await TurninQuestAndBuyMount( MobId_Aalun, _aalunLoc, QuestId_LearnToRide_Draenei, MobId_ToralliusThePackHandler, _toralliusThePackHandlerLoc, ItemId_BrownElekk)); } return(false); }
protected override Composite CreateBehavior_CombatMain() { return(new Decorator(context => !IsDone, new PrioritySelector( // Update values for this BT node visit... new Action(context => { VehicleUnoccupied = FindUnoccupiedVehicle(); // Figure out our final destination (i.e., a location or a mob)... // NB: this can change as we travel. If our destination is a mob, // We can't "see" distant mobs until we get within 100 yards or so of them. // Until we close that distance, we'll head towards the provided location. // As soon as we "see" the mob, we'll switch to the mob as the destination. FinalDestination = Destination; FinalDestinationName = "destination"; if (MobIds.Count() > 0) { // If we can see our destination mob, calculate a path to it... var nearestMob = Query.FindMobsAndFactions(MobIds).OrderBy(u => u.Distance).FirstOrDefault() as WoWUnit; if (nearestMob != null) { // Target destination mob as feedback to the user... Utility.Target(nearestMob); FinalDestination = nearestMob.Location; FinalDestinationName = nearestMob.SafeName; } } return RunStatus.Failure; // fall thru }), // Proceed if we're not in combat, or are ignoring it... new Decorator(context => !Me.Combat || IgnoreCombat, new PrioritySelector( // If we were successfully mounted... // and within a few yards of our destination when we were dismounted, we must // assume we were auto-dismounted, and the behavior is complete... new Decorator(context => DidSuccessfullyMount && !IsInVehicle() && (WoWMovement.ActiveMover.Location.Distance(FinalDestination) < 15.0), new Action(context => { BehaviorDone(); })), // Enable combat while not in a vehicle new Decorator(ctx => (LevelBot.BehaviorFlags & BehaviorFlags.Combat) == 0 && !Query.IsInVehicle(), new Action(ctx => LevelBot.BehaviorFlags |= BehaviorFlags.Combat)), // Disable combat while in a vehicle new Decorator(ctx => (LevelBot.BehaviorFlags & BehaviorFlags.Combat) != 0 && Query.IsInVehicle(), new Action(ctx => LevelBot.BehaviorFlags &= ~BehaviorFlags.Combat)), // If we're not in a vehicle, go fetch one... new Decorator(context => !IsInVehicle() && Query.IsViable(VehicleUnoccupied), new Sequence( new CompositeThrottleContinue( Throttle.UserUpdate, new Action(context => { TreeRoot.StatusText = string.Format("Moving to {0} {1}", VehicleUnoccupied.SafeName, Me.Combat ? "(ignoring combat)" : ""); })), new DecoratorContinue(context => VehicleUnoccupied.WithinInteractRange, new Action(context => { VehicleUnoccupied.Interact(); })), new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( VehicleUnoccupied.Location, VehicleUnoccupied.SafeName, MovementBy)) )), // If we can't find a vehicle, terminate if requested... new CompositeThrottle( context => !IsInVehicle() && !Query.IsViable(VehicleUnoccupied), Throttle.UserUpdate, new Action(context => { if (!WaitForVehicle) { BehaviorDone(string.Format("No Vehicle, and WaitForVehicle=\"{0}\"", WaitForVehicle)); } else { TreeRoot.StatusText = "No vehicles in area--waiting for vehicle to become available."; } })), // Move vehicle to destination... new Decorator(context => IsInVehicle(), new PrioritySelector( // If we successfully mounted the vehicle, record the fact... new Decorator(context => !DidSuccessfullyMount, new Action(context => { DidSuccessfullyMount = true; })), new Decorator(context => !Navigator.AtLocation(FinalDestination), new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( FinalDestination, FinalDestinationName, MovementBy))), new Decorator(context => WoWMovement.ActiveMover.IsMoving, new Action(context => { WoWMovement.MoveStop(); })), // Arrived at destination, use spell if necessary... // NB: We want to make certain movement is settled before we attempt // to cast spell, so we won't be interrupted. new SleepForLagDuration(), CreateSpellBehavior() )) )), // Squelch combat, if requested... new Decorator(context => IgnoreCombat, new ActionAlwaysSucceed()) ))); }
private Composite CreateMainBehavior() { return(new PrioritySelector( // If quest is done, behavior is done... new Decorator(context => IsDone, new Action(context => { _isBehaviorDone = true; QBCLog.Info("Finished"); })), // Stateful Operation: new Switch <StateType_MainBehavior>(context => State_MainBehavior, #region State: DEFAULT new Action(context => // default case { QBCLog.MaintenanceError("StateType_MainBehavior({0}) is unhandled", State_MainBehavior); TreeRoot.Stop(); _isBehaviorDone = true; }), #endregion #region State: Dropping Off Victim new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.DroppingOffVictim, new PrioritySelector( // If Watchman dropped off, go get another... new Decorator(context => !Me.HasAura(AuraId_RescueDrowningWatchman), new Action(context => { WoWMovement.MoveStop(); _currentPath = null; SelectedTarget = null; State_MainBehavior = StateType_MainBehavior.PathingOutToVictim; })), // Move to drop off spot... new Decorator(context => Me.Location.Distance(PositionToMakeLandfall) > Navigator.PathPrecision, new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( PositionToMakeLandfall, "back to shore"))) )), #endregion #region State: Pathing Out to Victim new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.PathingOutToVictim, new PrioritySelector( // If our selected target is no good, find another... new Decorator(context => !IsViableDrowningWatchman(SelectedTarget), new Action(context => { QBCLog.Info("Finding new Drowning Watchman to save"); _currentPath = null; SelectedTarget = FindDrowningWatchman(); })), // Show user which target we're after... new Decorator(context => Me.CurrentTarget != SelectedTarget, new Action(context => { SelectedTarget.Target(); })), // If we don't have a path to victim, find one... new Decorator(context => _currentPath == null, new Action(context => { _currentPath = FindPath(Me.Location, SelectedTarget.Location); })), // If path completely consumed, we're done... new Decorator(context => _currentPath.Count() <= 0, new Action(context => { State_MainBehavior = StateType_MainBehavior.Rescuing; })), // If we've arrived at the current waypoint, dequeue it... new Decorator(context => Navigator.AtLocation(_currentPath.Peek()), new Action(context => { _currentPath.Dequeue(); })), // Follow the prescribed path... new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( _currentPath.Peek(), "out to Drowned Watcman")) )), #endregion #region State: Rescuing new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.Rescuing, new PrioritySelector( // If we've got the Watchman, start heading in... new Decorator(context => Me.HasAura(AuraId_RescueDrowningWatchman), new Action(context => { _currentPath = null; State_MainBehavior = StateType_MainBehavior.PathingIntoShore; })), // If our selected target is no good, find another... new Decorator(context => !IsViableDrowningWatchman(SelectedTarget), new Action(context => { _currentPath = null; SelectedTarget = null; State_MainBehavior = StateType_MainBehavior.PathingOutToVictim; })), // Go get a fresh Drowning Watchman... UtilityBehavior_InteractWithMob(context => SelectedTarget) )), #endregion #region State: Pathing Into Shore new SwitchArgument <StateType_MainBehavior>(StateType_MainBehavior.PathingIntoShore, new PrioritySelector( // If we don't have a path, find the correct one... new Decorator(context => _currentPath == null, new Action(context => { _currentPath = FindPath(Me.Location, PositionToMakeLandfall); })), // If path completely consumed, we're done... new Decorator(context => _currentPath.Count() <= 0, new Action(context => { State_MainBehavior = StateType_MainBehavior.DroppingOffVictim; })), // If we've lost the Watchman we rescued, go fetch another... new Decorator(context => !Me.HasAura(AuraId_RescueDrowningWatchman), new Action(context => { _currentPath = null; SelectedTarget = null; State_MainBehavior = StateType_MainBehavior.PathingOutToVictim; })), // If we've arrived at the current waypoint, dequeue it... new Decorator(context => Navigator.AtLocation(_currentPath.Peek()), new Action(context => { _currentPath.Dequeue(); })), // Follow the prescribed path... new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( _currentPath.Peek(), "in to drop off Drowned Watchman")) )) #endregion ))); }
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); }
private Composite UtilityBehavior_InteractWithMob(WoWUnitDelegate unitToInteract) { return(new PrioritySelector(interactUnitContext => unitToInteract(interactUnitContext), new Decorator(interactUnitContext => IsViable((WoWUnit)interactUnitContext), new PrioritySelector( // Show user which unit we're going after... new Decorator(interactUnitContext => Me.CurrentTarget != (WoWUnit)interactUnitContext, new Action(interactUnitContext => { ((WoWUnit)interactUnitContext).Target(); })), // If not within interact range, move closer... new Decorator(interactUnitContext => !((WoWUnit)interactUnitContext).WithinInteractRange, new ActionRunCoroutine( interactUnitContext => UtilityCoroutine.MoveTo( ((WoWUnit)interactUnitContext).Location, "to interact with " + ((WoWUnit)interactUnitContext).SafeName))), new Decorator(interactUnitContext => Me.IsMoving, new Action(interactUnitContext => { WoWMovement.MoveStop(); })), new Decorator(interactUnitContext => !Me.IsFacing((WoWUnit)interactUnitContext), new Action(interactUnitContext => { Me.SetFacing((WoWUnit)interactUnitContext); })), // Blindly interact... // Ideally, we would blacklist the unit if the interact failed. However, the HB API // provides no CanInteract() method (or equivalent) to make this determination. new Action(interactUnitContext => { QBCLog.DeveloperInfo("Interacting with {0}", ((WoWUnit)interactUnitContext).SafeName); ((WoWUnit)interactUnitContext).Interact(); return RunStatus.Failure; }), new Wait(TimeSpan.FromMilliseconds(1000), context => false, new ActionAlwaysSucceed()) )))); }
private async Task <bool> Coroutine_CombatMain() { if (IsDone) { return(false); } if (!Query.IsInVehicle()) { // only move to vehicle if doing nothing else if (!Targeting.Instance.IsEmpty() || BotPoi.Current.Type != PoiType.None) { return(false); } WoWUnit amber = Amber; // Wait for Amber to load in the ObjectMananger. if (amber == null || !amber.WithinInteractRange) { var moveTo = amber != null ? amber.Location : _vehicleLoc; await UtilityCoroutine.MoveTo(moveTo, "Moving to Start Amber(Human) Story", MovementBy); return(true); } if (await CommonCoroutines.StopMoving()) { return(true); } if (!GossipFrame.Instance.IsVisible) { amber.Interact(); await CommonCoroutines.SleepForRandomUiInteractionTime(); return(true); } if (GossipFrame.Instance.GossipOptionEntries != null) { GossipFrame.Instance.SelectGossipOption(0); await CommonCoroutines.SleepForRandomUiInteractionTime(); return(true); } return(true); } if (await InteractWithUnit(HozenEnemy)) { return(true); } if (await InteractWithUnit(OrcEnemy)) { return(true); } if (!Me.HasAura("See Quest Invis 5")) { var turret = Turret; if (TurretLocation.DistanceSqr(Me.Location) > 3 * 3) { await UtilityCoroutine.MoveTo(TurretLocation, "Turret Location", MovementBy); return(true); } if (turret == null) { TreeRoot.StatusText = "Waiting for turret to spawn"; return(true); } if (!turret.WithinInteractRange) { await UtilityCoroutine.MoveTo(TurretLocation, "interact range of turret", MovementBy); return(true); } if (await CommonCoroutines.StopMoving()) { return(true); } QBCLog.Info("Using turret"); Turret.Interact(); return(true); } return(false); }
private Composite StateBehaviorPS_MovingToSafeSpot() { return(new PrioritySelector( // If a "Move Near" mob was specified, move to it... new Decorator(context => MobIdToMoveNear > 0, new PrioritySelector( new Decorator(context => Query.IsViable(Mob_ToMoveNear), new PrioritySelector( // Target the MoveToNpc, as feedback to the user... new ActionFail(context => { Utility.Target(Mob_ToMoveNear); }), // Move to mob... new Decorator(ctx => !Navigator.AtLocation(Mob_ToMoveNear.Location), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( Mob_ToMoveNear.Location, Mob_ToMoveNear.SafeName, MovementBy))) )), // Need to wait for Mob to respawn... new Decorator(context => !Query.IsViable(Mob_ToMoveNear), new Action(context => { TreeRoot.StatusText = string.Format("Waiting for {0} to respawn", Utility.GetObjectNameFromId(MobIdToMoveNear)); })) )), // No "Move Near" mob, so use the provided Safe spot coordinates... new Decorator(context => MobIdToMoveNear <= 0 && !Navigator.AtLocation(SafespotLocation), new ActionRunCoroutine( context => UtilityCoroutine.MoveTo( SafespotLocation, "safe spot", MovementBy))), // Dismount once we've arrived at mob or destination... new Decorator(ctx => Me.Mounted, new ActionRunCoroutine(ctx => CommonCoroutines.LandAndDismount())), new Decorator(ctx => StyxWoW.Me.IsMoving, new Action(ctx => WoWMovement.MoveStop())), // Target and Face the AvoidNpc, as feedback to the user... new ActionFail( context => { Utility.Target(Mob_ToAvoid, true); }), // If AvoidNpc is not around, // or if AvoidNpc is prescribed distance away, and facing away from us, // we're done... new Decorator(context => IsSafeToMoveToDestination(Mob_ToAvoid), new Action(context => { FollowPath.DismissPetIfNeeded(); Path_Ingress = null; Path_Egress = null; State_MainBehavior = StateType_MainBehavior.PathIngressing; })), // Tell user what we're up to... new CompositeThrottle(Throttle.UserUpdate, new Action(context => { TreeRoot.StatusText = string.Format("Waiting for '{0}' to move {1:F1}/{2:F1} yards away, and pathing away from us.", Mob_ToAvoid.SafeName, Mob_ToAvoid.Distance, AvoidDistance); })) )); }
private async Task <bool> MainCoroutine() { // break if we are done or we are not in combat and targting is not empty, we want the botbase to clear path for us. if (IsDone || (!Me.Combat && Targeting.Instance.FirstUnit != null) || !Me.IsAlive) { return(false); } if (!Query.IsViable(SelectedNpc)) { SelectedNpc = GetNpc(); } if (!Query.IsViable(SelectedNpc) || !Me.IsActuallyInCombat && Targeting.Instance.FirstUnit == null) { // move to search area if (SearchLocation != Vector3.Zero && !Navigator.AtLocation(SearchLocation)) { await UtilityCoroutine.MoveTo(SearchLocation, "Search Area", MovementBy); } // Dismount after reaching search location. else if ((SearchLocation == Vector3.Zero || Navigator.AtLocation(SearchLocation)) && Me.Mounted) { await UtilityCoroutine.ExecuteMountStrategy(MountStrategyType.Dismount); } else { TreeRoot.StatusText = "Waiting for NPC to spawn"; } return(true); } if (SelectedNpc.IsDead && SelectedNpc.TaggedByMe && !VariantQuestIds.Any()) { BehaviorDone(); return(true); } if (SelectedNpc.HasAura(ImmunityAuraId)) { if (BotPoi.Current.AsObject == SelectedNpc) { BotPoi.Clear("Mob is immune"); } var targetedMob = Targeting.Instance.FirstUnit; if (targetedMob != null && ImmunityBreakingMobIds.Contains((int)targetedMob.Entry)) { if (targetedMob.IsTargetingMeOrPet) { // move close enough to shielded NPC so that the exploding mobs will hit it when killed. var myMinDistance = Math.Max(2, MaxRange - targetedMob.MeleeRange); if (SelectedNpc.DistanceSqr > myMinDistance * myMinDistance) { TreeRoot.StatusText = string.Format("Moving closer to {0} before killing {1}", SelectedNpc.SafeName, targetedMob.SafeName); Navigator.MoveTo(SelectedNpc.Location); return(true); } // wait for exploding mob to get within range of shielded mob. if (targetedMob.Location.DistanceSquared(SelectedNpc.Location) > MaxRange * MaxRange) { TreeRoot.StatusText = string.Format( "Waiting for {0} to move withing range of {1}", targetedMob.SafeName, SelectedNpc.SafeName); return(true); } } } } return(false); }
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()) )) )); }