Pseudo Posted January 7 Share Posted January 7 (edited) Another release for everyone. Features: - Fletches headless arrows from level 1-20 fletching (Have approx 5k arrow shafts and feathers banked). - Fletches the best possible bow (short and long) for it's level, progressively, from Oak shortbows all the way to Magic longbows. - Stops if it detects we're out of the necessary supplies. (Have more than enough of each log required for the progression if you intend on leaving it run for a long time unmonitored). import com.epicbot.api.shared.APIContext; import com.epicbot.api.shared.GameType; import com.epicbot.api.shared.entity.ItemWidget; import com.epicbot.api.shared.entity.WidgetChild; import com.epicbot.api.shared.model.Skill; import com.epicbot.api.shared.script.LoopScript; import com.epicbot.api.shared.script.ScriptManifest; import com.epicbot.api.shared.util.details.Completable; import com.epicbot.api.shared.util.paint.frame.PaintFrame; import com.epicbot.api.shared.util.time.Time; import com.epicbot.api.shared.util.time.Timer; import java.awt.*; import java.awt.event.KeyEvent; @ScriptManifest(name = "Λ Progressive Fletcher", gameType = GameType.OS) public class LambdaProgressiveFletcher extends LoopScript { private final Timer runTimer = new Timer(0); private final Timer experienceTimer = new Timer(5000); private Timer idleTimer = null; private final double version = 0.1; private int experienceGained, startExperience = 0; private final PaintFrame paintFrame = new PaintFrame(); private String status = ""; @Override protected int loop() { if (getAPIContext().client().isLoggedIn()) { handleCalculations(); doTasks(); } return 50; } private enum Task { FLETCHING, BANKING; @Override public String toString() { return this.name().toLowerCase(); } } private void handleCalculations() { if (startExperience == 0) { startExperience = getAPIContext().skills().get(Skill.Skills.FLETCHING).getExperience(); } else { if (!experienceTimer.isRunning()) { experienceGained = getAPIContext().skills().get(Skill.Skills.FLETCHING).getExperience() - startExperience; experienceTimer.reset(); } } } private void doTasks() { status = getCurrentTask().toString(); switch (getCurrentTask()) { case FLETCHING: doFletching(); break; case BANKING: doBanking(); break; } } private void buildPaintTitle() { paintFrame.setTitle(getManifest().name() + " v" + version); paintFrame.setColumnValueSpacing(0); } private boolean isFletching() { if (!hasInputItems() || idleTimer == null || idleTimer.getElapsed() >= getRandomNumber(2500, 4000)) return false; if (getAPIContext().localPlayer().getAnimation() != -1) { idleTimer = new Timer(0); return true; } return true; } private boolean hasInputItems() { return getAPIContext().inventory().contains(getFletchingMethod().getItemsRequired()); } private void doBanking() { if (getAPIContext().bank().isOpen()) { if (hasRequiredItemsInInventoryOrBank()) { if (getAPIContext().inventory().getCount() > 27) { if (getAPIContext().bank().depositAllExcept("Knife")) { Time.sleep(1800, () -> getAPIContext().inventory().getCount() <= 27); } } else { if (getFletchingMethod().getOutputName().contains("arrow")) { withdrawItem(getFletchingMethod().getItemsRequired()[0], 0); withdrawItem(getFletchingMethod().getItemsRequired()[1], 0); } else { withdrawItem("Knife", 1); withdrawItem(getFletchingMethod().getItemsRequired()[0], 0); } } } else { stop("We don't have the required items!"); } } else { if (getAPIContext().bank().open()) { Time.sleep(2400, () -> getAPIContext().bank().isOpen()); } } } private boolean withdrawItem(String itemName, int amount) { if (!getAPIContext().inventory().contains(itemName)) { if (amount == 0) { getAPIContext().bank().withdrawAll(itemName); } else { getAPIContext().bank().withdraw(amount, itemName); } } return Time.sleep(1000, 2000, () -> hasItem(itemName)); } private boolean hasItem(String itemName) { return getAPIContext().inventory().contains(itemName); } private boolean itemExistsInInventoryOrBank(String item) { return getAPIContext().inventory().contains(item) || getAPIContext().bank().contains(item); } private boolean hasRequiredItemsInInventoryOrBank() { for (String item : getFletchingMethod().getItemsRequired()) { if (item != null) { if (!itemExistsInInventoryOrBank(item)) return false; } } return true; } private void doFletching() { if (!getAPIContext().bank().isOpen()) { if (!isFletching()) { if (isWidgetValid(getTargetWidget())) { getAPIContext().keyboard().sendKey(getWidgetOptionKeyboardKey()); idleTimer = new Timer(0); Time.sleep(1200, 2000, this::isFletching); } else { if (getFletchingMethod().getOutputName().contains("arrow")) { if (handleItem(getFletchingMethod().getItemsRequired()[0], null, 1200, () -> getAPIContext().inventory().isItemSelected())) { handleItem(getFletchingMethod().getItemsRequired()[1], null, 1200, () -> isWidgetValid(getTargetWidget())); } } else { if (handleItem("Knife", null, 1200, () -> getAPIContext().inventory().isItemSelected())) { handleItem(getFletchingMethod().itemsRequired[0], null, 1200, () -> isWidgetValid(getTargetWidget())); } } } } else { idleTimer.reset(); Time.sleep(50, 300); } } else { if (closeBank()) { Time.sleep(1800, () -> !getAPIContext().bank().isOpen()); } } } private boolean hasEscToCloseInterface() { return getAPIContext().vars().getVarbit(4681) == 1; } private boolean closeBank() { if (hasEscToCloseInterface() && getWidgetOptionKeyboardKey() != -1) { getAPIContext().keyboard().sendKey(KeyEvent.VK_ESCAPE); return true; } else return getAPIContext().bank().close(); } private boolean isWidgetValid(WidgetChild widgetChild) { return widgetChild != null && widgetChild.isVisible(); } private WidgetChild getTargetWidget() { return getAPIContext().widgets().get(getParentWidgetId()).find(i -> i != null && getWidgetPredicateString() != null && i.getName().contains(getWidgetPredicateString())); } private int getWidgetOptionKeyboardKey() { if (getWidgetPredicateString() == null) return -1; return getWidgetPredicateString().equals("shortbow") ? KeyEvent.VK_2 : getWidgetPredicateString().equals("longbow") ? KeyEvent.VK_3 : KeyEvent.VK_1; } private String getWidgetPredicateString() { String output = getFletchingMethod().getOutputName(); if (output != null) { if (output.contains("shortbow")) { return "shortbow"; } else if (output.contains("longbow")) { return "longbow"; } else { return "arrow"; } } return null; } private int getParentWidgetId() { return 270; } private Task getCurrentTask() { if (!hasItemsRequired()) { return Task.BANKING; } else return Task.FLETCHING; } private boolean hasItemsRequired() { return inventoryContainsAllOf(getFletchingMethod().getItemsRequired()); } private boolean handleItem(String itemName, String action, int timeOut, Completable condition) { ItemWidget itemWidget = getAPIContext().inventory().getItem(itemName); if (itemWidget == null) return false; if (action != null) { if (itemWidget.interact(action)) { return Time.sleep(timeOut, condition); } } else { if (itemWidget.click()) { return Time.sleep(timeOut, condition); } } return false; } private int getRandomNumber(int min, int max) { return (int) ((Math.random() * (max - min)) + min); } @Override public boolean onStart(String... strings) { System.out.println("Starting " + getManifest().name() + " v" + version); buildPaintTitle(); return true; } private boolean inventoryContainsAllOf(String[] items) { for (String item : items) { if (item != null) { if (!getAPIContext().inventory().contains(item)) { return false; } } } return true; } private String rsFormat(Integer number) { String[] suffix = new String[]{"K", "M", "B", "T"}; int size = (number != 0) ? (int) Math.log10(number) : 0; if (size >= 3) { while (size % 3 != 0) { size = size - 1; } } return (size >= 3) ? +(Math.round((number / Math.pow(10, size)) * 10) / 10d) + suffix[(size / 3) - 1] : +number + ""; } private int getHourlyRate(int i) { return (int) (i / (runTimer.getElapsed() / 3600000.0D)); } private String getExperienceGainedString() { return "Experience gained: " + rsFormat(experienceGained) + " (" + rsFormat(getHourlyRate(experienceGained)) + ")"; } private String getStatusString() { return modifyString(status); } private String modifyString(String string) { String input = string.replace("_", " "); return input.substring(0, 1).toUpperCase() + input.substring(1); } private final Font boldText = new Font(Font.SANS_SERIF, Font.BOLD, 12); @Override protected void onPaint(Graphics2D g2d, APIContext ctx) { if (getAPIContext().client().isLoggedIn()) { paintFrame.draw(g2d, 20, 30, getAPIContext()); g2d.setFont(boldText); g2d.setColor(Color.WHITE); g2d.drawString("Time running: " + runTimer.toElapsedString(), 20, 70); g2d.drawString("Status: " + getStatusString(), 20, 90); g2d.drawString(getExperienceGainedString(), 20, 110); g2d.drawString("Fletching method: " + getFletchingMethod().toString(), 20, 130); super.onPaint(g2d, ctx); } } private int getFletchingLevel() { return getAPIContext().skills().get(Skill.Skills.FLETCHING).getRealLevel(); } private Fletch getFletchingMethod() { for (Fletch fletch : Fletch.values()) { if (fletch.getRequiredLevel() <= getFletchingLevel() && fletch.getTargetLevel() > getFletchingLevel()) { return fletch; } } return Fletch.HEADLESS_ARROW; } private enum Fletch { HEADLESS_ARROW("Headless arrow", 1, 20, new String[]{"Feather", "Arrow shaft"}), OAK_SHORTBOW("Oak shortbow", 20, 25, new String[]{"Oak logs"}), OAK_LONGBOW("Oak longbow", 25, 35, new String[]{"Oak logs"}), WILLOW_SHORTBOW("Willow shortbow", 35, 40, new String[]{"Willow logs"}), WILLOW_LONGBOW("Willow longbow", 40, 50, new String[]{"Willow logs"}), MAPLE_SHORTBOW("Maple shortbow", 50, 55, new String[]{"Maple logs"}), MAPLE_LONGBOW("Maple longbow", 55, 65, new String[]{"Maple logs"}), YEW_SHORTBOW("Yew shortbow", 65, 70, new String[]{"Yew logs"}), YEW_LONGBOW("Yew longbow", 70, 80, new String[]{"Yew logs"}), MAGIC_SHORTBOW("Magic shortbow", 80, 85, new String[]{"Magic logs"}), MAGIC_LONGBOW("Magic longbow", 85, 100, new String[]{"Magic logs"}); private final int requiredLevel, targetLevel; private final String[] itemsRequired; private final String outputName; Fletch(String outputName, int requiredLevel, int targetLevel, String[] itemsRequired) { this.outputName = outputName; this.requiredLevel = requiredLevel; this.targetLevel = targetLevel; this.itemsRequired = itemsRequired; } public int getRequiredLevel() { return requiredLevel; } public String getOutputName() { return outputName; } public int getTargetLevel() { return targetLevel; } public String[] getItemsRequired() { return itemsRequired; } } } See this post for how to compile local scripts if you intend on using this. Edited January 7 by Pseudo 1 1 Quote Link to post Share on other sites
smile Posted January 7 Share Posted January 7 but can it kill vorkath tho? Quote Link to post Share on other sites
Pseudo Posted January 7 Author Share Posted January 7 Just now, smile said: but can it kill vorkath tho? Only on Wednesdays 😕 1 Quote Link to post Share on other sites
smile Posted January 7 Share Posted January 7 Just now, Pseudo said: Only on Wednesdays 😕 what's it kill on fridays? Quote Link to post Share on other sites
Sellout Posted January 7 Share Posted January 7 damn keep 'm coming 😮 1 Quote Link to post Share on other sites
Pseudo Posted January 7 Author Share Posted January 7 Forgot to mention, if you wanted to stop progressing logs/bows at say, maple, then you can do so by just simply modifying the enum. Quote Link to post Share on other sites
MansNoThot Posted January 7 Share Posted January 7 Ayyy. Killing it with the releases! Quote Link to post Share on other sites
Global Moderators Euan Posted January 8 Global Moderators Share Posted January 8 Nice man, looks great! Quote Link to post Share on other sites
Pseudo Posted January 11 Author Share Posted January 11 (edited) 1-50 without interruption: Edited January 11 by Pseudo Quote Link to post Share on other sites
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.