Jump to content
View in the app

A better way to browse. Learn more.

OSBot :: 2007 OSRS Botting

A full-screen app on your home screen with push notifications, badges and more.

To install this app on iOS and iPadOS
  1. Tap the Share icon in Safari
  2. Scroll the menu and tap Add to Home Screen.
  3. Tap Add in the top-right corner.
To install this app on Android
  1. Tap the 3-dot menu (⋮) in the top-right corner of the browser.
  2. Tap Add to Home screen or Install app.
  3. Confirm by tapping Install.

MGFighter: Melee [Combat] [Simple]

Featured Replies

OSBot community,

 

This is my first bot script. I would like to thank Pug and Apaec. I followed your tutorials and learned from them. I used that knowledge to create this script that is probably badly coded, but I'm learning and I want to learn more. Here it goes:

 

Script Name: MGFighter: Melee

Features: 

  • Picks up and buries bones

  • Attacks NPCs (Currently only one and it is hardcoded in. I don't know how to add options and stuff like that through a menu)

  • How long it has been running for

  • In-Game Paint


 

As stated through the title of the script, this is meant to be only for melee. The reason stands behind the paint. It shows levels gained as well as XP gained per different combat and I could only fit melee ones along side prayer on there. 

 

I would really enjoy any criticism. If you have feedback about my code, I am all eyes and ears. There is always room to learn and I would like to become a great script developer.

 

Thank you,

Rutsy

----------------------------------------------------------

Here is my source code:

package osBotFightScript;

import org.osbot.rs07.api.model.GroundItem;
import org.osbot.rs07.api.model.Item;
import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.api.ui.Skill;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;

import java.io.IOException;
import java.net.URL;
import java.util.concurrent.TimeUnit;
import java.awt.*;

import javax.imageio.ImageIO;

@ScriptManifest(author = "Rutsy", info = "A Basic Melee Training Script.", name = "MGFighter: Melee", version = 0.1, logo = "")
public class main extends Script {
	private long timeBegan;
	private long timeRan;
	
	private int beginningXPAttack;
	private int beginningXPStrength;
	private int beginningXPDefence;
	private int beginningXPHitpoints;
	private int beginningXPPrayer;
	private int currentXPAttack;
	private int currentXPStrength;
	private int currentXPDefence;
	private int currentXPHitpoints;
	private int currentXPPrayer;
	private int xpGainedAttack;
	private int xpGainedDefence;
	private int xpGainedStrength;
	private int xpGainedHitpoints;
	private int xpGainedPrayer;
	
	private int currentLevelAttack;
	private int currentLevelDefence;
	private int currentLevelStrength;
	private int currentLevelHitpoints;
	private int currentLevelPrayer;
	private int beginningLevelAttack;
	private int beginningLevelDefence;
	private int beginningLevelStrength;
	private int beginningLevelHitpoints;
	private int beginningLevelPrayer;
	private int levelsGainedAttack;
	private int levelsGainedDefence;
	private int levelsGainedStrength;
	private int levelsGainedHitpoints;
	private int levelsGainedPrayer;
	
	private final Image bg = getImage("http://s27.postimg.org/8pkfefqjn/mgfighter_Background.png");

	//Image loading from PUG
	  private Image getImage(String url)
	  {
	    try
	    {
	      return ImageIO.read(new URL(url));
	    }
	    catch (IOException e) {}
	    return null;
	  }

	@Override
	public void onStart() {
		log("Welcome to MGFighter: Melee ~ By Rutsy!");
		timeBegan = System.currentTimeMillis();
		
		beginningXPAttack = skills.getExperience(Skill.ATTACK);
		beginningXPStrength = skills.getExperience(Skill.STRENGTH);
		beginningXPDefence = skills.getExperience(Skill.DEFENCE);
		beginningXPHitpoints = skills.getExperience(Skill.HITPOINTS);
		beginningXPPrayer = skills.getExperience(Skill.PRAYER);
		
		beginningLevelAttack = skills.getStatic(Skill.ATTACK);
		beginningLevelStrength = skills.getStatic(Skill.STRENGTH);
		beginningLevelDefence = skills.getStatic(Skill.DEFENCE);
		beginningLevelHitpoints = skills.getStatic(Skill.HITPOINTS);
		beginningLevelPrayer = skills.getStatic(Skill.PRAYER);

	}

	private enum State {
		KILL, WAIT, PICKUP, BURY
	};

	private State getState() {
		NPC goblin = npcs.closest("Goblin");
		GroundItem bones = groundItems.closest("Bones");
		if (goblin != null && !myPlayer().isAnimating() && !goblin.isUnderAttack())
			return State.KILL;
		if (bones != null && !myPlayer().isUnderAttack()) 
			return State.PICKUP;
		return State.WAIT;
	}

	@Override
	public int onLoop() throws InterruptedException {
		switch (getState()) {
		case PICKUP:
			GroundItem groundBones = groundItems.closest("Bones");
			Item bones = inventory.getItem("Bones");
			if ((!inventory.isFull() && !myPlayer().isUnderAttack())) {
				groundBones.interact("Take");
				bones.interact("Bury");
				sleep(random(300, 600));
			}
			break;
		case KILL:
			NPC goblin = npcs.closest("Goblin");
			if (goblin != null && !myPlayer().isAnimating() && !goblin.isUnderAttack()) {
				goblin.interact("Attack");
				sleep(random(800, 1000));
			}
			break;

		case WAIT:
			sleep(random(500, 700));
			break;
		}
		return random(200, 300);
	}

	@Override
	public void onExit() {
		log("Thanks for running MGFighter: Melee!");
	}

	@Override
	public void onPaint(Graphics2D g) {
			
			
            Graphics2D gr = g;
            //Background Image Loaded
            g.drawImage(bg, 2, 340, null);
            //Time Drawn on the Screen
            timeRan = System.currentTimeMillis() - this.timeBegan;
            g.drawString(ft(timeRan), 135, 404);
            
            //Drawing Numbers of the Screen
            currentXPAttack = skills.getExperience(Skill.ATTACK);
            xpGainedAttack = currentXPAttack - beginningXPAttack;
            currentLevelAttack = skills.getStatic(Skill.ATTACK);
            levelsGainedAttack = currentLevelAttack - beginningLevelAttack;
            g.drawString("" + xpGainedAttack + " (" + levelsGainedAttack + ")", 135, 435);
            
            currentXPDefence = skills.getExperience(Skill.DEFENCE);
            xpGainedDefence = currentXPDefence - beginningXPDefence;
            currentLevelDefence = skills.getStatic(Skill.DEFENCE);
            levelsGainedDefence = currentLevelDefence - beginningLevelDefence;
            g.drawString("" + xpGainedDefence + " (" + levelsGainedDefence + ")", 135, 467);
            
            currentXPStrength = skills.getExperience(Skill.STRENGTH);
            xpGainedStrength = currentXPStrength - beginningXPStrength;
            currentLevelStrength = skills.getStatic(Skill.STRENGTH);
            levelsGainedStrength = currentLevelStrength - beginningLevelStrength;
            g.drawString("" + xpGainedStrength + " (" + levelsGainedStrength + ")", 312, 467);
            
            currentXPHitpoints = skills.getExperience(Skill.HITPOINTS);
            xpGainedHitpoints = currentXPHitpoints - beginningXPHitpoints;
            currentLevelHitpoints = skills.getStatic(Skill.HITPOINTS);
            levelsGainedHitpoints = currentLevelHitpoints - beginningLevelHitpoints;
            g.drawString("" + xpGainedHitpoints + " (" + levelsGainedHitpoints + ")", 312, 435);
            
            currentXPPrayer = skills.getExperience(Skill.PRAYER);
            xpGainedPrayer = currentXPPrayer - beginningXPPrayer;
            currentLevelPrayer = skills.getStatic(Skill.PRAYER);
            levelsGainedPrayer = currentLevelPrayer - beginningLevelPrayer;
            g.drawString("" + xpGainedPrayer + " (" + levelsGainedPrayer + ")", 312, 404);
            
          }
	
	//Time conversion function from PUG
		private String ft(long duration) 
		{
			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;
		}
		
	}
 

Here is a screenshot:

If I could post images, it would have been easier. I apologize for having to click the image link.

Edited by Rutsy

Yay!

 

Congratulations on your first script!

 

If you are interested, I can teach you how to implement a GUI to your script (GUI = Graphic User Interface (i.e menu basically, not paint!)). 

 

I'm glad you found my tutorial helpful, all you have to do now is stay interested, and the more you code, the more familiar you get with the API and general java concepts. 

 

Ofcouse, if you have any questions, please don't hesitate to ask me them via PM, i'd be willing to help.

 

Apa

  • Author

Yay!

 

Congratulations on your first script!

 

If you are interested, I can teach you how to implement a GUI to your script (GUI = Graphic User Interface (i.e menu basically, not paint!)). 

 

I'm glad you found my tutorial helpful, all you have to do now is stay interested, and the more you code, the more familiar you get with the API and general java concepts. 

 

Ofcouse, if you have any questions, please don't hesitate to ask me them via PM, i'd be willing to help.

 

Apa

 

Thank you very much. I am really looking forward to gaining some experience on script development. I actually am interested in learning about GUI implementation, and yes I guess I meant pain on the screen. I'll edit that.

 

Thank you,

Rutsy

I've seen a lot of scripts and I can tell you that this one is really clean / easy to read, especially for a first one!

There are a few things that are redundant / could be more efficient but overall this is really nice :) Gratz!

  • Author

