Jump to content
TRiLeZ

TRiLeZ's Scripting Tutorial

Recommended Posts

Ty for putting effort into this to try and teach us!!

 

I have been reading up on scripting all day and been staring at this script for a long time now :P

And something is unclear to me and I hope that you or someone else can explain this to me, would really appreciate it.

 

In the example you gave us at the end, line 383-416 is this the place where the script starts?

 

First sleeps 50 miliseconds

then jumps to isAtTrees,

Returns to line 390

Jumps Inventory.isFull,

Etc

 

 

If this is true why is this at the bottom? :P 

I have 0 experience with java scripting so please explain it to me like i am a 8 year old.

 

 

@Override
public void run() {
while (true) {
sleep(50);
 
if (isAtTrees()) { // We are at the trees
// Time to check what to do. If the inventory is full, we should
// walk to the bank. Otherwise, we should cut the willows.
if (Inventory.isFull()) { // The inventory is full
walkToBank(); // Let's walk to the bank
} else
// The inventory is not full
cut(); // Let's cut the willows.
} else if (isInBank()) { // We are at the bank
// Time to check what to do. If the inventory is full, we should
// bank the items. Otherwise, we should walk back to the trees.
if (Inventory.isFull()) // The inventory is full
bank(); // Let's bank the items
else { // The inventory is not full
walkToTrees(); // Let's walk to the trees.
}
} else { // We are neither in the bank, nor at the willows
// Time to check what to do. If the inventory is full, we will
// walk to the bank. Otherwise, we will walk to the willows.
if (Inventory.isFull()) // Inventory is full
walkToBank(); // Walk to the bank
else
// Inventory is not full
walkToTrees(); // Walk to the trees.
}
}
}
 
}
 
 
 
 

 

 

Share this post


Link to post
Share on other sites
On 5/28/2016 at 4:57 PM, xmaxing said:

Can anyone update this with properly formatted code? This is a bloody mess. Single line code with // comments is NOT a good idea.

The single line is an issue from when the forums updated. Any pre-existing code was put onto a single line.

Share this post


Link to post
Share on other sites

So I'm a comp sci major and would love to try to start making scripts for osrs and the above tutorial makes perfect sense to me. I was wondering if anyone has advice as far as formatting scripts (whether to use a bunch of conditionals or if implementing a FSM would work better?) or if there are different types of scripts that are better for FSM such as a power mining script?

 

 

Share this post


Link to post
Share on other sites

@TRiLeZ Hi would like to lean how to script for Tribot but im a complete noob. I know the osrs game well and im an experienced botter but have no knowledge of Java. How long would it take me to get up to the level to write premium ABC2 scripts? And where should I start? 

Edited by idkfa
  • Like 1

Share this post


Link to post
Share on other sites

I've been trying to follow up on this scripting, I understand most bits. I just got this thing that I do not know how to deal with.

 

if (this.last_tree_tile != null) {

 

The last_tree_tile has never been declared anywhere and so it shows in red in my intellij. What can I do for this? Do i need to declare last_tree_tile = 3938; for example? or how does this work and where do we place this?

Share this post


Link to post
Share on other sites

@vibis Because when the script starts there is no such thing as a last tree tile so you initialize it to null. last_tree_tile refers to the Tile of the last tree being cut. I think you may be getting last_tree_tile mixed up with tree id which is just an int. last_tree_tile is a Tile which has a position and defines a unique tree as apposed to a tree id which just refers to a tree type like a willow tree.

Edited by dirtbikr88

Share this post


Link to post
Share on other sites
12 minutes ago, dirtbikr88 said:

@vibis Because when the script starts there is no such thing as a last tree tile so you initialize it to null. last_tree_tile refers to the Tile of the last tree being cut. I think you may be getting last_tree_tile mixed up with tree id which is just an int. last_tree_tile is a Tile which has a position and defines a unique tree as apposed to a tree id which just refers to a tree type like a willow tree.

ah thanks cleared that up for me! Now looking into a paint tutorial, anyone know any?

Share this post


Link to post
Share on other sites
On 2/9/2014 at 3:19 AM, TRiLeZ said:

 

6. Things to Check For

  • NullPointerException (NPEs)
    • These occur when a variable is null, and you try to perform an action (other than a null check) on that variable.
    • They are simple to prevent. The API will state whether or not null is a possible result of the API method. If the method can return null, you need to:
      • Store the returned value in a variable.
      • Null check that variable. If not null, you can perform actions upon it.
      • Null checking is like so: if (variable == null) //Oh no. The variable is null. Let's not perform any action upon it.
      • Note: theMethod() != theMethod()
        • Values returned by methods may not always be the same. The first could be not null, and the second could be null.
        • Do not null check the return of a method unless you store that returned value in a variable, then null check that variable.
        • Example:
        •  
          if (object.getDefinition() != null) {
           final String name = object.getDefinition().getName();
          }

           

        • The first call to getDefinition() may not result in a null returned value, and would pass the null check. The second call to getDefinition() could return null, resulting in an NPE. In this case, the returned value of getDefinition() should be stored in a variable. That variable should then be null checked. After the null check is passed, getName() can be called upon that variable.
  • IndexOutOfBoundsException
    • This occurs when you try to load an element from an array which is not within the bounds of the array. This exception is thrown when an array element is loaded from from index such that:
      • index < 0
      • index >= array.length
    • Always make sure to check the length of the array before trying to grab an array element at an index. Also, never try grabbing an array element at a negative index. Negative indices don't exist.
    • Index checking is simple:
      •  
        if (index >= 0 && index < array.length) {	//The index is within the bounds of the array.
                                                    //We can pull the value of array[index] now.
        }

         

      • Sometimes checking index >= 0 isn't necessary if you already know index isn't negative.
  • Infinite Loops
    • Infinite loops occur when a thread never exits a loop. Typically, these are while loops. Make sure to use a timeout on loops to prevent this.
  • Inefficient Coding
    • There exists so many possibilities which inefficient code can exist. I'll give just a few pointers:
      • In while loops (sometimes also other types of loops), make sure to include a sleep at the top of the loop. If the loop contains no sleeps, it will execute the code of the loop as much as possible, and as fast as possible. The loop will use as much CPU power as it is able to. Avoid this.
      • Store returned values from methods in variable if you are going to use the value twice. You may already need to store the value in a variable to do a null check anyways.
      • If you are waiting for a condition, make sure to use appropriate sleeps.
        • If you don't need to perform an action immediately after a different action, or if a few hundred milliseconds doesn't harm the outcome of whatever you are doing, use a larger sleep rather than a smaller one. Larger waits will reduce CPU usage.
      • When using object finding, doing set the tile radius too large. If an object is expected to be within 10-20 tiles of your character, don't search for the object with a radius of 60 (unless there is a reason to).
      • Don't define all the needed variables of a method all at once. Define them one at a time, then inspect the variable. You may not need to use all of the variable before coming to a conclusion.

7. Bug Fixing

  • A lot of scripters here haven't quite yet grasped the concept of bug finding and fixing, so here we go.
  • First, you have to identify the problem. Let's create an example... the script isn't clicking on the oven (cooking script).
  • Next, you have to identify the code that is responsible for performing the action which isn't being performed. In our example, we have to find the piece of code that clicks the oven.
  • Next, try doing a brief scan of your code and see if you can find any obvious logic errors.
  • If weren't able to solve the bug with a brief scan, then try debugging code. Here's what I suggest: using println. Use println to determine if a section of code is being executed or not. If it's not being executed, try to find where the execution cuts off. Find the exact position where the execution cuts off.
    • This cut off will likely help you fix the bug. Identify why the execution cuts off at where it does, then fix it.
  • You will probably also have to check variables. Check all variables, and all method return values in suspect. The way you check variable is you println their value(s).
  • In our example, we should have inserted printlns to make sure our oven clicking method was being hit, and we should have checked the variables involved in clicking the oven.
  • That's the gist of bug fixing. Think about what is going wrong, what code is responsible, and why the code is failing. Println everything.

 

  Reveal hidden contents

package scripts;
import org.tribot.api.DynamicClicking;
import org.tribot.api.General;
import org.tribot.api.Timing;
import org.tribot.api.types.generic.Condition;
import org.tribot.api2007.Banking;
import org.tribot.api2007.Inventory;
import org.tribot.api2007.NPCs;
import org.tribot.api2007.Objects;
import org.tribot.api2007.Player;
import org.tribot.api2007.Walking;
import org.tribot.api2007.WebWalking;
import org.tribot.api2007.types.RSNPC;
import org.tribot.api2007.types.RSObject;
import org.tribot.api2007.types.RSTile;
import org.tribot.script.Script;

public class TutorialScript extends Script {

	private RSTile last_tree_tile = null;

	/**	 
	 * Checks if we are at the trees.
	 * 	
	 * @return True if we are at the trees; false otherwise.	
	 */
	private boolean isAtTrees() {
		// We search for the trees by their name - Willow. The means that we	
		// will search for the trees within a radius of 20 tiles from our	
		// character. If they are more than 20 tiles away, the findNearest
		// method will not find them. Although, if they are more than 20 tiles
		// away, we can be sure that they aren't on the screen.	
		// We will now store the variable returned form findNearest in the	
		// variable called 'willows'. We declare this variable final because we	
		// will not be changing it's contents after the variable is set.
		// According to the API, the returned value from findNearest will be
		// RSObject[]. If there are no trees found, the array will not contain
		// any elements. The returned value cannot be null, and therefore we
		// don't have to null check it.		
		// Next, we check the length of the array. If the length is less than 1,	
		// we know that no trees were found. We can now return false.
		final RSObject[] willows = Objects.findNearest(20, "Willow");
		if (willows.length < 1)
			return false;
		// The array contains at least one element. The first element in the
		// array will be the nearest tree to our character. Let's check if this
		// tree is on screen. We will return the value.	
		return willows[0].isOnScreen();
	}

	/**	 
	 * Checks if we are in the bank.	
	 * 	
	 * @return True if we are in the bank; false otherwise.	
	 */
	private boolean isInBank() {
		// Let's first search for on-screen booths.	
		final RSObject[] booths = Objects.findNearest(20, "Bank booth");
		if (booths.length > 1) { // A booth is in the array. Let's check if the first element of the		
			// array is on the screen.		
			if (booths[0].isOnScreen())
				return true;
			// The booth is on the screen. We don't need to
			// check for visible bankers since we already know	
			// that we are in the bank. Let's exit this method	
			// and return true.			
		}

		// Nope, the nearest booth is no visible. Let's go and and search	
		// for bankers.		
		final RSNPC[] bankers = NPCs.findNearest("Banker");
		if (bankers.length < 1)
			return false; // No booths are on the screen, and no bankers exist.	
		// Let's just exit already since we know that we are		
		// not in the bank. We will return false.	

		// Okay, so we found a banker. The first element in the array is the	
		// nearest NPC. Let's check if that NPC is on-screen.	
		return bankers[0].isOnScreen(); // Return whether or not the banker is on	
		// the screen. If it is, we are in the			
		// bank; if not, then we are not in the		
		// bank.
	}

	/**	 
	 * Attempts to cut a tree. If we are already cutting a tree, we will wait	 
	 * until that tree has been cut.	 
	 * 	 
	 * @return True if we were able to cut the tree; false otherwise.	 
	 */
	private boolean cut() {
		if (isCutting()) {
			final long timeout = System.currentTimeMillis() + General.random(60000, 90000); // Let's define a timeout for the loop below. If we don't have a
			// timeout, it is possible that the script will enter an infinite
			// loop, and will therefore be stuck. We set the timeout for the
			// current time plus somewhere between 60 and 90 seconds. We use
			// randomness to avoid seeming bot-like.
			while (isCutting() && System.currentTimeMillis() < timeout) {
				sleep(100, 150); // We will loop while we are cutting, and while the current time			
				// is before the timeout. Make sure to have a sleep to prevent a				// CPU overload.				
				// We could also implement some anti-ban features here if we	
				// want.			
				// Now, let's check if the willow tree is still at the location	
				// of the last clicked location. To do this, we will define a	
				// global variable - last_tree_tile - of type RSTile. The	
				// variable will be defined below, when we find and click a	
				// tree.			
				// Make sure to null check the variable, since it can be null.
				// If it is null and we try to perform actions upon it, a Null	
				// Pointer Exception will be thrown, crashing the script.	
				if (this.last_tree_tile != null) {
					// The variable is not null. We can use it now.			
					if (!Objects.isAt(this.last_tree_tile, "Willow")) {
						// The willow tree is gone. It has either been chopped		
						// down, or turned into an ent. Let's break out of this		
						// loop.	
						break; // Good-bye loop	
					}
				}
			}
		}
		// Let's go find a tree to chop.
		final RSObject[] trees = Objects.findNearest(50, "Willow");
		// Search for the willow within 50	tiles
		// from our character.		
		if (trees.length < 1)
			return false; // No trees have been found. We can't do anything, so	
		// let's exit this method.

		if (!trees[0].isOnScreen()) {
			// The nearest tree is not on the screen. Let's walk to it.	
			if (!Walking.walkPath(Walking.generateStraightPath(trees[0]))) // We could not walk to the tree. Let's exit so we don't try	
				// clicking a tree which isn't on screen.
				return false;

			if (!Timing.waitCondition(new Condition() { // We will now use the Timing API to wait until the tree is on	
				// the screen (we are probably walking to the tree right now).	
				@Override
				public boolean active() {
					General.sleep(100); // Sleep to reduce CPU usage.
					return trees[0].isOnScreen();
				}
			}, General.random(8000, 9300)))
				// A tree could not be found before the timeout of 8-9.3	
				// seconds. Let's exit the method and return false. we don't		
				// want to end up trying to click a tree which isn't on the
				// screen.		
				return false;
		}
		// Okay, now we are sure trees[0] is on-screen. Let's click it. We may	
		// be still moving at this moment, so let's use DynamicClicking.		
		// DynamicClicking should be used when your character is moving, or the	
		// target is moving, and you need to click the target.	
		if (!DynamicClicking.clickRSObject(trees[0], "Chop down")) // We could not click the tree. Let's exit the method since we		
			// failed.
			return false;
		// We clicked the tree. Let's first wait to stop chopping for 1-1.2	
		// seconds just in case we moved on to this tree while still performing		
		// the chopping animation.	
		Timing.waitCondition(new Condition() {
			@Override
			public boolean active() {
				return !isCutting();
			}
		}, General.random(1000, 1200));
		// We don't need to if check it since the result doesn't matter.		
		if (Timing.waitCondition(new Condition() {
			// Now let's wait until we are cutting.			
			@Override
			public boolean active() {
				return isCutting();
			}
		}, General.random(8000, 9000))) {
			// We are cutting! Now let's record the tree's tile and return true.			
			this.last_tree_tile = trees[0].getPosition().clone(); // getPosition() can never be null, so we don't need to null check		
			// it.		
			return true;
		}
		// We failed to cut a tree. Return false.	
		return false;
	}

	/**	 
	 * Checks if we are cutting a tree.	
	 * 	 
	 * @return True if were are cutting a tree; false otherwise.	
	 */
	private boolean isCutting() {
		return Player.getAnimation() > 0; // If the animation ID is greater than			
		// 0, then we are animating. Let's		
		// assume that if were are							
		// animating, that the animation is		
		// the chopping one.	
	}

	/**	 
	 * Attempts to walk to the bank.	
	 * 	 
	 * @return True if we were able to walk to the bank; false otherwise.	 
	 */
	private boolean walkToBank() {
		if (!WebWalking.walkToBank()) { // We failed to walk to the bank. Let's return false.	
			return false;
		}
		// Walking succeeded, but we may still be moving, and not our destination	
		// yet. Let's wait until we are in the bank.	
		return Timing.waitCondition(new Condition() { // If we reach the bank before the timeout, this method will return		
			// true. Otherwise, it will return false.			
			@Override public boolean active() {
				General.sleep(200, 300); // Reduces CPU usage.		
				return isInBank();
			}
		}, General.random(8000, 9000));
	}

	/**	
	 * Attempts to walk to the trees.	
	 * 	
	 * @return True if we were able to walk to the trees; false otherwise.
	 */
	private boolean walkToTrees() {
		final RSObject[] willows = Objects.findNearest(50, "Willow");
		if (willows.length < 1) // No willows could be found. We cannot do anything. Let's exit this		
			// method.		
			return false;
		// Let's walk to the closest willow tree now.	
		if (!WebWalking.walkTo(willows[0]))
			// We failed to walk to the bank. Let's return false.	
			return false;
		// Walking failed, but we may still be moving, and not our destination	
		// yet. Let's wait until we are at the trees.		
		return Timing.waitCondition(new Condition() { // If we reach the trees before the timeout, this method will return	
			// true. Otherwise, it will return false.	
			@Override public boolean active() {
				General.sleep(200, 300); // Reduces CPU usage.	
				return isAtTrees();
			}
		}, General.random(8000, 9000));
	}

	/**	 
	 * Attempts to bank our items.
	 * 	
	 * @return True if we were successfully able to bank the items;
	 * false otherwise.         
	 */
	private boolean bank() {
		if (!Banking.isBankScreenOpen()) { // The bank screen is not open. Let's open it.		
			if (!Banking.openBank())
				// Could not open the bank. Let's return false.		
				return false;
			// Since openBank() will wait for the bank screen to be open before	
			// returning true, it is safe to assume that the bank screen is now		
			// open.		
		}
		// Now let's deposit the logs. We will check if an axe is in our	
		// inventory. If there is one, we will bank by using our inventory	
		// items. Otherwise, we will just click the deposit all button.	
		// Let's define our axe names now. It is better to define variables like	
		// this globally, but we only use the axe names within this method, so I	
		// don't feel the need to.		
		final String[] axe_names = {
				"Bronze axe",
				"Iron Axe",
				"Black Axe",
				"Steel Axe",
				"Mithril Axe",
				"Adamant Axe",
				"Rune Axe",
				"Dragon Axe"
		};
		if (Inventory.find(axe_names).length > 0) { // If the length of the returned value if greater than one, that		
			// means we have an axe in our inventory.	
			if (Banking.depositAllExcept(axe_names) < 1)
				// We failed to deposit our items. Let's exit and return false.		
				return false;
		} else {
			if (Banking.depositAll() < 1)
				// We failed to click the deposit all button. Let's exit and				// return false.	
				return false;
		}
		// Okay, our items should get deposited. Let's wait and make sure they
		// get deposited.		
		return Timing.waitCondition(new Condition() { // Since we can only enter the bank method if our inventory is full,	
			// let's wait until our inventory is not full. If it is not full	
			// before the timeout, return true. Otherwise, return false.		
			@Override
			public boolean active() {
				return !Inventory.isFull();
			}
		}, General.random(3000, 4000));
	}


	@Override
	public void run() {
		while (true) {
			sleep(50);
			if (isAtTrees()) { // We are at the trees		
				// Time to check what to do. If the inventory is full, we should	
				// walk to the bank. Otherwise, we should cut the willows.	
				if (Inventory.isFull()) { // The inventory is full	
					walkToBank(); // Let's walk to the bank			
				} else // The inventory is not full	
					cut(); // Let's cut the willows.	
			} else if (isInBank()) { // We are at the bank	
				// Time to check what to do. If the inventory is full, we should	
				// bank the items. Otherwise, we should walk back to the trees.		
				if (Inventory.isFull()) // The inventory is full		
					bank(); // Let's bank the items		
				else  // The inventory is not full	
					walkToTrees(); // Let's walk to the trees.		
			} else { // We are neither in the bank, nor at the willows		
				// Time to check what to do. If the inventory is full, we will	
				// walk to the bank. Otherwise, we will walk to the willows.	
				if (Inventory.isFull()) // Inventory is full		
					walkToBank(); // Walk to the bank			
				else // Inventory is not full		
					walkToTrees(); // Walk to the trees.	
			}
		}
	}
}

This thread is an effing life saver. Especially this piece here. Bless you TrileZ.

  • Like 1

Share this post


Link to post
Share on other sites

If you can pay or have authentication to do so, through work/school, I would highly recommend using Intellij as the IDE instead of eclipse. Eclipse is good software but have ran into a few major bugs in eclipse. One being sometimes setting the path to an imported library renders the whole project with an error that doesn't exist.

 

Debugging is made much easier with intellij for instance not having to highlight the whole expression to have it evaluated.

Much better auto-complete that only suggests valid argument/parameter

Refactoring is much more intelligent with name suggestions.

 

If you cant, its not a big deal. Eclipse is a great free open-source IDE. Intellij will just make it a bit easier.

 

Goodluck all

Share this post


Link to post
Share on other sites

Not sure where this should be reported to:

Although it seems self explanatory, I figured it wouldn't hurt to create awareness. In the documentation in the ABCUtil class in org.tribot.api.util.abc (the top ABCUtil link) the run() method doesn't have any provided documentation.

Thank you,

Andrew M Williams

 

runmethod.png.9cba1fed0666268b7768066de1aa1ff1.png

 

 

Edited by Willington

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


  • Recently Browsing   0 members

    No registered users viewing this page.

×