Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
jkpker

First Script

Recommended Posts

Hi Everyone, i've started scripting as of today and would like some help.

 

The goal is to make a script to woodcut trees and light them in the lumbridge area. 

The problem i've encountered is the way how i check if the tile is available for lighting a fire or not and finding a new empty tile.

 

My method (although not ideal) for tile availability is by checking the latest entry in the chatbox to see if it is equal to  "You can't light a fire here.".

I've tested it by using a System.out.println to see the output, but it is still just executing the code of lighting a log anyways.

 

Any suggestions on how i can check for a new tile as well, currently what i have is just random generation of a tile where current x & y are increased by a number between 0 and 3, really not ideal.

 

This is not really an end-goal project script, the goal of this script is to practice. If you have any tips on how to improve this script or just scripting in general, feel free to give them!

Cheers

Find the script here: https://pastebin.com/d9BV21D7

Share this post


Link to post
Share on other sites
  1. Create an area around the player.
  2. Create a List of RSTile that will contain the usable tiles.
  3. Invoke getAllTiles on the area you created. Iterate over the tiles and do this for every one:
if (!PathFinding.isTileWalkable(tile))
	continue nextTile; // The player is unable to walk here. Do not add this tile to the usable tiles list.
RSObject[] objects = Objects.getAt(tile);
if (objects.length > 0) {
	for (int i = 0; i < objects.length; i++) {
		RSObjectDefinition def = objects[i].getDefinition();
		if (def != null) {
			String name = def.getName();
			if (name != null)
				if (!name.equals("null")) // If the object has an actual name, other than "null" (fungus, flowers etc.)
					continue nextTile; // This tile is not usable. Do not add it to the usable tiles list.
		}
	}
	// Objects found on the tile, but they are named "null" and they are non-interactable
	usableTiles.add(tile); // This tile is usable and can be added to the list.
} else {
	// No objects found on the tile. This tile is usable and can be added to the list.
	usableTiles.add(tile);
}
  • I've commented the code so it's easy to understand what's happening.
  • Please note that the objects named "null" are not actually null.

Your usable tiles list will now contain tiles on which you can walk on and light a fire. Write an algorithm that finds multiple free tiles in a sequence, walk to the first tile and

RCvQlH3.gif

 

 

@HeyImJamie   🔥🚒🚒

  • Like 1

Share this post


Link to post
Share on other sites
6 hours ago, jkpker said:

Thank you Einstein for the reply and the commentary, i understand and really appreciate it!

You're welcome!

Feel free to tag me, so I'll get the notification @Einstein

 

7 hours ago, jkpker said:

Current method as reference:

First of all, the return type of your method should be void, because you're not getting any tile. This method is just compiling a list of usable tiles, which could then be used by another method to get a series of subsequent free tiles (10 free tiles in a row, for example), so you could make multiple fires. You could simply skip the list entirely and simply return a single usable tile, but this might not be very effective when you have to light more than one fire.

The radius of the area created around the player should be greater than 1.

 

7 hours ago, jkpker said:

My only question is about the nextTile, how does that variable work within the for loop? Because continue should work just fine within the for loop alone shouldn't it?

In this case, nextTile is not a variable, it's a label.

The unlabeled continue statement will skip the remaining code of the current iteration of a for, while or do-while loop for the innermost loop:

nHpWUA9.png

 