I've seen a lot of scripts and I can tell you that this one is really clean / easy to read, especially for a first one!

There are a few things that are redundant / could be more efficient but overall this is really nice smile.png Gratz!

 

That is great to hear! I will keep practicing. Could you state what is redundant and how it can be more efficient? It'll help me make better scripts in the future.

 

Thank you,

Rutsy

That is great to hear! I will keep practicing. Could you state what is redundant and how it can be more efficient? It'll help me make better scripts in the future.

 

Thank you,

Rutsy

 

Sure:

 

1. The WAIT state doesn't require a sleep, this just makes your script slower and less responsive which I wouldn't call desirable. I suggest you leave that state blank. Keep in mind every time the script loops it already sleeps for the onLoop()'s return value (in your case 200-300 ms).

 

2. Every time getState() is called you look for both the closest goblins and the closest bones.

I suggest you look first for the goblin to check if the KILL state is valid.

If the KILL state is not valid, then and only then look for the closest bones. Only try and get a value when that value is required.

Like so:

// mhm let's search the closest goblin to see if the KILL state is valid.
NPC goblin = npcs.closest("Goblin");
if (goblin != null && !myPlayer().isAnimating() && !goblin.isUnderAttack())
			return State.KILL;

// if the code reaches this point it means the KILL state isn't valid.
// what should I do next? mhm perhaps I should try and find the closest bones now.
GroundItem bones = groundItems.closest("Bones");
if (bones != null && !myPlayer().isUnderAttack()) 
			return State.PICKUP;

