Jump to content

[Open Source] Λ Progressive Fletcher [1-99]


Recommended Posts

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 by Pseudo
  • Like 1
  • Thanks 1
Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...