Jump to content

DexCutter - F2P Draynor Woodcutting Script | Woodcutting Guild Mage Trees


Recommended Posts

Hello everyone this is my first script. 

I'd love to grab some feedback and any progress pictures you guys post would greatly help!

This bot supports all trees around draynor village up to yew trees!

Make sure to start the bot in lumbridge or draynor to get it running for all the other trees!

If you select Magic Trees please be within the woodcutting guild!

Source Code

Spoiler
package com.dexcutter;

import java.awt.Color;
import java.awt.Component;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.net.URL;
import java.text.DecimalFormat;
import java.util.Comparator;
import java.util.List;
import java.util.concurrent.TimeUnit;

import javax.imageio.ImageIO;
import javax.swing.BoxLayout;
import javax.swing.ButtonGroup;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JRadioButton;

import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.api.model.Entity;
import org.osbot.rs07.api.model.RS2Object;
import org.osbot.rs07.api.ui.Skill;
import org.osbot.rs07.api.ui.Tab;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;
import org.osbot.rs07.utility.ConditionalSleep;

@ScriptManifest(author = "Dextrell", info = "Woodcutting Script", name = "DexCutter", version = 2, logo = "https://i.imghippo.com/files/7akYx1724390898.png")
public class DexCutter extends Script {

	private boolean isRunning;

	private long timeStarted;
	private long timeFinished;
	private long timeElapsed;

	private int startingXp;
	private int endedXp;
	private int xpGained;
	private int currentXp;

	private int logsChopped = 0;

	private int currentLevel;
	private int startingLevel;
	private int levelsGained;
	private boolean forestry = true;

	@SuppressWarnings("unused")
	private boolean dropLogs;

	private DecimalFormat df = new DecimalFormat("#");
	private Font font = new Font("Consolas", Font.BOLD, 15);

	// Gui components
	private JFrame frame;

	private String[] treeChoices = { "Magic tree", "Tree", "Oak tree", "Willow tree", "Yew tree" };
	private String[] axeChoices = { "Dragon axe", "Bronze axe", "Iron axe", "Steel axe", "Black axe", "Adamant axe",
			"Rune axe" };

	private Player player;
	
	private BufferedImage img;


