I have added a couple of lines to teleport the bot to Revenant's Toll, which works properly, but I cannot get it to actually run to the Summoning Bell. I've tried to look up how to declare and utilize the Vector3 data for Navigator.MoveTo, but I seem to be missing something crucial. Here is what I have for the move that I am trying to do. [HIDE] Code: var location = new Vector3(14.30233f, 28.99997f, -734.7808f); if (Navigator.NavigationProvider != null) { Navigator.MoveTo(location); } [/HIDE] I have attached my code, which does work, but only if you are currently standing next to the Summoning Bell already. Any insight you have to offer would be greatly appreciated, thank you! newb
Define the navigation provider in your Start block. Is your code a plugin or a botbase? If you're defining NavigationProviders it would be better served as a botbase. The navigation provider is set on the start of the botbase, so OrderBot when started will define a navigation provider, same with Fate Bot, which is why plugins like RePear are able to piggyback off of the BotBase's defined navigation provider. You will need to define your own. Below, the PlayerMover is for movement that doesn't require the navigation server, the GaiaNavigator uses the navigation server for smart movement. Code: Navigator.PlayerMover = new SlideMover(); Navigator.NavigationProvider = new GaiaNavigator();
I am designing it as a plugin, simply because I want it to be able to be used with any version of the basebots. My vision is to have it run alongside of other plugins to automatize the process of leveling our retainers and characters. I added: Code: Navigator.NavigationProvider = new GaiaNavigator(); to my code on Start, and it generated my path here: Code: Generated path to <14.30233, 28.99997, -734.7808> in 00:00:00.1761897 ms but the bot still will not move to that location, is there another call that I need to make besides Code: Navigator.MoveTo(location); to make the bot move to (location)? I'm so close I can taste it! Thank you!
Won't he also need to kill GaiaNav on Stop? https://www.thebuddyforum.com/rebor...3022-bot-base-set-navigator-gaia-startup.html Also I think kaga's point is you don't want to start multiple sessions of GaiaNav. If the Botbase already has GaiaNav running you won't want to also initialize it in your plugin (to my knowledge). You can probably get away with checking for BotManager.Current.IsAutonomous but I'll leave it up to someone more knowledgeable to reply.
Yes sorry, I didn't mention it, you would want this in your Stop code: Code: (Navigator.NavigationProvider as GaiaNavigator).Dispose(); Also true, you don't want multiple GaiaNavigators running, the nav server won't like you much. You could probably check if ff14bot.Navigation.Navigator.NavigationProvider is null or ff14bot.Navigation.NullProvider and re-set it to GaiaNavigator as well. The biggest issue with this being a plugin in my opinion is just that the plugin will need to know when the bot is not doing anything important so that it doesn't interrupt something like a FATE or a gather node or any other host of things it could be doing. In addition to that, it needs to port you to a summoning bell (not everyone will have every aetheryte so you might need a couple different locations with bells), do its stuff, and then return you back to the map you were on so the profile can take over again. Take the following example: You are mining in Upper La Noscea on the west side of the map. SlaveBot teleports you to Limsa Lominsa to check your summoning bell. It then teleports you back to Camp Bronze Lake in Upper La Noscea so your bot can resume mining, but your bot can't resume mining because it can't get back to the western side of the map because there's a lake in the way. Another example, what if you're questing on the Isles of Umbra and your bot teleports you away, your bot won't know how to get back there. You get the idea.
Okay! Progress! I now have movement with the following code, BUT, it's dumb movement. As in, run into walls dumb. It also does not stop at the vector3 coordinates I set up, instead, it tries to continue to try and run through the wall back behind the Bell. How do I go about getting it to move around objects and actually stopping at the bell/my specified coordinates? [HIDE] Code: using System;using System.Threading; using System.Threading.Tasks; using Buddy.Coroutines; using Clio.Utilities; using ff14bot; using ff14bot.Helpers; using ff14bot.Interfaces; using ff14bot.Managers; using ff14bot.Navigation; using ff14bot.Objects; using ff14bot.RemoteWindows; namespace Slavebot9001 { public class Slavebot9001 : IBotPlugin { public string Author { get { return "newb23"; } } public string Description { get { return "Retainer Auto-Quick Explorer"; } } public Version Version { get { return new Version(1, 2, 0); } } public string Name { get { return "Slavebot9001"; } } public string ButtonText { get { return "No Settings"; } } public bool WantButton { get { return true; } } public bool Equals(IBotPlugin other) { throw new NotImplementedException(); } public static IntPtr GameHandle = IntPtr.Zero; private GameObject _summonbell; public int LoopCount; public int RetRetn; public void OnInitialize() { } public void OnEnabled() { //Navigator.NavigationProvider = new GaiaNavigator(); //Navigator.PlayerMover = new SlideMover(); GamelogManager.MessageRecevied += MessageReceived; } private void MessageReceived(object sender, ChatEventArgs e) { if (e.ChatLogEntry.Contents.Contains("has completed a venture!") && RetRetn == 0) { RetRetn = 1; Logging.Write("Slavebot9001: Your retainer is back!"); if (Core.Player.IsMounted && WorldManager.ZoneId != 156) { Actionmanager.Dismount(); Thread.Sleep(1000); } if (WorldManager.ZoneId != 156) { Logging.Write("Slavebot9001: Going to the Summoning Bell now!"); WorldManager.TeleportById(24); Thread.Sleep(15000); } var location = new Vector3(14.30233f, 28.99997f, -734.7808f); Navigator.PlayerMover.MoveTowards(location); _coroutine = null; } } private Coroutine _coroutine; public void OnPulse() { if (_coroutine == null || _coroutine.IsFinished) { _coroutine = new Coroutine(() => MainLoop()); } _coroutine.Resume(); } internal async Task MainLoop() { if (WorldManager.ZoneId != 156) { Logging.Write("Slavebot9001: Going to the Summoning Bell now!"); WorldManager.TeleportById(24); await Coroutine.Sleep(15000); var location = new Vector3(14.30233f, 28.99997f, -734.7808f); Navigator.PlayerMover.MoveTowards(location); } _summonbell = GameObjectManager.GetObjectByObjectId(4627757); while (LoopCount < 4) { //Open retainer list var location = new Vector3(14.30233f, 28.99997f, -734.7808f); Navigator.PlayerMover.MoveTowards(location); Logging.Write("Slavebot9001: Using Summoning Bell."); await Coroutine.Sleep(2000); _summonbell.Interact(); await Coroutine.Sleep(2000); //Select A Retainer Logging.Write("Slavebot9001: Searching for Complete Ventures."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); if (SelectString.ClickLineContains("Venture complete)")) { Logging.Write("Slavebot9001: Selecting First Retainer with a Complete Venture."); SelectString.ClickLineContains("Venture complete)"); await Coroutine.Sleep(2000); } else { Logging.Write("Slavebot9001: No Ventures available, quiting Retainer Menu."); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); Logging.Write("Slavebot9001: Sleeping for 62 Minutes."); await Coroutine.Sleep(3720000); LoopCount = 0; } //Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //View Venture Report Logging.Write("Slavebot9001: Selecting Venture Report."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); SelectString.ClickLineContains("View venture report"); await Coroutine.Sleep(2000); //Venture Report Window Reassign/Confirm Logging.Write("Slavebot9001: Reassigning Venture."); while (!RetainerTaskResult.IsOpen) await Coroutine.Sleep(2000); RetainerTaskResult.Reassign(); await Coroutine.Sleep(2000); //Venture Confirm Window Logging.Write("Slavebot9001: Confirming Reassignment."); while (!RetainerTaskAsk.IsOpen) await Coroutine.Sleep(2000); RetainerTaskAsk.Confirm(); await Coroutine.Sleep(2000); //Wait/Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //Quit Retainer Dialog Logging.Write("Slavebot9001: Quiting Selected Retainer."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); //Wait/Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //None of the Retainers are back/ready Logging.Write("Slavebot9001: Quiting Retainer Menu."); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); Logging.Write("Slavebot9001: Returning to Beginning."); await Coroutine.Sleep(2000); LoopCount++; } Logging.Write("Slavebot9001: All avilable ventures ordered! Sleeping for 62 Minutes."); LoopCount = 0; RetRetn = 0; await Coroutine.Sleep(3720000); } private void KillCoroutine(ref Coroutine coroutine) { if (coroutine == null) return; coroutine.Dispose(); } public void OnShutdown() { GamelogManager.MessageRecevied -= MessageReceived; KillCoroutine(ref _coroutine); _coroutine = null; } public void OnDisabled() { GamelogManager.MessageRecevied -= MessageReceived; KillCoroutine(ref _coroutine); _coroutine = null; } public void OnButtonPress() { } } } [/HIDE]
I do indeed. Once I get this hashed out as a plugin, (So close! Navigation! Curse you!) how would I go about setting it up as a bot base? And moreso than that, how would I go about having other people be able to use it in conjunction with FATE Bot or Orderbot? Ultimately, that is what I want it to do. I was inspired from the way that Neverdyne's Agil is able to work, and I wanted to try and mimic that action (with a different job - Retainer vs Repair).
A BotBase cannot work with another BotBase. If you want to use it in conjunction with a BotBase it should be a plugin. Just keep in mind the things to be careful of and what your plugin will need to be responsible for.
I understand, and will be continuing to work on it for as long as I can make improvements to it. I would very much like for it to be a Go-To plugin for management, and even if I can't get it to do what Neverdyne's do, I hope I can get it to do what I want it to do. That being said, is PlayerMover ONLY through SlideMover, meaning I cannot have "intelligent" movement? I ask because, in a couple posts up I have it laid out so that I did not declare my own Code: [COLOR=#333333]Navigator.PlayerMover = new SlideMover(); [/COLOR]or [COLOR=#333333]Navigator.NavigationProvider = new GaiaNavigator();[/COLOR] but instead left them commented out. But the only way I can actually get the bot to even begin a move, is to use Code: Navigator.PlayerMover.MoveTowards(location); Is there something else that I am missing?
Check if NavigationProvider is null, if it is set your own, if it isn't don't set it. Then you can have smart movement, no? I don't see why that wouldn't work, but most people would be using your plugin with Order Bot or Fate Bot which both define NavigationProvider. How are you testing your plugin that you don't have movement?
I should have mentioned, I am testing this with FATE bot, and I do have movement with the code I'll post below in this post. It just doesn't stop moving at my coords, and doesn't intelli-move. Clarification: I have not set my own NavigationProvider, I am using FATE bot to test, and the last paragraph is what issues I am having. Code: using System;using System.Threading; using System.Threading.Tasks; using Buddy.Coroutines; using Clio.Utilities; using ff14bot; using ff14bot.Helpers; using ff14bot.Interfaces; using ff14bot.Managers; using ff14bot.Navigation; using ff14bot.Objects; using ff14bot.RemoteWindows; namespace Slavebot9001 { public class Slavebot9001 : IBotPlugin { public string Author { get { return "newb23"; } } public string Description { get { return "Retainer Auto-Quick Explorer"; } } public Version Version { get { return new Version(1, 2, 0); } } public string Name { get { return "Slavebot9001"; } } public string ButtonText { get { return "No Settings"; } } public bool WantButton { get { return true; } } public bool Equals(IBotPlugin other) { throw new NotImplementedException(); } public static IntPtr GameHandle = IntPtr.Zero; private GameObject _summonbell; public int LoopCount; public int RetRetn; public void OnInitialize() { } public void OnEnabled() { //Navigator.NavigationProvider = new GaiaNavigator(); //Navigator.PlayerMover = new SlideMover(); GamelogManager.MessageRecevied += MessageReceived; } private void MessageReceived(object sender, ChatEventArgs e) { if (e.ChatLogEntry.Contents.Contains("has completed a venture!") && RetRetn == 0) { RetRetn = 1; Logging.Write("Slavebot9001: Your retainer is back!"); if (Core.Player.IsMounted && WorldManager.ZoneId != 156) { Actionmanager.Dismount(); Thread.Sleep(1000); } if (WorldManager.ZoneId != 156) { Logging.Write("Slavebot9001: Going to the Summoning Bell now!"); WorldManager.TeleportById(24); Thread.Sleep(15000); } var location = new Vector3(12.30275f, 28.99997f, -734.2261f); Navigator.PlayerMover.MoveTowards(location); _coroutine = null; } } private Coroutine _coroutine; public void OnPulse() { if (_coroutine == null || _coroutine.IsFinished) { _coroutine = new Coroutine(() => MainLoop()); } _coroutine.Resume(); } internal async Task MainLoop() { if (WorldManager.ZoneId != 156) { Logging.Write("Slavebot9001: Going to the Summoning Bell now!"); WorldManager.TeleportById(24); await Coroutine.Sleep(15000); var location = new Vector3(12.30275f, 28.99997f, -734.2261f); Navigator.PlayerMover.MoveTowards(location); } _summonbell = GameObjectManager.GetObjectByObjectId(4627757); while (LoopCount < 4) { //Open retainer list var location = new Vector3(12.30275f, 28.99997f, -734.2261f); Navigator.PlayerMover.MoveTowards(location); Logging.Write("Slavebot9001: Using Summoning Bell."); await Coroutine.Sleep(2000); _summonbell.Interact(); await Coroutine.Sleep(2000); //Select A Retainer Logging.Write("Slavebot9001: Searching for Complete Ventures."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); if (SelectString.ClickLineContains("Venture complete)")) { Logging.Write("Slavebot9001: Selecting First Retainer with a Complete Venture."); SelectString.ClickLineContains("Venture complete)"); await Coroutine.Sleep(2000); } else { Logging.Write("Slavebot9001: No Ventures available, quiting Retainer Menu."); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); Logging.Write("Slavebot9001: Sleeping for 62 Minutes."); await Coroutine.Sleep(3720000); LoopCount = 0; } //Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //View Venture Report Logging.Write("Slavebot9001: Selecting Venture Report."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); SelectString.ClickLineContains("View venture report"); await Coroutine.Sleep(2000); //Venture Report Window Reassign/Confirm Logging.Write("Slavebot9001: Reassigning Venture."); while (!RetainerTaskResult.IsOpen) await Coroutine.Sleep(2000); RetainerTaskResult.Reassign(); await Coroutine.Sleep(2000); //Venture Confirm Window Logging.Write("Slavebot9001: Confirming Reassignment."); while (!RetainerTaskAsk.IsOpen) await Coroutine.Sleep(2000); RetainerTaskAsk.Confirm(); await Coroutine.Sleep(2000); //Wait/Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //Quit Retainer Dialog Logging.Write("Slavebot9001: Quiting Selected Retainer."); while (!SelectString.IsOpen) await Coroutine.Sleep(2000); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); //Wait/Skip dialog while (!Talk.DialogOpen) await Coroutine.Sleep(2000); Talk.Next(); await Coroutine.Sleep(2000); //None of the Retainers are back/ready Logging.Write("Slavebot9001: Quiting Retainer Menu."); SelectString.ClickLineContains("Quit"); await Coroutine.Sleep(2000); Logging.Write("Slavebot9001: Returning to Beginning."); await Coroutine.Sleep(2000); LoopCount++; } Logging.Write("Slavebot9001: All avilable ventures ordered! Sleeping for 62 Minutes."); LoopCount = 0; RetRetn = 0; await Coroutine.Sleep(3720000); } private void KillCoroutine(ref Coroutine coroutine) { if (coroutine == null) return; coroutine.Dispose(); } public void OnShutdown() { GamelogManager.MessageRecevied -= MessageReceived; KillCoroutine(ref _coroutine); _coroutine = null; } public void OnDisabled() { GamelogManager.MessageRecevied -= MessageReceived; KillCoroutine(ref _coroutine); _coroutine = null; } public void OnButtonPress() { } } } Also, a log.
Look at how other plugins handle movement. Look at RePear or Agil or something and look at the movement code.
I took a gander at the other plugins, got lost, went searching through the forums again, and came across one phrase buried deeeeep that mentioned something about OnPulse(). "Huh." I thought to myself, "well screw it, let's try to just throw my Navigator.MoveTo(location); into there." Sure enough, works like a charm! I released version 1.3.0 of Slavebot 9001 just a little while ago featuring automatic movement to the Bell, so, thank you for your help and encouragement!
False, playermover is separate from the navigation provider. Both a playermover and a navigaitonprovider are required. I was considering writing a CTM based playermover but as its not normally available i decided against it.
Oh I had no idea, good to know. I guess I just got lucky with defining both and not running into any problems.
Well... have no idea how I was able to get it to work then, as I do not have a playermover defined in my code at all.. Hmm. A quandary to be sure. And one that will likely break as I try to call on it for my return-to-previous-duty functions. Ah well, c'est la vie, I'll figure it out, and if not, someone can help me. Ya'll are wonderful about that. [h=3][/h]
This is how movement is handled with the new coroutine version of Agil. You could copy it exactly if you want, I don't mind. Just be warned the way I'm doing it might be the worst way possible for some reason that escapes me and could explode your computer, ban you from the internetz for life, and burn your house down. The file you would need to include in your project is this one: View attachment MovementActions.cs Just change the namespace to something else so there's no conflicts with Agil. Then what you do is use it inside coroutines like this: Code: public static async Task<bool> MenderRepair(Func<Mender> menderRetriever) { Logger.Log("Starting mender repair."); if (CraftingLog.IsOpen) { await DialogActions.CloseCraftingLog(); } var mender = menderRetriever.Invoke(); if (mender == null) { return false; } var initialLocation = Core.Me.Location; await MovementActions.MoveTo(mender.Location); await DialogActions.Target(mender.NpcId); await DialogActions.InteractOpenIconString(); await SetRepairIconString(); await RepairAll(); await DialogActions.SelectYesNo(); await CloseRepair(); await MovementActions.MoveTo(initialLocation); Logger.Log("Finished mender repair."); return true; } You can see how the calls to "MovementActions.MoveTo(vector3)" are weaved in between other actions. I'm guessing you're looking into doing something like that. When moving with that code, it currently doesn't mount up, haven't figured how to check if the player can mount anything or not yet, last I checked the CanMount property somewhere returns a numeric value which I'm not sure what it means, so never added it. It will, however, dismount once getting near the location.
Thank you very, very much for your instructions and permission to use this. I will attempt to get it implemented over the course of the next few days!