3. This one is also related to goblins and bones. I'm going to demonstrate the issue with the goblin case.

 

In your getState() you scan all NPCs and try to get the closest goblin, you then store the value of that goblin locally and when the method has finished the value is discarded.

 

Ok so a goblin was found, you are ready to kill but... you already forgot which one to kill (the previously locally stored value is already gone *sadface*). You rescan all NPCs again for the closest goblin and now you can finally attack it.

 

That's two scans for one goblin. If you were to store the closest goblin found in the getState() method in a global value then you could just re-use that value in your onLoop(), boom: one goblin, one scan.

 

4. These are small errors, you are doing a great job and you might not even notice the difference when fixing these inefficiencies ;)

  • Author

Sure:

 

1. The WAIT state doesn't require a sleep, this just makes your script slower and less responsive which I wouldn't call desirable. I suggest you leave that state blank. Keep in mind every time the script loops it already sleeps for the onLoop()'s return value (in your case 200-300 ms).

 

2. Every time getState() is called you look for both the closest goblins and the closest bones.

I suggest you look first for the goblin to check if the KILL state is valid.

If the KILL state is not valid, then and only then look for the closest bones. Only try and get a value when that value is required.

Like so:

// mhm let's search the closest goblin to see if the KILL state is valid.
NPC goblin = npcs.closest("Goblin");
if (goblin != null && !myPlayer().isAnimating() && !goblin.isUnderAttack())
			return State.KILL;

// if the code reaches this point it means the KILL state isn't valid.
// what should I do next? mhm perhaps I should try and find the closest bones now.
GroundItem bones = groundItems.closest("Bones");
if (bones != null && !myPlayer().isUnderAttack()) 
			return State.PICKUP;

