Jump to content

[Open Source] ~ Fanny Shafter ~ Fletches arrow shafts


Fanny

Recommended Posts

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
Link to comment
Share on other sites

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
Link to comment
Share on other sites

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?

Link to comment
Share on other sites

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
Link to comment
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.
Note: Your post will require moderator approval before it will be visible.

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.

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...