	/**
	 * Regular Tree: 1278 Oak Tree: 10820
	 */
	@Override
	public void onStart() {
		log("Initializing Script....");
		frame = new JFrame("DexCutter");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.setBounds(50, 50, 400, 400);


		JPanel panel = new JPanel();
		panel.setLayout(new BoxLayout(panel, BoxLayout.Y_AXIS));
		JLabel treeLabel = new JLabel("Select a tree type");
		treeLabel.setAlignmentX(Component.CENTER_ALIGNMENT);
		panel.setSize(400, 400);
		panel.add(treeLabel);

		JComboBox<String> treeComboBox = new JComboBox<String>(treeChoices);
		treeComboBox.setMaximumSize(treeComboBox.getPreferredSize());
		treeComboBox.setAlignmentX(Component.CENTER_ALIGNMENT);
		treeComboBox.setSelectedItem(treeChoices[0]);

		player = new Player(this);
		player.setTree(Tree.MAGIC);
		player.setTreeArea(player.getTree().getAreas()[0]);
		treeComboBox.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				// TODO Auto-generated method stub
				String treeSelected = treeComboBox.getSelectedItem().toString();

				switch (treeSelected) {
				case "Tree":
					player.setTree(Tree.TREE);
					break;
				case "Oak tree":
					player.setTree(Tree.OAK);
					break;
				case "Willow tree":
					player.setTree(Tree.WILLOW);
					break;
				case "Yew tree":
					player.setTree(Tree.YEW);
					break;
				case "Magic tree":
					player.setTree(Tree.MAGIC);
					log("Setting Magic Tree");
				default:
					player.setTree(Tree.TREE);
					break;
				}
				player.setTreeArea(player.getTree().getAreas()[0]);
			}
		});

		JComboBox<String> axeComboBox = new JComboBox<String>(axeChoices);
		axeComboBox.setMaximumSize(axeComboBox.getPreferredSize());
		axeComboBox.setAlignmentX(Component.CENTER_ALIGNMENT);
		axeComboBox.setSelectedItem(axeChoices[0]);
		player.setAxe(axeChoices[0]);
		axeComboBox.addActionListener(new ActionListener() {

			@Override
			public void actionPerformed(ActionEvent e) {
				player.setAxe((String) axeComboBox.getSelectedItem());
			}

		});
		panel.add(treeComboBox);
		panel.add(axeComboBox);

		JLabel dropLogsLabel = new JLabel("Drop Logs?");

		panel.add(dropLogsLabel);

		ButtonGroup dropRadioButtonGroup = new ButtonGroup();

		JRadioButton yesButton = new JRadioButton();
		yesButton.setText("Yes");
		// yesButton.setBounds(120, 30, 120, 50);

		JRadioButton noButton = new JRadioButton();
		noButton.setText("No");
		// noButton.setBounds(250, 30, 80, 50);
		noButton.setSelected(true);

		panel.add(yesButton);
		panel.add(noButton);

		dropRadioButtonGroup.add(yesButton);
		dropRadioButtonGroup.add(noButton);

		JButton startButton = new JButton("Start");
		startButton.setAlignmentX(Component.CENTER_ALIGNMENT);

		startButton.addActionListener(e -> {

			dropLogs = yesButton.isSelected();

			if (player.getTree() == null && player.getTreeArea() != null) {
				JOptionPane.showMessageDialog(null, "Error: Tree type not selected!");
			} else {
				isRunning = true;
				timeStarted = System.currentTimeMillis();
				startingXp = skills.getExperience(Skill.WOODCUTTING);
				startingLevel = skills.getStatic(Skill.WOODCUTTING);
				frame.dispose();
				log("Selected: " + player.getTree().getName());
			}
		});

		panel.add(startButton);
		frame.add(panel);

		log("Tree selected: " + player.getTree());

		img = getImage("https://iili.io/dFKcgGR.png");
		//log("image: " + backgroundImage);
		frame.setVisible(true);
	}

	@Override
	public int onLoop() throws InterruptedException {

		if (isRunning) {
			if (!getInventory().isFull() && !player.getTreeArea().contains(myPlayer())) {
				if (getWalking().webWalk(player.getTreeArea())) {
					log("Walking to trees...");

					if (settings.getRunEnergy() >= 70) {
						settings.setRunning(true);
					}

					new ConditionalSleep(8000, 10000) {
						@Override
						public boolean condition() throws InterruptedException {
							return false;
						}
					};
				}
			} else if (!getInventory().isFull()) {
				player.chopTree();
			} else {
				log("Inventory full."); // Walks to the bank.
				player.bankInventory();
			}

			int randVal = random(0, 1000);

			if (randVal == 25) {
				log(randVal + " open friends");
				openFriends();
			}
			
			
			if(getEquipment().isWieldingWeapon("Dragon axe") && getCombat().getSpecialPercentage() == 100) {
				log("Activing spec...");
				getCombat().toggleSpecialAttack(true, true);
			}
			
			if(forestry) {
				//check for rising roots
				Entity risingRoots = getObjects().closestThatContains("Rising roots");
				
				if(risingRoots != null) {
					new ConditionalSleep(2000, 3000) {
						@Override
						public boolean condition() throws InterruptedException {
							risingRoots.interact("Chop down");
							return !myPlayer().isAnimating();
						}
					}.sleep();
				}
			}
		}

		return random(200, 300);
	}

	@Override
	public void onExit() {
		log("Thank you for using DexCutter!");
		timeFinished = System.currentTimeMillis();
		endedXp = skills.getExperience(Skill.WOODCUTTING);
		log("Time Finished: " + timeFinished + " Exp Gathered: " + endedXp);
	}

	@Override
	public void onPaint(Graphics2D g) {

		if (isRunning) {
			g.setFont(font);
			g.setFont(g.getFont().deriveFont(15.0f));
			g.setColor(Color.CYAN);

			g.drawRect((int)mouse.getPosition().getX()-10, (int)mouse.getPosition().getY()-10, 20, 20);
			g.drawLine((int)mouse.getPosition().getX(), 0, (int)mouse.getPosition().getX(), 500);
			g.drawLine(0, (int)mouse.getPosition().getY(), 800, (int)mouse.getPosition().getY());
			
			g.setColor(Color.RED);
			timeElapsed = System.currentTimeMillis() - this.timeStarted;

			if (img != null)
				g.drawImage(img, 0, 340, img.getWidth(), img.getHeight()-25, null);
			g.drawString("Time ran for:", 40, 395);
			g.drawString(ft(timeElapsed), 150, 395);

			currentXp = skills.getExperience(Skill.WOODCUTTING);
			xpGained = currentXp - startingXp;
			currentLevel = skills.getStatic(Skill.WOODCUTTING);
			g.drawString("Xp Gained:" + xpGained, 40, 420);
			levelsGained = currentLevel - startingLevel;
			g.drawString("Levels gained:" + levelsGained, 260, 420);

			logsChopped = (int) (xpGained / player.getTree().getExperience());

			g.drawString("Logs chopped:" + df.format(logsChopped), 40, 445);
		}

	}

	private String ft(long duration) // Makes time 0:0:0
	{

		String res = "";
		long days = TimeUnit.MILLISECONDS.toDays(duration);
		long hours = TimeUnit.MILLISECONDS.toHours(duration)
				- TimeUnit.DAYS.toHours(TimeUnit.MILLISECONDS.toDays(duration));
		long minutes = TimeUnit.MILLISECONDS.toMinutes(duration)
				- TimeUnit.HOURS.toMinutes(TimeUnit.MILLISECONDS.toHours(duration));
		long seconds = TimeUnit.MILLISECONDS.toSeconds(duration)
				- TimeUnit.MINUTES.toSeconds(TimeUnit.MILLISECONDS.toMinutes(duration));
		if (days == 0) {
			res = (hours + ":" + minutes + ":" + seconds);
		} else {
			res = (days + ":" + hours + ":" + minutes + ":" + seconds);
		}
		return res;
	}

	public RS2Object getClosestObject(Script script, Position position) {
		List<RS2Object> regionObjects = script.objects.getAll();
		if (regionObjects.size() == 0) {
			script.log("No objects found");
			return null;
		} else if (regionObjects.size() == 1) {
			return regionObjects.get(0);
		}
		regionObjects.sort(new Comparator<RS2Object>() {
			@Override
			public int compare(RS2Object o1, RS2Object o2) {
				return o1.getPosition().distance(position) - o2.getPosition().distance(position);
			}
		});
		return regionObjects.get(0);
	}

	public void openInventory() {
		getTabs().open(Tab.INVENTORY);

		new ConditionalSleep(450, 3000) {

			@Override
			public boolean condition() throws InterruptedException {

				return getTabs().getOpen().equals(Tab.INVENTORY);
			}

		}.sleep();
	}

	public void openFriends() {
		getTabs().open(Tab.FRIENDS);

		new ConditionalSleep(450, 3000) {

			@Override
			public boolean condition() throws InterruptedException {

				return getTabs().getOpen().equals(Tab.FRIENDS);
			}

		}.sleep();
		openInventory();
	}
	
	private BufferedImage getImage(String url) // Get's the background image.
	{
		try {
			log("image read");
			return ImageIO.read(new URL(url));
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
	}

}

 