3. This one is also related to goblins and bones. I'm going to demonstrate the issue with the goblin case.

 

In your getState() you scan all NPCs and try to get the closest goblin, you then store the value of that goblin locally and when the method has finished the value is discarded.

 

Ok so a goblin was found, you are ready to kill but... you already forgot which one to kill (the previously locally stored value is already gone *sadface*). You rescan all NPCs again for the closest goblin and now you can finally attack it.

 

That's two scans for one goblin. If you were to store the closest goblin found in the getState() method in a global value then you could just re-use that value in your onLoop(), boom: one goblin, one scan.

 

4. These are small errors, you are doing a great job and you might not even notice the difference when fixing these inefficiencies wink.png

I removed the sleep in the WAIT case. Could you teach me how to assign a global variable to the getState()'s goblin? 

 

Thank you,

Rutsy


//IMPORTS

public class main extends Script {

private NPC one_goblin_per_scan; // GLOBAL GOBLIN VARIABLE

private long timeBegan;

private long timeRan;

//...

private State getState() {

one_goblin_per_scan= npcs.closest("Goblin"); // STORE GOBLIN

// ...

}

@Override

public int onLoop() throws InterruptedException {

switch (getState()) {

//...

case KILL:

if (one_goblin_per_scan!= null && !myPlayer().isAnimating() && !(one_goblin_per_scan.isUnderAttack()) {

(one_goblin_per_scan.interact("Attack");

sleep(random(800, 1000));

//...

}

  • Author

 

//IMPORTS

public class main extends Script {
	
        private NPC one_goblin_per_scan; // GLOBAL GOBLIN VARIABLE
        private long timeBegan;
	private long timeRan;
	//...

	private State getState() {
		one_goblin_per_scan= npcs.closest("Goblin"); // STORE GOBLIN
		// ...
	}

	@Override
	public int onLoop() throws InterruptedException {
		switch (getState()) {
		//...
		case KILL:
			if (one_goblin_per_scan!= null && !myPlayer().isAnimating() && !(one_goblin_per_scan.isUnderAttack()) {
				(one_goblin_per_scan.interact("Attack");
				sleep(random(800, 1000));
//...
	}

I read what you placed down and implemented it into my code. Also, I fixed some errors. Here is my new code on the edited areas:

private NPC one_goblin_per_scan;
//...

	private State getState() {
		one_goblin_per_scan = npcs.closest("Goblin");
		if (one_goblin_per_scan!= null && !myPlayer().isAnimating() && !(one_goblin_per_scan.isUnderAttack()))
			return State.KILL;
		
		GroundItem bones = groundItems.closest("Bones");
		if (bones != null && !myPlayer().isUnderAttack()) 
			return State.PICKUP;
		
		return State.WAIT;
	}


		case KILL:
			if (one_goblin_per_scan!= null && !myPlayer().isAnimating() && !(one_goblin_per_scan.isUnderAttack())) {
				one_goblin_per_scan.interact("Attack");
				sleep(random(800, 1000));
			}
			break;

		case WAIT:
			//Removed the timer in the WAIT case
			break; //Credits also to Botre

What do you think?

 

Thank you,

Rutsy

Edited by Rutsy

  • Author

Yes looks good, I recommend you do the same for the bones biggrin.png

cheers

This is what I did for the bones:

	private GroundItem one_bone_per_scan;

		one_bone_per_scan = groundItems.closest("Bones");
		if (one_bone_per_scan != null && !myPlayer().isUnderAttack()) 
			return State.PICKUP;

		case PICKUP:
			Item bones = inventory.getItem("Bones");
			if ((!inventory.isFull() && !myPlayer().isUnderAttack())) {
				one_bone_per_scan.interact("Take");
				bones.interact("Bury");
				sleep(random(300, 600));
			}
			break; 

Is it better now?

 

Thank you,

Rutsy

Recently Browsing 0

  • No registered users viewing this page.

Account

Navigation

Search

Configure browser push notifications

Chrome (Android)
  1. Tap the lock icon next to the address bar.
  2. Tap Permissions → Notifications.
  3. Adjust your preference.
Chrome (Desktop)
  1. Click the padlock icon in the address bar.
  2. Select Site settings.
  3. Find Notifications and adjust your preference.