However, (line 14) if the name of the object is anything other than "null" (this is not null value, it's the string "null"), the tile is not usable. Therefore we don't need to continue reading the name of the next object found at that tile, because we already concluded that this tile is useless. So we use the labeled continue statement to continue with the next tile, jumping to this outer loop:

ILwUAax.png

Share this post


Link to post
Share on other sites

@Einstein

Thank you for the reply Einstein, i really appreciate the time and effort you put in to helping me!

The explanation is great, thank you. I understand the labeling now. 

Because of your explanation  instead of writing a method for a static amount, i started making a method for a single tile which can then be used for a different method to get multiple different tiles. For the consecutive line of 10, the approach i have in mind is:

- Get a list of all the tiles in the area( which are available).

- Create a hashmap where the key is 'x' + the x coordinate + the row number  or 'y' + y coordinate + the row number.

- For each tile, get the x and get the y.

- loop through every x -> start at the lowest y and y++, if RSTile != null && RSTile.length > 0 then add to hashmap where the key is the current coordinate type ('x') + the actual coordinate + row number.  else ++ row number(Making you basically create a new consecutive row)

- loop through every y -> start at the lowest x and x++, if RSTile != null && RSTile.length > 0 then add to hashmap where the key is the current coordinate type ('y') + the actual coordinate + row number.  else ++ row number(Making you basically create a new consecutive row)

- create x arrayList

- create y arrayList

- for each item in the hashmap of x if hashmap size is bigger than the x arraylist then add to x

- for each item in the hashmap of y if hashmap size is bigger than the y arraylist then add to y

if x is bigger return the RSTile arrayList of x

else if y is bigger return the RSTile arrayList of y

else return void;

 

Any thoughts on this approach?

  • Like 1

Share this post


Link to post
Share on other sites
1 hour ago, jkpker said:

Any thoughts on this approach?

 

This is the easiest solution I can think of right now:

private RSTile getGoodStartingTile() {
	nextTile: for (RSTile tile : usableTiles) {
		for (int i = 1; i < 10; i++)
			if (!usableTiles.contains(new RSTile(tile.getX() - i, tile.getY(), 0)))
				continue nextTile;
		return tile;
	}
	return null;
}

Call this after you cache the usable tiles. It should return the first tile of a sequence of 10 usable tiles.

Share this post


Link to post
Share on other sites

@jkpker

I ran the code and it seems to be working.

Here is searching for 10 subsequent free tiles:

FGYf715.png

 

Same fore 30:

XhDzeDU.png

 

Code:

Spoiler
private List<RSTile> usableTiles = new ArrayList<>();

private void compileList() {
	nextTile: for (RSTile tile : new RSArea(Player.getPosition(), 30).getAllTiles()) {
		if (!PathFinding.isTileWalkable(tile))
			continue;
		RSObject[] objects = Objects.getAt(tile);
		if (objects.length == 0) {
			usableTiles.add(tile);
		} else {
			for (int i = 0; i < objects.length; i++) {
				RSObjectDefinition def = objects[i].getDefinition();
				if (def != null) {
					String name = def.getName();
					if (name != null)
						if (!name.equals("null"))
							continue nextTile;
				}
			}
			usableTiles.add(tile);
		}
	}
}

private RSTile getGoodStartingTile() {
	nextTile: for (RSTile tile : usableTiles) {
		for (int i = 1; i <= 30; i++)
			if (!usableTiles.contains(new RSTile(tile.getX() - i, tile.getY(), 0)))
				continue nextTile;
		return tile;
	}
	return null;
}

 

 

  • Like 1

Share this post


Link to post
Share on other sites

@Einstein

That is amazing, thank you for the pointer!

I coded the current version with the State framework, it however became a bit messy because of it. 

I will remake it and use the node framework and incorporate this in there.

I will send you an update on how it goes once i'm done :)

  • Like 1

Share this post


Link to post
Share on other sites

@Einstein

After long debugging, this is what i came up with, do you mind giving some feedback?

package scripts.WoodCutter2.nodes;

import java.util.ArrayList;
import java.util.List;

import org.tribot.api.General;
import org.tribot.api2007.GameTab;
import org.tribot.api2007.Inventory;
import org.tribot.api2007.Objects;
import org.tribot.api2007.PathFinding;
import org.tribot.api2007.Player;
import org.tribot.api2007.types.RSArea;
import org.tribot.api2007.types.RSItem;
import org.tribot.api2007.types.RSObject;
import org.tribot.api2007.types.RSObjectDefinition;
import org.tribot.api2007.types.RSTile;


import scripts.Node;
import scripts.Timer;
import scripts.wait;

public class lightLogs extends Node {
	
	Timer time = new Timer(3000);
	wait wait = new wait();
	
	private final int LOG_ID = 1511;
	private final int TINDERBOX_ID = 590;
	
	private List<RSTile> usableTiles = new ArrayList<>();
	
	
	private void compileList(int x) {
		nextTile: for (RSTile tile : new RSArea(Player.getPosition(), x).getAllTiles()) {
			if(!PathFinding.canReach(tile, false))
				continue;
			if (!PathFinding.isTileWalkable(tile))
				continue;
			RSObject[] objects = Objects.getAt(tile);
			if (objects.length == 0) {
				usableTiles.add(tile);
			} else {
				for (int i = 0; i < objects.length; i++) {
					RSObjectDefinition def = objects[i].getDefinition();
					if (def != null) {
						String name = def.getName();
						if (name != null)
							if (!name.equals("null"))
								continue nextTile;
					}
				}
				usableTiles.add(tile);
			}
		}
	}

	private boolean checkTile(RSTile r) {//Checks for a specific tile.
		if(PathFinding.canReach(r, false)) {
			if (PathFinding.isTileWalkable(r)) {
				RSObject[] objects = Objects.getAt(r);
				if (objects.length == 0) {
					return true;
				} else {
					for (int i = 0; i < objects.length; i++) {
						RSObjectDefinition def = objects[i].getDefinition();
						if (def != null) {
							String name = def.getName();
							if (name != null)
								if (!name.equals("null"))
									return false;
						}
					}
					return true;
				}
			}
		}	
		return false;
	}
	
	private RSTile getGoodStartingTile() {
		nextTile: for (RSTile tile : usableTiles) {
			for (int i = 1; i <= 30; i++)
				if (!usableTiles.contains(new RSTile(tile.getX() - i, tile.getY(), 0)))
					continue nextTile;
			System.out.println("The starting tile is " + tile.getX() + tile.getY());
			return tile;
		}
		return null;
	}
	
	
	private boolean lightAllLogs() {
		RSItem[] tinderbox = Inventory.find(TINDERBOX_ID);// find tinderbox in inventory
		RSItem[] logs = Inventory.find(LOG_ID);// find logs in inventory
		final long timeout = System.currentTimeMillis() + General.random(90000, 120000);
		while(logs.length > 0 && tinderbox.length > 0 && System.currentTimeMillis() < timeout) {
			if(!checkTile(Player.getPosition())) {//if player tile isn't usable at the beginning, compile a list and get the first tile
				compileList(30);
				System.out.println("The current tile is not ok");
				PathFinding.aStarWalk(getGoodStartingTile());
				wait.waitUntilIdle();
			}
			else {
			if(isLighting()) //if already lighting, sleep
				General.sleep(100,150);
			else if(Player.isMoving())
				General.sleep(100,150);// if walking, sleep
			else {
				if(!GameTab.TABS.INVENTORY.isOpen())//if you don't have the inventory tob open, open it
					Inventory.open();
				if(tinderbox[0] != null)//light a log
				tinderbox[0].click("Use");
				if(logs[0] != null)
				logs[0].click("Use");
				time.reset();
				while(!isLighting() && time.isRunning()) {//dynamic sleep
					General.sleep(100,150);
					System.out.println("# of logs: " + logs.length);
				}	
				wait.waitUntilIdle();
			}
			logs = Inventory.find(LOG_ID);
		}
		}
		//return PathFinding.aStarWalk(getStartPosition(9));
		return true;
	}
	
	private boolean isLighting() {
		return Player.getAnimation() != -1;
	}

	@Override
	public void execute() {
		//System.out.println("light");
		lightAllLogs();
		wait.waitUntilIdle();
	}

	@Override
	public boolean validate() {
		if (Inventory.isFull() && !isLighting() && Player.isMoving())
			return true;
		return false;
	}
}

 

Share this post


Link to post
Share on other sites

@jkpker

 

Just a small hint:

The name of your class makes it look like a method. Java naming convention is to use camel case for methods (like you have done), but classes should be uppercase. I would suggest "LightLogs".

 

Nit picky, but thought you may want the advice nonetheless.

 

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

  • Our picks

    • This release will:

      Fix LG for both OSBuddy and RuneLite


      Fix issue where the resizable client isn't able to be made smaller (Thanks @JoeDezzy1)


      Fix detection of the logout game tab when resizable mode and side panels are enabled (Thanks @JoeDezzy1)


      Add initial support for Sentry to allow us to identify and easily debug exceptions happening with all TRiBot users


      Add methods to determine if the bank is actually loaded, and not just the overarching interface (Thanks @wastedbro)



      Upcoming updates:

      Improved CLI support


      Full Sentry support


      Much more
        • Like
      • 50 replies
    • This release will:

      Fix NPE in Camera API (Thanks @wastedbro)


      Update deposit box interface ids (Thanks @Encoded)


      Add various bank methods (Thanks @wastedbro)


      Banking#getWithdrawXQuantity


      Banking#getDefaultWithdrawQuantity


      Banking#arePlaceholdersOn




      Fix resizeable minimap bug (Thanks @wastedbro)


      Remove Java 8 requirement


      Please note: TRiBot is not yet fully compatible with Java 10+




      Fix the break handler issues by ensuring the break handler thread never gets paused


      Fix broken settings hooks



      Upcoming updates:

      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
        • Like
      • 68 replies
    • This release will:

      Add support for using custom F key bindings to switch between game tabs (Thanks @erickho123)


      Fix tab opening for "Skills" and "Kourend Tasks" (Thanks @erickho123)



      Note: If you are using LG, please restart both the RS client and TRiBot
        • Like
      • 34 replies
    • This release will:

      Fix an issue where breaks would stop firing


      Fix Combat#getWildernessLevel, use dynamic search for text and cache ID for later calls


      Fix an NPE in the Combat API


      Fix Mouse#leaveGame bug where the mouse wouldn't actually leave the game screen
        • Like
      • 21 replies
    • This release will:

      Add LG support for Runelite


      Fix NPCChat issues


      Fix a bug where the camera angle setter would just hold down a key for 5 seconds (the timeout)


      Slightly adjust the rotation via keys to be more accurate


      Add the ability for asynchronous camera movement via keys


      Make Camera rotation via mouse more fluid, with more antiban, and work much better in resizable mode


      Add a "Camera#setCamera" method, allowing the rotation and angle to be set in parallel


      Increase the likelihood of using the mouse for camera movements


      Add support for adjusting the camera to positionable entities (Positionable#adjustCameraTo)



      Upcoming updates:

      Improved CLI support


      Much more



      Note: If you are using LG, please restart both the RS client and TRiBot
        • Thanks
        • Like
      • 59 replies
  • Recently Browsing   0 members

    No registered users viewing this page.

×