package com.dexcutter;

import org.osbot.rs07.api.map.Area;

public enum Tree {

	TREE("Tree", 25, 1278, 2000, 8000, new Area[]{new Area(3146, 3228, 3204, 3213)}),
	OAK("Oak tree", 10820, 37.5, 8000, 10000, new Area[] {new Area(3146, 3228, 3164, 3213)}),
	WILLOW("Willow tree", 8481, 67.5, 10000, 13000, new Area[] {new Area(3087, 3225, 3092, 3239)}),
	YEW("Yew tree", 10822, 175, 15000, 20000, new Area[] {new Area(3145,3251,3150,3257), new Area(3150, 3223, 3154, 3230), 
			new Area(3164, 3218, 3168, 3222), new Area(3183, 3224, 3188, 3228)});
	
	private String name;
	private int objectId;
	private double experience;
	private int minTime;
	private int maxTime;
	private Area[] areas;
	
	private Tree(String name, int objectId, double experience, int minTime, int maxTime, Area[] areas) {
		this.name = name;
		this.objectId = objectId;
		this.experience = experience;
		this.minTime = minTime;
		this.maxTime = maxTime;
		this.areas = areas;
	}
	
	public String getName() {
		return this.name;
	}
	
	public int getObjectId() {
		return this.objectId;
	}
	
