Welcome!

By registering with us, you'll be able to discuss, share and private message with other members of our community.

Sign up now!

Tutorial A simple TaskBot

Was this guide usefull?

  • Yes

    Votes: 11 78.6%
  • No

    Votes: 0 0.0%
  • Kind of, still trying to understand things

    Votes: 3 21.4%

  • Total voters
    14
Joined
Sep 22, 2015
Messages
1,610
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.
24mOf55.png


In order for this class to be an TaskBot, we need to extend it to TaskBot:
Code:
package com.qverkk.bots.tutorial_task_bot;

import com.runemate.game.api.script.framework.task.TaskBot;

public class TutorialTaskBot extends TaskBot {

}

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

Code:
package com.qverkk.bots.tutorial_task_bot;

import com.runemate.game.api.script.framework.task.TaskBot;

public class TutorialTaskBot extends TaskBot {
    @Override
    public void onStart(String... strings) {
        super.onStart(strings);
    }
}


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:
package com.qverkk.bots.tutorial_task_bot.tasks;

import com.runemate.game.api.script.framework.task.Task;

public class TravelToBank extends Task {

    @Override
    public boolean validate() {
        return false;
    }

    @Override
    public void execute() {

    }
}

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:
package com.qverkk.bots.tutorial_task_bot.tasks;

import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
import com.runemate.game.api.hybrid.region.Banks;
import com.runemate.game.api.script.framework.task.Task;

public class TravelToBank extends Task {

    @Override
    public boolean validate() {
        return Inventory.isFull() && Banks.newQuery().results().isEmpty();
    }

    @Override
    public void execute() {

    }
}

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:
package com.qverkk.bots.tutorial_task_bot.tasks;

import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
import com.runemate.game.api.hybrid.location.Area;
import com.runemate.game.api.hybrid.location.Coordinate;
import com.runemate.game.api.hybrid.region.Banks;
import com.runemate.game.api.script.framework.task.Task;

public class TravelToBank extends Task {

    private final Area.Circular exampleArea = new Area.Circular(new Coordinate(1,1,1), 15);

    @Override
    public boolean validate() {
        return Inventory.isFull() && Banks.newQuery().within(exampleArea).results().isEmpty();
    }

    @Override
    public void execute() {

    }
}

After doing so, we'll just walk to the area or a coordinate (For this, we'll use WebPath system):​
Code:
@Override
    public void execute() {
        Path path = Traversal.getDefaultWeb().getPathBuilder().buildTo(exampleArea.getRandomCoordinate());
        if(path != null) {
            path.step();
        }
    }
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:
package com.qverkk.bots.tutorial_task_bot.tasks;

import com.runemate.game.api.hybrid.entities.Player;
import com.runemate.game.api.hybrid.local.hud.interfaces.Inventory;
import com.runemate.game.api.hybrid.location.Area;
import com.runemate.game.api.hybrid.location.Coordinate;
import com.runemate.game.api.hybrid.location.navigation.Path;
import com.runemate.game.api.hybrid.location.navigation.Traversal;
import com.runemate.game.api.hybrid.region.Players;
import com.runemate.game.api.script.framework.task.Task;

public class TravelToFlax extends Task {

    private final Area.Circular flaxArea = new Area.Circular(new Coordinate(1,1,1), 15);

    @Override
    public boolean validate() {
        final Player me = Players.getLocal();
        return me != null && !Inventory.isFull() && !flaxArea.contains(me);
    }

    @Override
    public void execute() {
        Path path = Traversal.getDefaultWeb().getPathBuilder().buildTo(flaxArea.getRandomCoordinate());
        if(path != null) {
            path.step();
        }
    }
}
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:
package com.qverkk.bots.tutorial_task_bot.tasks;

import com.runemate.game.api.hybrid.entities.GameObject;
import com.runemate.game.api.hybrid.entities.Player;
import com.runemate.game.api.hybrid.local.Camera;
import com.runemate.game.api.hybrid.location.Area;
import com.runemate.game.api.hybrid.location.Coordinate;
import com.runemate.game.api.hybrid.region.GameObjects;
import com.runemate.game.api.hybrid.region.Players;
import com.runemate.game.api.script.Execution;
import com.runemate.game.api.script.framework.task.Task;

public class PickFlax extends Task {

    private final Area.Circular flaxArea = new Area.Circular(new Coordinate(1,1,1), 15);
    private GameObject flax;

    @Override
    public boolean validate() {
        final Player me = Players.getLocal();
        flax = GameObjects.newQuery().names("Flax").actions("Pick").within(flaxArea).results().nearest();
        return me != null && flax != null;
    }

    @Override
    public void execute() {
        //we don't want to interact with the flax, if it's not visible, so let's check
        //if it's visible let's interact with it, if not then just turn the camera
        if(flax.isVisible()) {
            if(flax.interact("Pick")) {
                //After interacting with our flax, we can add a check if it's still valid
                //This isn't required, you can check for player animation also
                //If you'd use player animation, you'd check if it went back to idle after picking the flax
                Execution.delayWhile(() -> flax.isValid(), 3000, 4000);
            }
        } else {
            Camera.turnTo(flax);
        }
    }
}


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:
package com.qverkk.bots.tutorial_task_bot;

import com.qverkk.bots.tutorial_task_bot.tasks.PickFlax;
import com.qverkk.bots.tutorial_task_bot.tasks.TravelToBank;
import com.qverkk.bots.tutorial_task_bot.tasks.TravelToFlax;
import com.runemate.game.api.script.framework.task.TaskBot;

public class TutorialTaskBot extends TaskBot {
    @Override
    public void onStart(String... strings) {
        super.onStart(strings);
        add(new TravelToBank(), new TravelToFlax(), new PickFlax());
    }
}

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:
@Override
    public void initialize(URL location, ResourceBundle resources) {
        setVisible(true);
        startBtn.setOnAction(event -> {
            if(isRenewalsSelected) {
               bot.add(new UseRenewals()); 
            }
            if(isOverloadSelected) {
               bot.add(new UseOverloads()); 
            }
        );
    }


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.​
 
Last edited:
Joined
Jun 24, 2014
Messages
172
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.
 
Joined
Sep 22, 2015
Messages
1,610
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.
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
 
Joined
Jun 24, 2014
Messages
172
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

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.
 
Joined
Mar 11, 2018
Messages
19
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!
 
Joined
Aug 11, 2018
Messages
3
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...
 
Joined
Sep 22, 2015
Messages
1,610
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...
The tasks are executed by the TaskBot framework. Here is a list of added tasks:
Code:
        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:
        add(new EdgevilleTraversal(), new EquipmentLoadout(), new NpcAttack());
 
Bot Author
Joined
Jan 29, 2016
Messages
1,296
The tasks are executed by the TaskBot framework. Here is a list of added tasks:
Code:
        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:
        add(new EdgevilleTraversal(), new EquipmentLoadout(), new NpcAttack());

This is a thread back from 2017 and the comments are from 2021 at the latest..
 
Top