Skip to content

Instantly share code, notes, and snippets.

@battleguard
Created July 14, 2012 06:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save battleguard/3109764 to your computer and use it in GitHub Desktop.
Save battleguard/3109764 to your computer and use it in GitHub Desktop.
Alchs all the items you select. No messing with ids. Automatically sets up alch spot for you!
import org.powerbot.core.event.events.MessageEvent;
import org.powerbot.core.event.listeners.MessageListener;
import org.powerbot.core.event.listeners.PaintListener;
import org.powerbot.core.script.ActiveScript;
import org.powerbot.core.script.job.Task;
import org.powerbot.core.script.job.state.Node;
import org.powerbot.game.api.Manifest;
import org.powerbot.game.api.methods.Game;
import org.powerbot.game.api.methods.Tabs;
import org.powerbot.game.api.methods.Widgets;
import org.powerbot.game.api.methods.input.Mouse;
import org.powerbot.game.api.methods.tab.Inventory;
import org.powerbot.game.api.methods.tab.Skills;
import org.powerbot.game.api.methods.widget.Camera;
import org.powerbot.game.api.methods.widget.Lobby;
import org.powerbot.game.api.util.Filter;
import org.powerbot.game.api.util.Random;
import org.powerbot.game.api.util.SkillData;
import org.powerbot.game.api.util.Time;
import org.powerbot.game.api.util.Timer;
import org.powerbot.game.api.wrappers.node.Item;
import org.powerbot.game.api.wrappers.widget.WidgetChild;
import javax.imageio.ImageIO;
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.util.ArrayList;
@Manifest(name = "The Best Alcher v3.2", authors = { "Battleguard, Logicail" }, description= "Magic: Alchs all the items you select. No messing with ids. Automatically sets up alch spot for you!", version=3.2, website="http://www.powerbot.org/community/topic/733464-the-best-alcher-alchs-all-selected-items-no-ids-required-sets-up-items-for-you/")
public class TheBestAlcher extends ActiveScript implements PaintListener, MessageListener, MouseListener {
private static Timer runTime;
private static Timer lastAlch = new Timer(0);
private static Rectangle ALCH_REC, ITEM_SPOT_REC, HIGH_ALCH_SPELL_REC;
private static Point ALCH_PNT;
private static int START_XP = 0, START_LVL = 0;
private static final ArrayList<Item> goodItems = new ArrayList<Item>();
private static AlchGui gui;
private static boolean runPaint = false, highalch;
private static int tries = 0;
private String version;
@Override
public void onStart() {
version = "v" + this.getClass().getAnnotation(Manifest.class).version();
System.setProperty("http.agent", "");
getAlchList();
getContainer().submit(new ImageLoader());
getContainer().submit(new PriceLoader());
gui = new AlchGui();
};
private void startScript() {
jobs = new Node[] { new Restart(), new Alch(), new Cam() };
runPaint = true;
runTime = new Timer(0);
}
private Node[] jobs;
@Override
public int loop() {
if(jobs == null) return 50;
for (Node curJob : jobs) {
if(curJob.activate()) {
curJob.execute();
break;
}
}
return 50;
}
private static final Filter<Item> alchFilter = new Filter<Item>() {
public boolean accept(Item item) {
if (!item.getName().contains(" rune") && item.getStackSize() > 10) {
goodItems.add(item);
}
return false;
}
};
private void getAlchList() {
Tabs.INVENTORY.open();
Inventory.getItems(alchFilter);
itemCheckbox = new JCheckBox[goodItems.size()];
itemImages = new ImageIcon[goodItems.size()];
itemProfits = new JLabel[goodItems.size()];
for (int i = 0; i < goodItems.size(); i++) {
itemCheckbox[i] = new JCheckBox(goodItems.get(i).getName());
}
}
private class PriceLoader extends Task {
@Override
public void execute() {
int naturePrice;
try {
naturePrice = Integer.parseInt(lookup(561, false)[1]);
System.out.println("Nature Price: " + naturePrice);
} catch (Exception e) {
System.out.println("Failed to load nature rune price");
return;
}
for (int i = 0; i < itemImages.length; i++) {
try {
System.out.println("Nature rune price: " + naturePrice);
final String[] info = lookup(goodItems.get(i).getId(), false);
System.out.println("Alch: " + info[2] + " GE: " + info[1]);
final int alch = Integer.parseInt(info[2]) - Integer.parseInt(info[1]);
System.out.println("Alch - buyprice: " + alch);
final int profit = alch - naturePrice;
itemProfits[i] = new JLabel("" + profit + "gp");
itemProfits[i].setForeground(profit > 0 ? Color.green : Color.red);
} catch (Exception e) {
System.out.println("Failed to get alch profit on: " + goodItems.get(i).getName());
continue;
}
gui.draw();
}
}
}
private class ImageLoader extends Task {
@Override
public void execute() {
for (int i = 0; i < itemImages.length; i++) {
itemImages[i] = getItemImage(goodItems.get(i).getId());
gui.draw();
}
}
}
private class Restart extends Node {
@Override
public boolean activate() {
return Game.isLoggedIn() && Game.getClientState() == Game.INDEX_MAP_LOADED && !Lobby.isOpen()
&& (!lastAlch.isRunning() || (Tabs.INVENTORY.isOpen() && Inventory.getCount(goodItems.get(0).getId()) == 0));
}
@Override
public void execute() {
try {
System.out.println("resetting alch");
if (getOverlap()) {
Tabs.MAGIC.open();
Mouse.move(ALCH_PNT.x, ALCH_PNT.y);
lastAlch = new Timer(5000);
}
} catch (Exception e) {
e.printStackTrace();
System.out.println("showing error message");
if(!ACTIVE) {
new ErrorMessageGUI(e);
}
}
}
}
private int getBestSlot() throws Exception {
Dimension bestRec = new Dimension(0, 0);
final WidgetChild inv = Inventory.getWidget(false);
int idx = 0;
for (int i = 0; i < 28; i++) {
final Rectangle rec = inv.getChild(i).getBoundingRectangle().intersection(HIGH_ALCH_SPELL_REC);
if (!rec.isEmpty() && rec.width * rec.height > bestRec.width * bestRec.height) {
bestRec = rec.getSize();
idx = i;
}
}
return idx;
}
private boolean checkInventory = false;
private boolean isWieldable(final Item curItem) throws Exception {
if (curItem == null) return false;
final String[] actions = curItem.getWidgetChild().getActions();
if (actions != null) {
for (String action : actions) {
if (action != null && action.startsWith("Wield")) return true;
}
}
return false;
}
private void checkEquipped() throws Exception {
Task.sleep(500);
Tabs.EQUIPMENT.open();
Task.sleep(1000);
final WidgetChild arrow = Widgets.get(387, 37);
if(arrow != null && arrow.getChildId() == goodItems.get(0).getId()) {
arrow.click(true);
Task.sleep(1000);
Tabs.INVENTORY.open();
return;
}
}
private boolean getOverlap() throws Exception {
if(goodItems.isEmpty()) {
stop();
return false;
}
if (tries >= 5) {
goodItems.remove(0);
tries = 0;
return false;
}
Tabs.INVENTORY.open();
Task.sleep(500);
final Item curItem = Inventory.getItem(goodItems.get(0).getId());
if(curItem == null) {
if(checkInventory) {
checkEquipped();
}
tries++;
return false;
}
checkInventory = isWieldable(curItem);
ITEM_SPOT_REC = curItem.getWidgetChild().getBoundingRectangle();
Tabs.MAGIC.open();
Task.sleep(500);
HIGH_ALCH_SPELL_REC = Widgets.get(192, highalch ? 59 : 38).getBoundingRectangle();
ALCH_REC = ITEM_SPOT_REC.intersection(HIGH_ALCH_SPELL_REC);
if (ALCH_REC.isEmpty()) {
Tabs.INVENTORY.open();
final Rectangle rec = Inventory.getWidget(false).getChild(getBestSlot()).getBoundingRectangle();
curItem.getWidgetChild().interact("Use");
Task.sleep(500, 1000);
Mouse.move((int) ITEM_SPOT_REC.getCenterX(), (int) ITEM_SPOT_REC.getCenterY());
Task.sleep(500, 1000);
Mouse.drag((int) rec.getCenterX(), (int) rec.getCenterY());
Task.sleep(500, 1000);
tries++;
return false;
}
ALCH_PNT = new Point((int) ALCH_REC.getCenterX(), (int) ALCH_REC.getCenterY());
tries = 0;
return true;
}
public class Alch extends Node {
public Point getNextClickSpot() throws Exception {
int x = Mouse.getX();
int y = Mouse.getY();
x -= (x > (int) ALCH_REC.getCenterX() ? 10 : 5);
y -= (y > (int) ALCH_REC.getCenterY() ? 10 : 5);
return new Point(Random.nextGaussian(x, x + 15, 1), Random.nextGaussian(y, y + 15, 1));
}
@Override
public boolean activate() {
return Game.isLoggedIn() && !Lobby.isOpen() && Tabs.MAGIC.isOpen();
}
@Override
public void execute() {
try {
if (antiBan) {
Task.sleep(100, 450);
final Point p = getNextClickSpot();
if (ALCH_REC.contains(p)) {
Mouse.move(p);
}
}
if (!ALCH_REC.contains(Mouse.getLocation())) {
Mouse.hop(ALCH_PNT.x, ALCH_PNT.y);
}
Mouse.click(true);
Task.sleep(60, 120);
Mouse.click(true);
lastAlch.reset();
} catch (Exception e) {
e.printStackTrace();
if(!ACTIVE) {
System.out.println("showing error message");
new ErrorMessageGUI(e);
}
}
}
}
private class Cam extends Node {
final Timer timer = new Timer(Random.nextInt(60, 180) * 1000);
@Override
public boolean activate() {
return Game.isLoggedIn() && !Lobby.isOpen() && !timer.isRunning();
}
@Override
public void execute() {
Camera.setPitch(Random.nextInt(10, 90));
Camera.setAngle(Random.nextInt(340, 380) % 360);
timer.setEndIn(Random.nextInt(60, 180) * 1000);
}
}
private final static NumberFormat k = new DecimalFormat("###,###,###");
private final static Color OPAQUE_BLACK = new Color(0, 0, 0, 160);
private final static Color OPAQUE_BLACK2 = new Color(0, 0, 0, 180);
private final static Color GREEN = new Color(85, 110, 36, 180);
private static final Color BLUE = new Color(0, 0, 255, 180);
SkillData skillData;
@Override
public void onRepaint(Graphics g) {
if (!runPaint) {
return;
}
if (START_LVL == 0) {
if (Game.isLoggedIn()) {
START_XP = Skills.getExperience(Skills.MAGIC);
START_LVL = Skills.getLevel(Skills.MAGIC);
highalch = START_LVL > 54;
}
}
if (ITEM_SPOT_REC != null && HIGH_ALCH_SPELL_REC != null && ALCH_REC != null) {
g.setColor(BLUE);
g.drawRect(ITEM_SPOT_REC.x, ITEM_SPOT_REC.y, ITEM_SPOT_REC.width, ITEM_SPOT_REC.height);
g.drawRect(HIGH_ALCH_SPELL_REC.x, HIGH_ALCH_SPELL_REC.y, HIGH_ALCH_SPELL_REC.width, HIGH_ALCH_SPELL_REC.height);
g.setColor(GREEN);
g.fill3DRect(ALCH_REC.x, ALCH_REC.y, ALCH_REC.width, ALCH_REC.height, true);
}
final int CUR_XP = Skills.getExperience(Skills.MAGIC);
final int CUR_XP_GAIN = CUR_XP - START_XP;
final double XP_PER_HOUR = (long) (CUR_XP_GAIN * (3600000.0 / runTime.getElapsed()));
final int CUR_LVL = Skills.getLevel(Skills.MAGIC);
final int ALCHS = CUR_XP_GAIN / (highalch ? 65 : 31);
final double ALCHS_PER_HOUR = (long) (ALCHS * (3600000.0 / runTime.getElapsed()));
final double Percentage = (double) (CUR_XP - Skills.XP_TABLE[CUR_LVL]) / (double) (Skills.XP_TABLE[CUR_LVL + 1] - Skills.XP_TABLE[CUR_LVL]);
final long TTL = CUR_XP_GAIN > 0 ? ((runTime.getElapsed() * (Skills.XP_TABLE[CUR_LVL + 1] - CUR_XP)) / CUR_XP_GAIN) : 0;
if (!highalch && CUR_LVL > 54) {
highalch = true;
lastAlch.setEndIn(0);
}
int yComp = 345, xComp = 20;
g.setColor(OPAQUE_BLACK);
g.fill3DRect(0, yComp, 300, 45, true);
g.setFont(new Font("Gayatri", 0, 12));
final String l1 = version + " Run Time: " + runTime.toElapsedString() + " Alchs : " + k.format(ALCHS) + " - " + k.format(ALCHS_PER_HOUR) + "/H";
shadowText(g, l1, xComp, yComp += 18);
g.setColor(Color.BLACK);
g.draw3DRect(xComp - 5, yComp + 5, 270, 17, true);
g.setColor(OPAQUE_BLACK2);
g.fill3DRect(xComp - 5, yComp + 5, 270, 17, true);
g.setColor(BLUE);
g.fillRect(xComp - 4, yComp + 6, (int) (268 * Percentage), 15);
final String l2 = "Magic (" + CUR_LVL + ")" + (CUR_LVL == START_LVL ? "" : "+" + (CUR_LVL - START_LVL))
+ " - " + formatter(CUR_XP_GAIN) + " - " + formatter((int) XP_PER_HOUR) + "/H - TTL: " + Time.format(TTL);
shadowText(g, l2, xComp, yComp += 18);
drawButton(g);
drawMouse(g);
}
private void drawMouse(Graphics g) {
g.setColor(Mouse.isPressed() ? Color.RED : Color.GREEN);
final Point m = Mouse.getLocation();
g.drawLine(m.x - 5, m.y + 5, m.x + 5, m.y - 5);
g.drawLine(m.x - 5, m.y - 5, m.x + 5, m.y + 5);
}
private final static Rectangle REC = new Rectangle(372, 395, 125, 15);
private boolean antiBan = false;
private void drawButton(Graphics g) {
g.setColor(Color.BLACK);
g.drawRect(REC.x - 1, REC.y - 1, REC.width + 1, REC.height + 1);
g.setColor(antiBan ? new Color(85, 110, 36, 180) : new Color(153, 0, 36, 180));
g.fillRect(REC.x, REC.y, REC.width, REC.height);
g.setColor(Color.WHITE);
shadowText(g, "Antiban: " + (antiBan ? "Enabled" : "Disabled"), REC.x + 3, REC.y + 13);
}
private void shadowText(Graphics g, final String line, final int x, final int y) {
g.setColor(Color.BLACK);
g.drawString(line, x + 1, y + 1);
g.setColor(Color.WHITE);
g.drawString(line, x, y);
}
private String formatter(final int num) {
return num / 1000 + "." + (num % 1000) / 100 + "K";
}
private ImageIcon getItemImage(final int ITEM_ID) {
try {
return new ImageIcon(ImageIO.read(new URL("http://www.tip.it/runescape/styles/images/gec/items/" + ITEM_ID + ".gif")));
} catch (IOException e) {
try {
return new ImageIcon(ImageIO.read(new URL("http://www.tip.it/runescape/styles/images/gec/items/" + (ITEM_ID - 1) + ".gif")));
} catch (IOException f) {
System.out.println("Could not find item Image with ID: " + ITEM_ID);
return null;
}
}
}
private static JCheckBox[] itemCheckbox;
private static ImageIcon[] itemImages;
private static JLabel[] itemProfits;
public class AlchGui extends JFrame {
private static final long serialVersionUID = 1L;
final JButton startButton = new JButton("Start");
final JLabel instructionLabel = new JLabel("Please check all items you wish to alch", JLabel.CENTER);
final JCheckBox antiBanCheckBox = new JCheckBox("Use Antiban");
final int height = 32;
public AlchGui() {
super("The Best Alcher");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
dispose();
}
});
setLocationRelativeTo(getOwner());
draw();
startButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
for (int i = itemCheckbox.length - 1; i >= 0; i--) {
if (!itemCheckbox[i].isSelected()) goodItems.remove(i);
}
antiBan = antiBanCheckBox.isSelected();
startScript();
dispose();
}
});
}
private void draw() {
if (runPaint) return;
getContentPane().removeAll();
JPanel bottumPane = new JPanel();
bottumPane.setLayout(new GridLayout(1, 2));
bottumPane.setPreferredSize(new Dimension(240, height));
bottumPane.add(antiBanCheckBox);
bottumPane.add(startButton);
JPanel bottumPane2 = new JPanel();
bottumPane2.setLayout(new GridLayout(1, 1));
bottumPane2.setPreferredSize(new Dimension(240, height));
bottumPane2.add(instructionLabel);
getContentPane().setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
JPanel leftPane = new JPanel();
leftPane.setLayout(new GridLayout(itemCheckbox.length, 1));
leftPane.setPreferredSize(new Dimension(60, height * (itemCheckbox.length)));
for (ImageIcon curImage : itemImages) {
leftPane.add(new JLabel(curImage));
}
JPanel rightPane = new JPanel();
rightPane.setLayout(new GridLayout(itemCheckbox.length, 1));
rightPane.setPreferredSize(new Dimension(140, height * (itemCheckbox.length)));
for (JCheckBox curCheckBox : itemCheckbox) {
rightPane.add(curCheckBox);
}
JPanel profitPane = new JPanel();
profitPane.setLayout(new GridLayout(itemProfits.length, 1));
profitPane.setPreferredSize(new Dimension(40, height * (itemProfits.length)));
for (JLabel curItemProfits : itemProfits) {
profitPane.add(curItemProfits == null ? new JLabel() : curItemProfits);
}
JPanel centerPane = new JPanel();
centerPane.setLayout(new BoxLayout(centerPane, BoxLayout.X_AXIS));
centerPane.add(leftPane);
centerPane.add(rightPane);
centerPane.add(profitPane);
getContentPane().add(centerPane);
getContentPane().add(bottumPane2);
getContentPane().add(bottumPane);
pack();
setVisible(true);
}
}
private static boolean ACTIVE = false;
public class ErrorMessageGUI extends JFrame {
private static final long serialVersionUID = 1L;
public ErrorMessageGUI(Exception e) {
super("Error Message");
addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {
ACTIVE = false;
dispose();
}
});
setLocationRelativeTo(getOwner());
JTextArea textField = new JTextArea();
textField.append("Current Item: "
+ (goodItems.isEmpty() ? "No More Items" : goodItems.get(0).getName()));
textField.append("\nError Message \n");
textField.append(e.getMessage() + "\n");
final StackTraceElement[] elements = e.getStackTrace();
for(int i = 0; i < 5 && i < elements.length; i++) {
textField.append(elements[i].toString() + "\n");
}
add(textField);
pack();
setVisible(true);
ACTIVE = true;
}
}
/**
* Looks up grand exchange information and returns a string array with the following contents
* <br>String[0] = item name
* <br>String[1] = item price
* <br>String[2] = item Alch Price
*
* @param itemID for the item being looked up on the grand exchange
* @param secondRun used for recursive search of noted item ids
* @return : a string array of grand exchange information on the item id provided
*/
private static String[] lookup(final int itemID, final boolean secondRun) {
String[] info = {"0", "0", "0"};
try {
final URL url = new URL("http://www.tip.it/runescape/index.php?gec&itemid=" + itemID);
final BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String input;
while ((input = br.readLine()) != null) {
if (input.startsWith(" </table><p>Invalid item number")) {
return secondRun ? info : lookup(itemID - 1, true);
} else if (input.startsWith("<h2>")) {
info[0] = input.substring(4, input.length() - 5);
} else if (input.startsWith("<tr><td colspan=\"4\"><b>Current Market Price: </b>")) {
info[1] = input.substring(49, input.lastIndexOf("gp")).replaceAll(",", "");
return info;
} else if (input.contains("View Item DB")) {
input = input.substring(input.indexOf("id=") + 3, input.indexOf(" title") - 1);
info[2] = lookupAlchPrice(input);
}
}
} catch (final Exception ignored) {
}
return info;
}
/**
* Looks up grand exchange information and returns a string array with the following contents
*
* @param tipItID the tip it id for the item to find the alch price for
* @return : the alch price of the item if not found returns Error
*/
private static String lookupAlchPrice(final String tipItID) {
try {
final URL url = new URL("http://www.tip.it/runescape/?rs2item_id=" + tipItID);
final BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()));
String input;
while ((input = br.readLine()) != null) {
if (input.equals(" <td class=\"header\" width=\"25%\">High Alchemy</td>")) {
br.readLine();
input = br.readLine().replaceAll("\t", "");
return input.substring(0, input.indexOf(" gp"));
}
}
} catch (final Exception ignored) {
}
return "Error";
}
@Override
public void mouseClicked(MouseEvent e) {
if (REC.contains(e.getPoint())) {
antiBan ^= true;
}
}
@Override
public void mouseEntered(MouseEvent arg0) {
}
@Override
public void mouseExited(MouseEvent arg0) {
}
@Override
public void mousePressed(MouseEvent arg0) {
}
@Override
public void mouseReleased(MouseEvent arg0) {
}
@Override
public void messageReceived(MessageEvent e) {
if (e.getId() == 0 && e.getMessage().equals("You do not have enough nature runes to cast this spell.")) {
System.out.println("You are out of nature runes");
stop();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment