- Joined
- Sep 22, 2015
- Messages
- 1,610
- Thread Author
- #1
A basic TaskBot tutorial
Steps you have to do before getting into the code side:
Steps you have to do before getting into the code side:
- Make sure you've properly set your IDE. If not, please visit other tutorials for guidance. (Here's one for IntellIj: CLICK
- If you want to publish bots to the botstore, you also might take a look at THIS
- 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.
In order for this class to be an TaskBot, we need to extend it to TaskBot:
(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.
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:
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:
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: