• Visit Rebornbuddy
  • Utilizing the Navmesh System?

    Discussion in 'Community Developer Forum' started by kagamihiiragi17, Jun 30, 2014.

    1. kagamihiiragi17

      kagamihiiragi17 Community Developer

      Joined:
      Jun 24, 2014
      Messages:
      873
      Likes Received:
      25
      Trophy Points:
      0
      What's the best way to use the navmesh system that the Fate Bot uses? I can't find great documentation for it and it would be lovely in implementing repairs into Magitek. If anyone has some sample code I could look at or something that would be lovely. Thanks!
       
    2. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      Navigation is a bit tricky since we use a remote server for navmeshs. There are three main functions that you'd be interested in. CanFullyNavigateTo,MoveToPointWithin,MoveTo

      To query if you are able to reach a location:
      This function is synchronous and canlockup the client for a short period so its best to cache the results or call it only once in a while.
      Code:
                  var nav = (Navigator.NavigationProvider as GaiaNavigator);
                  var fates = FateManager.ActiveFates.Where(IsValid);
      
      
                  var fateDatas = fates as FateData[] ?? fates.ToArray();
                  var navReq = fateDatas.Select(r => new CanFullyNavigateTarget { Id = r.Id, Position = r.Location });
                  if (!navReq.Any())
                  {
                      Logging.Write("No fates we can tackle currently.");
                      return RunStatus.Failure;
                  }
                  var paths = nav.CanFullyNavigateTo(navReq);
                  if (paths == null)
                  {
                      Logging.WriteDiagnostic("Something strange happened, null path returned.");
                      return RunStatus.Failure;
                  }
      

      MoveToPointWithin,MoveTo are asynchronous and will not lockup, to be used you basically need to keep calling them with the same parameters so that they don't request a new path.

      Movetopointwithin basicly picks a random spot within X yards of the provided spot that it can navigate to.:
      Code:
      Navigator.MoveToPointWithin(Poi.Current.Location, 15, "Moving to rest location")
      
      For moveto we have nice wrappers that you should use inside commonbehaviors:

      Code:
      CommonBehaviors.CreateMountBehavior()
      
      Code:
      CommonBehaviors.MoveAndStop(ret => Location, r => 4f, true, "Moving to a location")
      

      I'd be more concerned about getting the windows interaction working properly first. Once you have that done I can help you setup a POI chain that will integrate with the botbase.
       
    3. kagamihiiragi17

      kagamihiiragi17 Community Developer

      Joined:
      Jun 24, 2014
      Messages:
      873
      Likes Received:
      25
      Trophy Points:
      0
      I have the window interaction done, for now it uses simple keyboard commands to navigate through the window (sending the client NumPad0 activates the cursor, and then you can navigate windows using NumPad8, NumPad2, NumPad6 and NumPad4) which works but in the future as window interaction is added to RebornBuddy we can clean up the code. Are there any downsides to navigating the window like that? The only downside I can think of is if someone has those keybindings changed, but we can add variables to the settings for people to input what they have their keybindings as.

      The code looks like the following:

      Code:
              [DllImport("user32.dll")]
              public static extern IntPtr PostMessage(IntPtr hWnd, uint Msg, IntPtr wParam, IntPtr lParam);
      
              public static void Repair()
              {
                  // Ideally this will contain databases for each zone including all repairing NPCs (their names, and locations)
                  // and will be able to navigate to the closest one, repair, then go back to the inital location
      
                  Vector3 InitialLocation;
                  InitialLocation = Core.Player.Location;
      
                  const uint WM_KEYDOWN = 0x100;
                  const uint WM_KEYUP = 0x0101;
      
                  // Add code to target NPC and then
                  // move player to the NPC as well
                  
      
                  // From here on the code should be fine
                  // to complete the repair
                  Core.Player.CurrentTarget.Interact();
      
                  Thread.Sleep(1000);  // Wait for the window to open
      
                  IntPtr hWnd;
                  string processName = "ffxiv";
                  Process[] processList = Process.GetProcesses();
      
      foreach (Process P in processList)
                  {
                      if (P.ProcessName.Equals(processName))
                      {
                          // The following code navigates the window and completes the repair, and then closes the window
                          IntPtr edit = P.MainWindowHandle;
                          if (Core.Target.Name == "Merchant & Mender")
                          {
                              // Merchant & Menders have an additional window before the repair window to navigate
                              PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              Thread.Sleep(500);
                              PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad8), IntPtr.Zero);
                              PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad8), IntPtr.Zero);
                              Thread.Sleep(500);
                              PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad8), IntPtr.Zero);
                              PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad8), IntPtr.Zero);
                              Thread.Sleep(500);
                              PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              Thread.Sleep(1000);
                          }
                          else
                          {
                              PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                              Thread.Sleep(500);
                          }
                          PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad6), IntPtr.Zero);
                          PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad6), IntPtr.Zero);
                          Thread.Sleep(500);
                          PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                          PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                          Thread.Sleep(500);
                          PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad4), IntPtr.Zero);
                          PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad4), IntPtr.Zero);
                          Thread.Sleep(500);
                          PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                          PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.NumPad0), IntPtr.Zero);
                          Thread.Sleep(500);
                          PostMessage(edit, WM_KEYDOWN, (IntPtr)(Keys.Escape), IntPtr.Zero);
                          PostMessage(edit, WM_KEYUP, (IntPtr)(Keys.Escape), IntPtr.Zero);
                      }
                  }
      
                  Logging.Write("[Magitek] Repaired!");
      
                  // Add logic to get back to the initial location
              }
       
      Last edited: Jul 2, 2014
    4. kagamihiiragi17

      kagamihiiragi17 Community Developer

      Joined:
      Jun 24, 2014
      Messages:
      873
      Likes Received:
      25
      Trophy Points:
      0
      Perhaps I'm showing my inexperience here, but I never did really get this working properly. Is there a good way to implement navigation without using TreeSharp? I'm still really new to TreeSharp so all my code for repairing is written in C#. Right now I have it set up to insert an NPC Name and location, and then ideally the bot will move to that location, interact with the NPC, do the repairs, and then move back to the initial location and resume the profile. I'd love to get this up and working but I still don't quite understand moving long distances. (moving in a straight line to a nearby point is easy, just a function call. If there was a nice function to move long distances on the same map that would be amazing! *wink*)
       
    5. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      namespace ff14bot.Behavior
      {
      public static class CommonBehaviors
      {
       
    6. kagamihiiragi17

      kagamihiiragi17 Community Developer

      Joined:
      Jun 24, 2014
      Messages:
      873
      Likes Received:
      25
      Trophy Points:
      0
      Sorry, I meant the navmesh system. CommonBehaviors doesn't use navmesh, right? Or did that change?
       
    7. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      It depends on what botbase your using. But they were designed for orderbot/fatebot.
       
    8. kagamihiiragi17

      kagamihiiragi17 Community Developer

      Joined:
      Jun 24, 2014
      Messages:
      873
      Likes Received:
      25
      Trophy Points:
      0
      What's the best way to repeatedly call the MoveToPointWithin function without TreeSharp? Putting it in a while loop freezes the game, and I haven't had much luck using Timer.Elapsed, putting it in a new thread, using tasks, or much else either. Sorry for the repeated bother, C# is still somewhat new to me.
       
    9. mastahg

      mastahg Administrator Staff Member

      Joined:
      Feb 27, 2011
      Messages:
      5,229
      Likes Received:
      364
      Trophy Points:
      83
      All of those things no.
       

    Share This Page