	public double getExperience() {
		return this.experience;
	}
	
	public int getMinTime() {
		return minTime;
	}
	
	public int getMaxTime() {
		return maxTime;
	}
	
	public Area[] getAreas() {
		return this.areas;
	}
}

 

Media

Spoiler

dFKE4xn.png

1100x800_cropped.jpg

 

 

Jar Download

Spoiler

 

Edited by Dextrell
Update fixing a bug with willows
Link to comment
Share on other sites

 

1. Put the image in resources so that a network request is not needed then use SystemIO to get thz. There is no guarantee that the hosting service won't delete your image randomly. Refer to the link below for a more concise tutorial. 


RS2Object treeObject = getObjects().closest(tree.getObjectId());

			if (treeObject == null) {
				this.log("Yew tree is null....");

			}
			log("does it contain tree obj? " + treeArea.contains(treeObject));

 

2. Use the filter API. This can be simplified to something like
```
RS2Object treeObject = getObjects().closest(rs2Object -> rs2Object.getId() == tree.getObjectId() && treeArea.contains(rs2Object);
```

This will ensure tree interactions are only done on trees of a certain type (regular, oak, willow, ect.) and are in the designated area.

 

 

3. The Paint and GUI are crammed in the the Script class its hard to read. Consider splitting these up into individual classes. You can designate a painter class by having it implement Painter. Then in onStart calling

getBot().addPainter(<paint instance>)

Make sure to remove this in onStop with 

getBot().removePainter(<same instance as above>)

Otherwise the paint may not get cleaned up if the script crashes/exits. 


4. You don't need to call this if you are intending to immediately interact with the object. The interaction will do this if the object is not on screen. 

if (getCamera().toEntity(treeObject))






Its a great first attempt. Ill take a look at the gui later. 

Edited by yfoo
  • Heart 1
Link to comment
Share on other sites

As for the GUI error

