1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Tutorial A simple TaskBot

Discussion in 'Tutorials & Resources' started by qverkk, Sep 10, 2017.

?

Was this guide usefull?

  1. Yes

    11 vote(s)
    78.6%
  2. No

    0 vote(s)
    0.0%
  3. Kind of, still trying to understand things

    3 vote(s)
    21.4%
  1. qverkk

    Joined:
    Sep 22, 2015
    Messages:
    1,603
    Likes Received:
    381
    A basic TaskBot tutorial

    Steps you have to do before getting into the code side:
    1. Make sure you've properly set your IDE. If not, please visit other tutorials for guidance. (Here's one for IntellIj: CLICK
    2. If you want to publish bots to the botstore, you also might take a look at THIS
    3. Also a good thing is to learn a bit about java naming conventions HERE
    What's a TaskBot framework

    (To be honest, I don't know the oryginal terminolog, but i'll try to explain it)
    Basicly, it'll loop through your tasks, from left to right. That's why you need to keep an order within the tasks. You an also add tasks within tasks, to separate some code, to keep clear validations and prevent repeating methods in validate. Hope you'll find some intresting stuff in this guide.

    First steps

    Before we get into the code, we need to create our main class.
    This can be done by: right clicking on our desired package -> selecting new -> clicking Java Class
    Type our desired name for the main class of our bot and press OK.
    [​IMG]

    In order for this class to be an TaskBot, we need to extend it to TaskBot:
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot;
    2.  
    3. import com.runemate.game.api.script.framework.task.TaskBot;
    4.  
    5. public class TutorialTaskBot extends TaskBot {
    6.  
    7. }
    8.  

    After doing so, we need to implement an onStart method provided by RuneMate API.

    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot;
    2.  
    3. import com.runemate.game.api.script.framework.task.TaskBot;
    4.  
    5. public class TutorialTaskBot extends TaskBot {
    6.     @Override
    7.     public void onStart(String... strings) {
    8.         super.onStart(strings);
    9.     }
    10. }
    11.  

    At this moment, we can create tasks for the bot. But we need to have in mind that we need to keep an order in them, so the bot won't go crazy doing them.

    Simple example of keeping order in tasks:
    1. If our inventory is full, and we're not close enough to a bank, then walk to it.
    2. If our inventory is full and we're close enough to a bank, start banking.
    3. If our inventory isn't full and we're not close enough to (for example flax), walk to flax area.
    4. If our inventory isn't full and there's flax within the area, start picking.

    Alright, so now we know how to properly set an order in our bot, so let's get into code.
    Remember how we did that main class of our bot? We need to repeat the process for each new task.
    Within the class, we need to extend it to a Task and implement validate and execute (it can be done easy, just click on task, and press ALT+ENTER, and then select Implement methods and press OK)

    So now our code within this class looks like this:​
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot.tasks;
    2.  
    3. import com.runemate.game.api.script.framework.task.Task;
    4.  
    5. public class TravelToBank extends Task {
    6.  
    7.     @Override
    8.     public boolean validate() {
    9.         return false;
    10.     }
    11.  
    12.     @Override
    13.     public void execute() {
    14.  
    15.     }
    16. }
    17.  
    Now we need to code the logic into this class. So we'll check if our inventory is full and we're close enough to a bank.​
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot.tasks;
    2.  
    3. import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
    4. import com.runemate.game.api.hybrid.region.Banks;
    5. import com.runemate.game.api.script.framework.task.Task;
    6.  
    7. public class TravelToBank extends Task {
    8.  
    9.     @Override
    10.     public boolean validate() {
    11.         return Inventory.isFull() && Banks.newQuery().results().isEmpty();
    12.     }
    13.  
    14.     @Override
    15.     public void execute() {
    16.  
    17.     }
    18. }
    19.  
    This code will check for our inventory and for any banks within our region area.

    If we want to check for a bank within a certain area, we can just add a ".within()" filter to our query:

    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot.tasks;
    2.  
    3. import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
    4. import com.runemate.game.api.hybrid.location.Area;
    5. import com.runemate.game.api.hybrid.location.Coordinate;
    6. import com.runemate.game.api.hybrid.region.Banks;
    7. import com.runemate.game.api.script.framework.task.Task;
    8.  
    9. public class TravelToBank extends Task {
    10.  
    11.     private final Area.Circular exampleArea = new Area.Circular(new Coordinate(1,1,1), 15);
    12.  
    13.     @Override
    14.     public boolean validate() {
    15.         return Inventory.isFull() && Banks.newQuery().within(exampleArea).results().isEmpty();
    16.     }
    17.  
    18.     @Override
    19.     public void execute() {
    20.  
    21.     }
    22. }

    After doing so, we'll just walk to the area or a coordinate (For this, we'll use WebPath system):​
    Code (Text):
    1. @Override
    2.     public void execute() {
    3.         Path path = Traversal.getDefaultWeb().getPathBuilder().buildTo(exampleArea.getRandomCoordinate());
    4.         if(path != null) {
    5.             path.step();
    6.         }
    7.     }
    A similiar code can be done for traveling back to flax area, we just need to check if our Inventory isn't full and Player isn't within our flax area:
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot.tasks;
    2.  
    3. import com.runemate.game.api.hybrid.entities.Player;
    4. import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
    5. import com.runemate.game.api.hybrid.location.Area;
    6. import com.runemate.game.api.hybrid.location.Coordinate;
    7. import com.runemate.game.api.hybrid.location.navigation.Path;
    8. import com.runemate.game.api.hybrid.location.navigation.Traversal;
    9. import com.runemate.game.api.hybrid.region.Players;
    10. import com.runemate.game.api.script.framework.task.Task;
    11.  
    12. public class TravelToFlax extends Task {
    13.  
    14.     private final Area.Circular flaxArea = new Area.Circular(new Coordinate(1,1,1), 15);
    15.  
    16.     @Override
    17.     public boolean validate() {
    18.         final Player me = Players.getLocal();
    19.         return me != null && !Inventory.isFull() && !flaxArea.contains(me);
    20.     }
    21.  
    22.     @Override
    23.     public void execute() {
    24.         Path path = Traversal.getDefaultWeb().getPathBuilder().buildTo(flaxArea.getRandomCoordinate());
    25.         if(path != null) {
    26.             path.step();
    27.         }
    28.     }
    29. }
    30.  
    Now we'll try to pick flax. For this instance we'll need to check if our player is still within the area, and if flax within this area exists, a good practice for this is to cache our GameObject/GroundItem so later on in execute we can interact with our previous checked object.
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot.tasks;
    2.  
    3. import com.runemate.game.api.hybrid.entities.GameObject;
    4. import com.runemate.game.api.hybrid.entities.Player;
    5. import com.runemate.game.api.hybrid.local.Camera;
    6. import com.runemate.game.api.hybrid.location.Area;
    7. import com.runemate.game.api.hybrid.location.Coordinate;
    8. import com.runemate.game.api.hybrid.region.GameObjects;
    9. import com.runemate.game.api.hybrid.region.Players;
    10. import com.runemate.game.api.script.Execution;
    11. import com.runemate.game.api.script.framework.task.Task;
    12.  
    13. public class PickFlax extends Task {
    14.  
    15.     private final Area.Circular flaxArea = new Area.Circular(new Coordinate(1,1,1), 15);
    16.     private GameObject flax;
    17.  
    18.     @Override
    19.     public boolean validate() {
    20.         final Player me = Players.getLocal();
    21.         flax = GameObjects.newQuery().names("Flax").actions("Pick").within(flaxArea).results().nearest();
    22.         return me != null && flax != null;
    23.     }
    24.  
    25.     @Override
    26.     public void execute() {
    27.         //we don't want to interact with the flax, if it's not visible, so let's check
    28.         //if it's visible let's interact with it, if not then just turn the camera
    29.         if(flax.isVisible()) {
    30.             if(flax.interact("Pick")) {
    31.                 //After interacting with our flax, we can add a check if it's still valid
    32.                 //This isn't required, you can check for player animation also
    33.                 //If you'd use player animation, you'd check if it went back to idle after picking the flax
    34.                 Execution.delayWhile(() -> flax.isValid(), 3000, 4000);
    35.             }
    36.         } else {
    37.             Camera.turnTo(flax);
    38.         }
    39.     }
    40. }
    41.  


    Banking class is for you guys to practice with. After you write the class, let's start implementing these tasks in order we described above, into our main TaskBot class.
    You can simply add them in your onStart method by doing : add(new Task(), new Task(), ...)
    Code (Text):
    1. package com.qverkk.bots.tutorial_task_bot;
    2.  
    3. import com.qverkk.bots.tutorial_task_bot.tasks.PickFlax;
    4. import com.qverkk.bots.tutorial_task_bot.tasks.TravelToBank;
    5. import com.qverkk.bots.tutorial_task_bot.tasks.TravelToFlax;
    6. import com.runemate.game.api.script.framework.task.TaskBot;
    7.  
    8. public class TutorialTaskBot extends TaskBot {
    9.     @Override
    10.     public void onStart(String... strings) {
    11.         super.onStart(strings);
    12.         add(new TravelToBank(), new TravelToFlax(), new PickFlax());
    13.     }
    14. }
    15.  
    Banking class is for you guys so you can try to code it by yourself, and implement it within your main class.


    For experimental purposes you can try:
    1. Implementing Player Sense (Guide by @Savior : HERE )
    2. Implementing an User Interface (Guide by @SlashnHax : HERE )
    3. Learning about Varbits and Varps, for in game data, like if Overload is active (Guide by @Snufalufugus : HERE)
    4. You might want to get Open Interface Explorer, to view your interfaces with ease (Made by @SlashnHax and edited by @Party : HERE )
    5. If you want to add tasks into your bot based on what your user selects in your UI, you may find this example code usefull:
    Code (Text):
    1. @Override
    2.     public void initialize(URL location, ResourceBundle resources) {
    3.         setVisible(true);
    4.         startBtn.setOnAction(event -> {
    5.             if(isRenewalsSelected) {
    6.                bot.add(new UseRenewals());
    7.             }
    8.             if(isOverloadSelected) {
    9.                bot.add(new UseOverloads());
    10.             }
    11.         );
    12.     }


    Also you might have a closer look at:
    1. More in depth Query Builders by @Guru HERE
    2. A video explaining some functions of RuneMate API (Guide by @Eagles13 : HERE)



    It's a nooby guide, but at least some people may learn from this ;)
    If you've got any questions, feel free to send me a DM or post in this thread.
    Also you can join RuneMate's slack channel to find more devs willing to help if you're stuck.​
     
    #1 qverkk, Sep 10, 2017
    Last edited: Sep 10, 2017
  2. Daniel

    Joined:
    Jun 24, 2014
    Messages:
    172
    Likes Received:
    29
    Nice tutorial although the order of the tasks should not matter for any reason if all the validate() methods are implemented correctly. While looping through the tasks it should only execute once no matter at what point the bot is because a validate() has returned true.

    In your example you've 3 variables that come into play to execute the bot, and you contemplated all the possible 8 (2^3) cases they can possibly have:
    Inventory not full, flax not visible
    Inventory not full, flax visible
    Inventory full, bank not visible
    Inventory full, bank visible


    I said 8 cases but I only listed 4, that's because, for example:
    Inventory full, bank not visible, flax visible
    Is exactly the same as:
    Inventory full, bank not visible, flax not visible
    While the inventory is full, flax being visible or not doesn't has any effect. The same thing applies for the others.

    Thanks to this (that you've contemplated all the possible cases), independently of the order you add the tasks, the bot will work correctly.
     
  3. qverkk

    Joined:
    Sep 22, 2015
    Messages:
    1,603
    Likes Received:
    381
    The order matters, example: for a fighter, you want to have an Eating task before anything else, to ensure that you won't die fighting, and it'll be always the first thing the loop starts with. And within the tasks i've wrote you can check for visible or not in the execute, the most important was just checking for the inventory and areas, aswell as for checking for flax. Every additional feature for turning the camera or not can be done in execute, no need to add a separate task just for turning the camera. You can also make tasks within tasks, so your essential task validations could just be Inventory.isFull() and !Inventory.isFull() and within them you could add additional tasks which would execute if the validation was correct etc
     
  4. Daniel

    Joined:
    Jun 24, 2014
    Messages:
    172
    Likes Received:
    29
    With visible/not visible I meant being in the area or not, because for me as a player I don't wait to be, for example, in the area of the draynor willows fire example, but instead if I can see them wherever I am, I'll click them. But yes, that's what I wanted to say, in area or not.

    Yes you're totally correct, that would be adding priorities to the bot, however it might not apply for all, just like the example you used.

    Either way, it was a nice read and hopefully someday RuneMate will work on my Mac and I'll be able to write some bots.
     
    qverkk likes this.
  5. HAckley

    Joined:
    Mar 11, 2018
    Messages:
    19
    Likes Received:
    4
    I know this post is a little older, but I just found it. Thanks so much for this, very well explained that even I could follow it :p

    edit: also thanks for the extra guide links at the bottom!
     
    Wet Rag and qverkk like this.
  6. Amaia

    Joined:
    Aug 11, 2018
    Messages:
    6
    Likes Received:
    0
    How do I make the bot move into the next task...? I am trying to learn and I thought my first good practise would be simply creating a man killing bot in edge.. My first task is to check that in my edge and I made it print to console that if its true, to say "We are in Edgeville" my next task is to check I have the equipment on that I need (Pre-determined equipment because im still a noob) I believe I added it, so all my bot does it spam "We are in edgeville". I have text for the next task to say "We are wearing the correct items" but it seems like it never gets called.. Maybe I am messing something up.. I coded everything under validate, maybe I should move it to execute and make validate do something else? idk

    Any inside would be great, ive read the the post like 1000 times and I cannot see where you tell the bot to call the next task...
     
  7. qverkk

    Joined:
    Sep 22, 2015
    Messages:
    1,603
    Likes Received:
    381
    The tasks are executed by the TaskBot framework. Here is a list of added tasks:
    Code (Text):
    1.         add(new TravelToBank(), new TravelToFlax(), new PickFlax());
    So in this scenario, it would execute from left to right. If the task validation fails, it picks the next one and validates it, if it succeeds then the tasks are validate from the beginning. In your scenario i see that you could have a few tasks:
    - Edgeville traversal - the validation would be: if we're not in edgeville, traverse there
    - Equipment loadout - the validation would be: if we don't have the equipment , get it from bank and wear it (this will only execute, once you're in edgeville cause of the task above)
    - Kill npc - the validation would be: if we don't have a target, attack an npc (this will only execute once you have the equipment on you cause of the task above)

    And you'd load these tasks in onStart like so:
    Code (Text):
    1.         add(new EdgevilleTraversal(), new EquipmentLoadout(), new NpcAttack());
     
  8. Bing Bong

    Bing Bong Bot Author

    Joined:
    Jan 29, 2016
    Messages:
    1,082
    Likes Received:
    103
    This is a thread back from 2017 and the comments are from 2021 at the latest..
     
    JaredCH likes this.
  9. qverkk

    Joined:
    Sep 22, 2015
    Messages:
    1,603
    Likes Received:
    381
    Yup no shit dude
     
    JaredCH likes this.
  10. Wet Rag

    Wet Rag easily triggered ✌

    Joined:
    Dec 31, 2015
    Messages:
    4,454
    Likes Received:
    1,694
    sorry bro forgive BB hes new here and british which is an awful curse
     
    JaredCH, Bing Bong and qverkk like this.

Share This Page

Loading...