Jump to content

[Open Source] ~ Fanny Shafter ~ Fletches arrow shafts


Recommended Posts

Posted (edited)

Never coded in Java before and first script!

It's a really simple one, but hopefully somebody gets some use out of it

Would really appreciate any feedback regards the code & methodology (but not planning to add features)

*Note: membership ran out before I got widgets working, so its kind of a guess whether it works or not... Would appreciate widget help tips... It can be modified to just wait a period of time and then press 1 or something to bypass widgets (thats how I used it since they seem difficult to use)

 

import java.util.List;

import org.osbot.rs07.api.ui.Skill;
import org.osbot.rs07.api.model.Item;
import org.osbot.rs07.api.ui.RS2Widget;
import org.osbot.rs07.script.Script;
import org.osbot.rs07.script.ScriptManifest;
import org.osbot.rs07.utility.ConditionalSleep;

@ScriptManifest(author = "Fanny", info = "Fletches arrow shafts and makes headless arrows", name = "Fanny Shafter", version = 1.0, logo = "")
public class FannyShafter extends Script {
    private long startTime;
    private int startLevel;
    private long startXp;

    private final String[] logTypes = {"Logs", "Oak logs", "Willow logs", "Maple logs", "Yew logs", "Magic logs"};
    private final int[] levelRequirements = {1, 15, 30, 45, 60, 75};
    private String logType;
    private long lastAnimationTime = 0;



    @Override
    public void onStart() {
        // onStart logic remains unchanged
    }

    @Override
    public int onLoop() throws InterruptedException {
        if (shouldFletch()) {
            fletchArrowShafts();
        }
        else if (shouldBank()) {
            handleBanking();
        }
        else {
            stop();
        }
        return random(200, 300); // Wait time before the loop starts over
    }

    private void handleBanking() throws InterruptedException {
        // Enhanced banking logic considering both logs and knife
        if (!getBank().isOpen() && !getBank().open()) return;
        new ConditionalSleep(5000, 1000) {
            @Override
            public boolean condition() throws InterruptedException {
                return getBank().isOpen();
            }
        }.sleep();

        if (!getInventory().contains("Knife") && getBank().contains("Knife")) {
            getBank().withdraw("Knife", 1);
        }
        else if(!getBank().contains("Knife") && !getInventory().contains("Knife")){
            stop();
        }

        for (String log : logTypes) {
            if (getBank().contains(log) && getSkills().getStatic(Skill.FLETCHING) >= getLevelRequirement(log)) {
                getBank().withdrawAll(log);
                break;
            }
        }

        getBank().close();
    }

    private boolean shouldBank() {
        // Check if player needs to bank
        return !hasRequiredItemsForFletching();
    }

    private boolean shouldFletch() {
        // Check if player can fletch
        return hasRequiredItemsForFletching();
    }

    private boolean hasRequiredItemsForFletching() {
        // Check if the inventory contains a knife and any of the log types
        if (!getInventory().contains("Knife")) {
            return false;
        }
        for (String log : logTypes) {
            if (getInventory().contains(log) && getSkills().getStatic(Skill.FLETCHING) >= getLevelRequirement(log)) {
                return true;
            }
        }
        return false;
    }

    private int getLevelRequirement(String logType) {
        // Return the level requirement for the given log type
        for (int i = 0; i < logTypes.length; i++) {
            if (logTypes[i].equals(logType)) {
                return levelRequirements[i];
            }
        }
        return 0; // Default to 0 if log type not found
    }

    private void fletchArrowShafts() throws InterruptedException {
        // Check bank is closed, then proceed to check logs & fletch
        if (getBank().isOpen()) closeBank();

        for (String log : logTypes) {
            if (getInventory().contains(log) && getSkills().getStatic(Skill.FLETCHING) >= getLevelRequirement(log)) {
                Item logToUse = getInventory().getItem(log);
                handleFletching(logToUse);
                break;
            }
        }
    }