public void onStart() {
		log("Initializing Script....");
		frame = new JFrame("DexCutter");
		frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
		frame.setBounds(50, 50, 400, 400);
		frame.setVisible(true); //<<<<<<<<<<<<<<<<<
...


Move 

frame.setVisible(true);


to the end of onStart(). It is set to visible before al the other components are added to the panel. 

  • Heart 1
Link to comment
Share on other sites

On 6/29/2024 at 5:20 PM, yfoo said:
 

1. Put the image in resources so that a network request is not needed then use SystemIO to get thz. There is no guarantee that the hosting service won't delete your image randomly. Refer to the link below for a more concise tutorial. 


RS2Object treeObject = getObjects().closest(tree.getObjectId());

			if (treeObject == null) {
				this.log("Yew tree is null....");

			}
			log("does it contain tree obj? " + treeArea.contains(treeObject));

 

2. Use the filter API. This can be simplified to something like
```
RS2Object treeObject = getObjects().closest(rs2Object -> rs2Object.getId() == tree.getObjectId() && treeArea.contains(rs2Object);
```

This will ensure tree interactions are only done on trees of a certain type (regular, oak, willow, ect.) and are in the designated area.

 

 

3. The Paint and GUI are crammed in the the Script class its hard to read. Consider splitting these up into individual classes. You can designate a painter class by having it implement Painter. Then in onStart calling

getBot().addPainter(<paint instance>)

Make sure to remove this in onStop with 

getBot().removePainter(<same instance as above>)

Otherwise the paint may not get cleaned up if the script crashes/exits. 


4. You don't need to call this if you are intending to immediately interact with the object. The interaction will do this if the object is not on screen. 

if (getCamera().toEntity(treeObject))






Its a great first attempt. Ill take a look at the gui later. 

Thank you so much for the useful insight I'll make those changes!

You're right about the painter thank you so much for the tips!

Link to comment
Share on other sites

  • 1 month later...
Posted (edited)
On 6/29/2024 at 5:20 PM, yfoo said:
 

1. Put the image in resources so that a network request is not needed then use SystemIO to get thz. There is no guarantee that the hosting service won't delete your image randomly. Refer to the link below for a more concise tutorial. 


RS2Object treeObject = getObjects().closest(tree.getObjectId());

			if (treeObject == null) {
				this.log("Yew tree is null....");

			}
			log("does it contain tree obj? " + treeArea.contains(treeObject));

 

2. Use the filter API. This can be simplified to something like
```
RS2Object treeObject = getObjects().closest(rs2Object -> rs2Object.getId() == tree.getObjectId() && treeArea.contains(rs2Object);
```

This will ensure tree interactions are only done on trees of a certain type (regular, oak, willow, ect.) and are in the designated area.

 

 

3. The Paint and GUI are crammed in the the Script class its hard to read. Consider splitting these up into individual classes. You can designate a painter class by having it implement Painter. Then in onStart calling

getBot().addPainter(<paint instance>)

Make sure to remove this in onStop with 

getBot().removePainter(<same instance as above>)

Otherwise the paint may not get cleaned up if the script crashes/exits. 


4. You don't need to call this if you are intending to immediately interact with the object. The interaction will do this if the object is not on screen. 

if (getCamera().toEntity(treeObject))






Its a great first attempt. Ill take a look at the gui later. 

I've tried loading the image as a resource countless of times i set a "res" folder as a resource my file structure is the following

(I made sure the res folder was set as a resource folder)

DexCutter

      -> src

               com.dexcutter <- code goes here

     -> res

             img.png

It will always be null I've tried loading it many different ways even did DexCutter.class.getResourceAsStream  

The only thing I can consider doing is having a downloader that gets the image online and puts it in the data folder.

try {

backgroundImage = ImageIO.read(getScriptResourceAsStream("img.png"));

} catch (IOException e) {

log(e);

}

Edited by Dextrell
Link to comment
Share on other sites

  • Dextrell changed the title to DexCutter - F2P Draynor Woodcutting Script | Woodcutting Guild Mage Trees
10 hours ago, Dextrell said:

I've tried loading the image as a resource countless of times i set a "res" folder as a resource my file structure is the following

(I made sure the res folder was set as a resource folder)

DexCutter

      -> src

               com.dexcutter <- code goes here

     -> res

             img.png

It will always be null I've tried loading it many different ways even did DexCutter.class.getResourceAsStream  

The only thing I can consider doing is having a downloader that gets the image online and puts it in the data folder.

try {

backgroundImage = ImageIO.read(getScriptResourceAsStream("img.png"));

} catch (IOException e) {

log(e);

}

Path is wrong. its in /res, and getScriptResourceAsStream("img.png") does not have /res in it. 

Link to comment
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...