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)) )); }
// 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() { // FollowPath processing... // NB: We had to defer this processing from the constructor, because XElement isn't available // to parse child XML nodes until OnStart() is called. FollowPath = SafePathType.GetOrCreate(Element, "FollowPath", AvoidDistance / 3.0, SafespotLocation); IsAttributeProblem |= FollowPath.IsAttributeProblem; // Let QuestBehaviorBase do basic initializaion 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( string.Format("Using safe spot {0} until '{1}' moves {2:F1} yards away.", SafespotLocation, Utility.GetObjectNameFromId(MobIdToAvoid), AvoidDistance)); // 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) { // Disable any settings that may interfere with the escort -- // When we escort, we don't want to be distracted by other things. // NOTE: these settings are restored to their normal values when the behavior completes // or the bot is stopped. CharacterSettings.Instance.HarvestHerbs = false; CharacterSettings.Instance.HarvestMinerals = false; CharacterSettings.Instance.LootChests = false; CharacterSettings.Instance.NinjaSkin = false; CharacterSettings.Instance.SkinMobs = false; // Disable any settings that may interupt us // NOTE: the ConfigMemento in QuestBehaviorBase restores these settings to their // normal values when OnFinished() is called. LevelBot.BehaviorFlags &= ~(BehaviorFlags.Loot | BehaviorFlags.Pull | BehaviorFlags.Vendor | BehaviorFlags.Roam); State_MainBehavior = StateType_MainBehavior.MovingToSafespot; } }
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()) )) )); }
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); })) )); }