    private void handleFletching(Item log) throws InterruptedException {
        // Check if log is not null
        if (log == null) {
            return;
        }

        boolean knifeUsedFirst = random(0, 2) == 0; // Randomly decide whether to use the knife or the log first

        if (knifeUsedFirst ? getInventory().interact("Use", "Knife") : log.interact("Use")) {
            new ConditionalSleep(2000, 500) {
                @Override
                public boolean condition() throws InterruptedException {
                    return getInventory().isItemSelected();
                }
            }.sleep();

            sleep(random(50, 300));
        }

        if (knifeUsedFirst ? log.interact("Use") : getInventory().interact("Use", "Knife")) {
            sleep(random(100,300));
        }
        
        new ConditionalSleep(5000, 1000) {
            @Override
            public boolean condition() throws InterruptedException {
                return isFletchingWidgetOpen();
            }
        }.sleep();

        sleep(random(100, 800));
        
        RS2Widget fletchingWidget = getFletchingWidget();

        if (fletchingWidget != null) {
            if (random(0, 100) < 25) {
                fletchingWidget.interact("15 arrow shafts");
            } else {
                getKeyboard().typeKey((char) 49);
            }
        }

        sleep(random(800,2500));

        getMouse().moveOutsideScreen();

        final long[] lastAnimated = {System.currentTimeMillis()};

        new ConditionalSleep(25000) { // Wait up to 25 seconds
            @Override
            public boolean condition() throws InterruptedException {
                // Check if the player is animating
                if(!getInventory().contains(logType)) {
                    return true;
                }
                else if (myPlayer().isAnimating()) {
                    // Update lastAnimated if the player is still animating
                    lastAnimated[0] = System.currentTimeMillis();
                }
                // Return true if more than 5 seconds have elapsed since lastAnimated
                return (System.currentTimeMillis() - lastAnimated[0]) > 5000;
            }
        }.sleep();

        // AFK returning to screen
        exponentialBackoffSleep();
    }

    private void exponentialBackoffSleep() throws InterruptedException{
        final int duration = random(1,3) * random(1,3) * random(1,3) * random(1, 3) * random(100, 300);
        sleep(duration);
    }
    private boolean isFletchingWidgetOpen(){
        if(getFletchingWidget() != null){
            return true;
        }
        return false;
    }
    private RS2Widget getFletchingWidget() {
        List<RS2Widget> allWidgets = getWidgets().getAll();
        RS2Widget storedWidget = allWidgets.stream().filter(w -> w.getWidth() == 52 && w.getHeight() == 52 && w.getItemId() == 52).findFirst().orElse(null);
        return storedWidget;
    }

    private void closeBank() throws InterruptedException {
        // Logic to close the bank
        getBank().close();
        new ConditionalSleep(3000, 1000) {
            @Override
            public boolean condition() throws InterruptedException {
                return !getBank().isOpen();
            }
        }.sleep();
    }
}

 

Edited by Fanny
Posted (edited)

Neat! What about adding an additional step to have headless arrowheads in inventory and use those as well?
Regarding the make widget I think the root id is 270. Also you can use "1" hotkey instead of clicking the widget since arrowheads are always the 1st option from the left.

Here is a example of how I get the widget then interact with it with spacebar. Same concept as "1" hotkey. Except spacebar repeats the last widget interaction used. 

https://github.com/YifanLi5/Bankstanding-Skiller/blob/cc8c13d063fd141125494fe3bf7643330d14a49d/src/Task/CombineItems.java#L86

 

Edited by yfoo
Posted
3 hours ago, yfoo said:

Neat! What about adding an additional step to have headless arrowheads in inventory and use those as well?
Regarding the make widget I think the root id is 270. Also you can use "1" hotkey instead of clicking the widget since arrowheads are always the 1st option from the left.

Here is a example of how I get the widget then interact with it with spacebar. Same concept as "1" hotkey. Except spacebar repeats the last widget interaction used. 

https://github.com/YifanLi5/Bankstanding-Skiller/blob/cc8c13d063fd141125494fe3bf7643330d14a49d/src/Task/CombineItems.java#L86

 

Thanks a lot for the tips, when I get enough gold for membership again I'l ltry that!

Really appreciate the link; that randomGaussian method is a good idea for sleeps! Although I feel like I would add a base 50ms just because reaction time?

I was also not aware of a conditionalSleep2 method - what is the difference?

Posted (edited)
15 hours ago, Fanny said:

Thanks a lot for the tips, when I get enough gold for membership again I'l ltry that!

Really appreciate the link; that randomGaussian method is a good idea for sleeps! Although I feel like I would add a base 50ms just because reaction time?

I was also not aware of a conditionalSleep2 method - what is the difference?

>I was also not aware of a conditionalSleep2 method - what is the difference?

regular CS requires you to make an object to call sleep. CS2.sleep() is a static method. 

 

>randomGaussian method is a good idea for sleeps! Although I feel like I would add a base 50ms just because reaction time?

That's the point actually, I was using it to delay menu interactions by a small amount, like a human would. 

ex:)

sleep(randomGaussian(300, 100));
keyboard.pressKey(KeyEvent.VK_SPACE);
ScriptPaint.setStatus("Spacebar-ing make widget");
result = ConditionalSleep2.sleep(2000, () -> {
  List<RS2Widget> widgets = new ArrayList<>(getWidgets().containingActions(270, CREATE_VERBS));
  return widgets.isEmpty();
});
sleep(randomGaussian(300, 100));
keyboard.releaseKey(KeyEvent.VK_SPACE);

In this block, I wanted to wait a moment after the make widget appears before interacting with it. Then wait again after spacebar-ing it before releasing it. 

Edited by yfoo

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.
×
×
  • Create New...