Before we begin, you should be on notice that:
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Now that we are done with the icky stuff, lets get to the goods.
First and foremost, I AM NOT A PROGRAMMER. In fact, I am a law student. I do this in my spare time for fun. I can use all of the help I can get, so please feel free to contribute your code.
UPDATES
1-18 - Added coordinate array to move subroutine on collector bot. This effectively allows the bot to collect in a circle around the hearth fire.
1-19 - Updated Logger bot. Should run smooth without errors.
2-8 - Added stump remover.
2-11 - Added Seed Dropper (Thanks Oddy)
Setting up the bot client
- 1. Go to this thread viewtopic.php?f=27&t=20326
- Code: Select all
"C:\Program Files (x86)\Java\jre6\bin\java.exe" -Djava.library.path="C:\users\david\desktop\bot" -cp groovy-1.7.5.jar -Xms256m -Xmx512m -jar haven.jar moltke.seatribe.se
2. Download the Hearth-Haven-Groovy-Bot
3. Run the Haven.Jar as if you would on ender's client (a run.command, or run.bat) In fact, you can probably just copy it although I haven't tried it.
4. If you are having trouble with the run.bat, try editing it to the following:
Just make sure you change the path= to the location of the bot folder on your own hard drive. Also, change the path to the place where Java is located on your computer - this may vary depending on your intall.
5. Log in to the character that you are using as a bot.
Once you run it, you’ll see that it looks like a vanilla haven and hearth client. However, it should be ark.su client that has the bot incorporated.
Running Scripts
There are two ways to run scripts (hotkey, manual), but I tend to use the hotkey method more.
When you are in the game with the character you are using as a bot, you can type :bot “script name” or you can bind a bot to either F1 or F2 by typing :set_bot1 “script name” or :set_bot2 “script name”
Note that the script name should not be in quotes
Bot Scripts are saved to the scripts folder, and only bots that end in .groovy will be able to run through this bot.
You can stop a script at any time by pressing F3.
Saving Scripts
If you find a bot that is posted in this thread or somewhere else, you can save it to your scripts folder simply by copying the code into a text file, and saving the file as whatever.groovy. Remember, the file must be .groovy or else it will not run in the bot.
Bot List
If you post a bot, please include a description of what it does, and any flaws it may have.
Logging Bot
This bot is just a basic rewrite of the logging bot that came with the bot listed. In order to make this work, you only need a character equipped with an axe. The bot will drop the logs next to his hearth, or any nearby hearth. It will teleport to the hearth after chopping down a tree. Also, it waits until it has 90% stamina to continue chopping. Unfortunately, I have not yet added a section which makes it pick up all of the logs from a tree, so it is not working at peak efficiency. Nevertheless, it will help automate collection of logs. Try using the log collector in addition for collecting all of the logs.
Problems: It will stop when there are no more logs in the area, but thats probably not a big concern anyway (You'll want to just move a hearth fire to be more efficient).
- Code: Select all
import haven.CharWnd
import haven.RootWidget
import haven.Speedget
import haven.ark_bot
import haven.Coord
import haven.Gob
import haven.Drawable;
import util.PathFinder;
import haven.UI
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.ConsoleHandler
class LamberJack {
def thread
Speedget speedget
PathFinder pathFinder
private final static Logger LOGGER = Logger.getLogger(LamberJack.class.getName());
final static int MOUSE_LEFT_BUTTON = 1
final static int MOUSE_RIGHT_BUTTON = 3
final int wineChestId;
final int waterBarrelId;
final int postId;
int totalLogs = 0
LamberJack(thread){
this.thread = thread
this.pathFinder = new PathFinder(thread)
LOGGER.setLevel(Level.FINE)
}
void run(){
println '.....................................................'
ark_bot.ui.widgets.each { key, value ->
if (value instanceof Speedget){
speedget = (Speedget)value;
}
}
this.speedget.uimsg("cur", 1);
def pauseTime = 400;
ark_bot.SlenPrint('Here Comes The Sun');
thread.sleep(pauseTime);
thread.sleep(pauseTime);
def i=0;
while(i<2000){
i = i+1;
this.cutATree(); // Finds a tree to cut and cuts it
this.getALog(); // picks up the log
this.stockPileLogs(); // stores log
this.logCount();
this.checkStamina();
}
println '.....................................................'
}
void getALog(){
int logID = ark_bot.find_object_by_name("trees/log", 200);
if (logID){
ark_bot.SlenPrint('Roses are red, violets are blue, I carry logs, and Redell sucks. :D');
pathFinder.travelTo(logID);
ark_bot.SendAction("carry");
this.waitChiCursor();
ark_bot.DoClick(logID, MOUSE_LEFT_BUTTON, 0);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
this.teleportToHearthFire();
}else{
this.cutATree();
this.getALog();
}
}
void cutATree(){
int treeId = ark_bot.find_object_by_type("tree", 50);
pathFinder.travelTo(treeId);
actTree(treeId, "Chop");
}
void actTree(treeId, act){
Coord offset1 = ark_bot.MyCoord().add(10,10);
pathFinder.travelToMapLocation(offset1); // Drops anything before trying to cut a tree
ark_bot.DoClick(offset1, MOUSE_RIGHT_BUTTON, 0); // Drops anything before trying to cut a tree
thread.sleep(1000);
ark_bot.DoClick(treeId, MOUSE_RIGHT_BUTTON, 0);
waitForContextMenu();
ark_bot.SlenPrint("I'll " + act + ' this bitch!');
ark_bot.SelectFlowerMenuOpt(act);
thread.sleep(200);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
waitForHourglass();
thread.sleep(500);
}
void stackLog(){
//ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
stockPileLogs(); //à reprendre
}
void processStump(){
int stumpID = ark_bot.find_object_by_name("stump", 10);
if (stumpID){
//pathFinder.travelTo(stumpID);
actTree(stumpID, "Remove");
}
thread.sleep(2000)
}
/*
* Need to be rebuilt for player to choose the place he wants the log stack.
*/
void stockPileLogs(){
ark_bot.SlenPrint("Stockpiling logs");
def claimID = ark_bot.find_object_by_name("hearth", 100);
if (claimID){
def claim = ark_bot.glob.oc.getgob(claimID);
Coord claimC = ark_bot.mapview.tilify(claim.getc());
Coord offset = claimC.add(new Coord(10, 10));
pathFinder.travelToMapLocation(offset);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0); // drop log
thread.sleep(300);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
} else {
this.teleportToHearthFire();
thread.sleep(1000);
ark_bot.exit_command();
}
}
/*
*
*
* ************ useful funcs ***********
*
*/
void openInventory(){
if(!ark_bot.isInventoryOpen()){
ark_bot.OpenInventory();
thread.sleep(500)
openInventory();
}
}
void waitForContextMenu(){
while(!ark_bot.isFlowerMenuReady()) {thread.sleep(100)}
}
void waitForHourglass(){
LOGGER.fine ' ' * 10 + '|| waitForHourglass started ['
while(!ark_bot.HourGlass){thread.sleep(100)}
while(ark_bot.HourGlass) {thread.sleep(100)}
LOGGER.fine ' ' * 10 + '|| waitForHourglass finished ]'
}
void teleportToVillage(){
ark_bot.SendAction("theTrav", "village");
thread.sleep(500);
}
void teleportToHearthFire(){
ark_bot.SendAction("theTrav", "hearth");
waitForHourglass();
thread.sleep(500);
}
void waitChiCursor(){
while(!(ark_bot.cursor_name == "chi")) thread.sleep(100);
}
void checkStamina(){
while(ark_bot.Stamina < 90){
ark_bot.SlenPrint('I am le tired...');
thread.sleep(1000);
}
ark_bot.SlenPrint('ENERGIZE');
thread.sleep(500);
}
void logCount(){
totalLogs++;
ark_bot.SlenPrint("I have delivered " + totalLogs + ' logs!');
thread.sleep(1000);
println ''
println '*' * 10
println 'Logs brought: ' + totalLogs
println '*' * 10
println ''
}
}
new LamberJack(thread=currentThread).run();
Log Collector
This bot runs in one direction and collects all of the logs in a particular radius. This now uses 8 coordinate points to collect in a circle around the hearth fire.
- Code: Select all
import haven.CharWnd
import haven.RootWidget
import haven.Speedget
import haven.ark_bot
import haven.Coord
import haven.Gob
import haven.Drawable;
import util.PathFinder;
import haven.UI
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.ConsoleHandler
class LamberJack {
def thread
Speedget speedget
PathFinder pathFinder
private final static Logger LOGGER = Logger.getLogger(LamberJack.class.getName());
final static int MOUSE_LEFT_BUTTON = 1
final static int MOUSE_RIGHT_BUTTON = 3
final int wineChestId;
final int waterBarrelId;
final int postId;
int totalLogs = 0
int arrcount = 0
LamberJack(thread){
this.thread = thread
this.pathFinder = new PathFinder(thread)
LOGGER.setLevel(Level.FINE)
}
void run(){
println '.....................................................'
ark_bot.ui.widgets.each { key, value ->
if (value instanceof Speedget){
speedget = (Speedget)value;
}
}
this.speedget.uimsg("cur", 1);
def pauseTime = 4000;
ark_bot.SlenPrint('Here Comes A Dumpster');
thread.sleep(pauseTime);
thread.sleep(pauseTime);
def i=0;
while(i<2000){
i = i+1;
this.randommove(); // Moves away from hearthfire
this.getALog(); // Finds and picks up log
this.stockPileLogs(); // Teleports back to hearthfire drops log
this.logCount(); // displays how many logs have been collected
this.checkStamina(); // Checks to see if bot needs to rest
}
println '.....................................................'
}
void waitArwCursor(){
while(!(ark_bot.cursor_name == "arw")) thread.sleep(100);
}
void randommove(){
def arr1 = [0, 250, 250,250, 0, -250,-250, -250] // x cords
def arr2 = [250, 250, 0, -250, -250, -250, 0, 250] // y cords
Coord offset1 = ark_bot.MyCoord().add(arr1[arrcount],arr2[arrcount]);
pathFinder.travelToMapLocation(offset1);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
println 'Done Waiting For Move'
arrcount = arrcount+1;
if(arrcount>=8){ // cycle through coordinates, returns to 0 after 8
arrcount = 0;
}
}
void getALog(){
int logID = ark_bot.find_object_by_name("trees/log", 200);
if (logID){
ark_bot.SlenPrint('I am a log dumpster. :( ');
pathFinder.travelTo(logID);
ark_bot.SendAction("carry");
this.waitChiCursor();
ark_bot.DoClick(logID, MOUSE_LEFT_BUTTON, 0);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
thread.sleep(300);
}else{
this.randommove();
this.getALog();
}
}
void cutATree(){
int treeId = ark_bot.find_object_by_type("tree", 50);
pathFinder.travelTo(treeId);
actTree(treeId, "Chop");
}
void actTree(treeId, act){
Coord offset1 = ark_bot.MyCoord().add(10,10);
pathFinder.travelToMapLocation(offset1);
ark_bot.DoClick(offset1, MOUSE_RIGHT_BUTTON, 0);
thread.sleep(1000);
ark_bot.DoClick(treeId, MOUSE_RIGHT_BUTTON, 0);
waitForContextMenu();
ark_bot.SlenPrint("I'll " + act + ' this bitch!');
ark_bot.SelectFlowerMenuOpt(act);
thread.sleep(200);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
}
void stackLog(){
//ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
stockPileLogs(); //à reprendre
}
void processStump(){
int stumpID = ark_bot.find_object_by_name("stump", 10);
if (stumpID){
//pathFinder.travelTo(stumpID);
actTree(stumpID, "Remove");
}
thread.sleep(2000)
}
/*
* Need to be rebuilt for player to choose the place he wants the log stack.
*/
void stockPileLogs(){
this.teleportToHearthFire();
ark_bot.SlenPrint("Stockpiling logs");
def claimID = ark_bot.find_object_by_name("hearth", 100);
if (claimID){
def claim = ark_bot.glob.oc.getgob(claimID);
Coord claimC = ark_bot.mapview.tilify(claim.getc());
Coord offset = claimC.add(new Coord(-15, -15));
pathFinder.travelToMapLocation(offset);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0); // drop log
thread.sleep(300);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
} else {
ark_bot.exit_command();
}
}
/*
*
*
* ************ useful funcs ***********
*
*/
void openInventory(){
if(!ark_bot.isInventoryOpen()){
ark_bot.OpenInventory();
thread.sleep(500)
openInventory();
}
}
void waitForContextMenu(){
while(!ark_bot.isFlowerMenuReady()) {thread.sleep(100)}
}
void waitForHourglass(){
LOGGER.fine ' ' * 10 + '|| waitForHourglass started ['
while(!ark_bot.HourGlass){thread.sleep(100)}
while(ark_bot.HourGlass) {thread.sleep(100)}
LOGGER.fine ' ' * 10 + '|| waitForHourglass finished ]'
}
void teleportToVillage(){
ark_bot.SendAction("theTrav", "village");
thread.sleep(500);
}
void teleportToHearthFire(){
ark_bot.SendAction("theTrav", "hearth");
waitForHourglass();
thread.sleep(500);
}
void waitChiCursor(){
while(!(ark_bot.cursor_name == "chi")) thread.sleep(100);
}
void checkStamina(){
while(ark_bot.Stamina < 90){
ark_bot.SlenPrint('I am le tired...');
thread.sleep(1000);
}
ark_bot.SlenPrint('ENERGIZE');
thread.sleep(500);
}
void logCount(){
totalLogs++;
ark_bot.SlenPrint("I have delivered " + totalLogs + ' logs!');
thread.sleep(1000);
println ''
println '*' * 10
println 'Logs brought: ' + totalLogs
println '*' * 10
println ''
}
}
new LamberJack(thread=currentThread).run();
Stump Remover
This bot finds stumps and removes them. It does NOT store the logs, and will wait for stamina to refill before moving to the next stump.
- Code: Select all
import haven.CharWnd
import haven.RootWidget
import haven.Speedget
import haven.ark_bot
import haven.Coord
import haven.Gob
import haven.Drawable;
import util.PathFinder;
import haven.UI
import java.util.logging.Logger;
import java.util.logging.Level;
import java.util.logging.ConsoleHandler
class LamberJack {
def thread
Speedget speedget
PathFinder pathFinder
private final static Logger LOGGER = Logger.getLogger(LamberJack.class.getName());
final static int MOUSE_LEFT_BUTTON = 1
final static int MOUSE_RIGHT_BUTTON = 3
final int wineChestId;
final int waterBarrelId;
final int postId;
int totalLogs = 0
LamberJack(thread){
this.thread = thread
this.pathFinder = new PathFinder(thread)
LOGGER.setLevel(Level.FINE)
}
void run(){
println '.....................................................'
ark_bot.ui.widgets.each { key, value ->
if (value instanceof Speedget){
speedget = (Speedget)value;
}
}
this.speedget.uimsg("cur", 1);
def pauseTime = 400;
ark_bot.SlenPrint('Here Comes The Sun');
thread.sleep(pauseTime);
thread.sleep(pauseTime);
def i=0;
while(i<2000){
i = i+1;
this.processStump();
this.checkStamina();
this.teleportToHearthFire();
}
println '.....................................................'
}
void getALog(){
int logID = ark_bot.find_object_by_name("trees/log", 200);
if (logID){
ark_bot.SlenPrint('Roses are red, violets are blue, I carry logs, and Redell sucks. :D');
pathFinder.travelTo(logID);
ark_bot.SendAction("carry");
this.waitChiCursor();
ark_bot.DoClick(logID, MOUSE_LEFT_BUTTON, 0);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
this.teleportToHearthFire();
}else{
this.cutATree();
this.getALog();
}
}
void cutATree(){
int treeId = ark_bot.find_object_by_type("tree", 50);
pathFinder.travelTo(treeId);
actTree(treeId, "Chop");
waitForHourglass();
}
void actTree(treeId, act){
Coord offset1 = ark_bot.MyCoord().add(10,10);
pathFinder.travelToMapLocation(offset1); // Drops anything before trying to cut a tree
ark_bot.DoClick(offset1, MOUSE_RIGHT_BUTTON, 0); // Drops anything before trying to cut a tree
thread.sleep(1000);
ark_bot.DoClick(treeId, MOUSE_RIGHT_BUTTON, 0);
waitForContextMenu();
ark_bot.SlenPrint("I'll " + act + ' this bitch!');
ark_bot.SelectFlowerMenuOpt(act);
thread.sleep(200);
while(ark_bot.mapview.player_moving){thread.sleep(10)}
waitForHourglass();
thread.sleep(500);
}
void stackLog(){
//ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
stockPileLogs(); //à reprendre
}
void processStump(){
int stumpID = ark_bot.find_object_by_name("stump", 200);
if (stumpID){
//pathFinder.travelTo(stumpID);
actTree(stumpID, "Remove");
}
thread.sleep(2000)
}
/*
* Need to be rebuilt for player to choose the place he wants the log stack.
*/
void stockPileLogs(){
ark_bot.SlenPrint("Stockpiling logs");
def claimID = ark_bot.find_object_by_name("hearth", 100);
if (claimID){
def claim = ark_bot.glob.oc.getgob(claimID);
Coord claimC = ark_bot.mapview.tilify(claim.getc());
Coord offset = claimC.add(new Coord(-25, -25));
pathFinder.travelToMapLocation(offset);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0); // drop log
thread.sleep(300);
ark_bot.DoClick(ark_bot.MyCoord(), MOUSE_RIGHT_BUTTON, 0);
} else {
this.teleportToHearthFire();
thread.sleep(1000);
ark_bot.exit_command();
}
}
/*
*
*
* ************ useful funcs ***********
*
*/
void openInventory(){
if(!ark_bot.isInventoryOpen()){
ark_bot.OpenInventory();
thread.sleep(500)
openInventory();
}
}
void waitForContextMenu(){
while(!ark_bot.isFlowerMenuReady()) {thread.sleep(100)}
}
void waitForHourglass(){
LOGGER.fine ' ' * 10 + '|| waitForHourglass started ['
while(!ark_bot.HourGlass){thread.sleep(100)}
while(ark_bot.HourGlass) {thread.sleep(100)}
LOGGER.fine ' ' * 10 + '|| waitForHourglass finished ]'
}
void teleportToVillage(){
ark_bot.SendAction("theTrav", "village");
thread.sleep(500);
}
void teleportToHearthFire(){
ark_bot.SendAction("theTrav", "hearth");
waitForHourglass();
thread.sleep(500);
}
void waitChiCursor(){
while(!(ark_bot.cursor_name == "chi")) thread.sleep(100);
}
void checkStamina(){
while(ark_bot.Stamina < 90){
ark_bot.SlenPrint('I am le tired...');
thread.sleep(1000);
}
ark_bot.SlenPrint('ENERGIZE');
thread.sleep(500);
}
void logCount(){
totalLogs++;
ark_bot.SlenPrint("I have delivered " + totalLogs + ' logs!');
thread.sleep(1000);
println ''
println '*' * 10
println 'Logs brought: ' + totalLogs
println '*' * 10
println ''
}
}
new LamberJack(thread=currentThread).run();
Seed Dropper
Drops all seeds in seed bags. Special thanks to Oddy for posting this one.
- Code: Select all
import static sys.*
main();
void main() {
// Close all seedbags.
findWindows("Seedbag").each { it.close() }
wait({ getInventory("Seedbag") != null });
invo = waitInventory();
for (item in invo.getItems()) {
if (item.isName("bag-seed")) {
item.act();
for (seed in waitInventory("Seedbag").getItems()) {
seed.drop();
}
closeBag();
}
}
}
void closeBag() {
findWindow("Seedbag")?.close();
while (getInventory("Seedbag") != null) {
Thread.sleep(100);
}
}
Work in Progress
- Farming bot (already exists, but needs work)
Gathering bot
Silk Farming bot
Paving bot
Requests
Programmer to clean up the code.