Jump to content

vsun

Members
  • Posts

    1
  • Joined

  • Last visited

  • Days Won

    2

Posts posted by vsun

  1. I've been interested in writing a bot for a while but doing 2000 laps of the Ape Atoll course is what finally broke me.

    Here's the completed script I wrote for doing the course. It'll only work if you run it at the start or end tile of an obstacle. I tried to add code to get back on the course if the player went off, but I ran into a bunch of issues navigating to the start/end tiles and gave up. Please let me know about any Java best practices I missed and how I can improve/clean this up since it's my first script.

    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.SceneObject;
    import com.epicbot.api.shared.methods.*;
    import com.epicbot.api.shared.model.Tile;
    import com.epicbot.api.shared.script.LoopScript;
    import com.epicbot.api.shared.script.ScriptManifest;
    import com.epicbot.api.shared.util.Random;
    import com.epicbot.api.shared.util.paint.frame.PaintFrame;
    import com.epicbot.api.shared.util.time.Time;
    
    import java.awt.*;
    
    @ScriptManifest(name = "ApeAtollAgility", gameType = GameType.OS)
    public class ApeAtollAgility extends LoopScript {
    
        private long startTime;
        private int laps;
        private int originalExperience;
    
        private ICameraAPI camera() { return getAPIContext().camera(); }
        private IInventoryAPI inventory() { return getAPIContext().inventory(); }
        private ILocalPlayerAPI localPlayer() { return getAPIContext().localPlayer(); }
        private IMouseAPI mouse() { return getAPIContext().mouse(); }
        private IObjectsAPI objects() { return getAPIContext().objects(); }
        private IWebWalkingAPI webWalking() { return getAPIContext().webWalking(); }
        private IWalkingAPI walking() { return getAPIContext().walking(); }
    
        private final String[] COURSE = { "Stepping stone", "Tropical tree", "Monkeybars", "Skull slope", "Rope", "Tropical tree" };
        private final String[] ACTIONS = { "Jump-to", "Climb", "Swing Across", "Climb-up", "Swing", "Climb-down" };
        private final Tile[] STARTS = { new Tile(2755, 2742, 0),
                                        new Tile(2753, 2742, 0),
                                        new Tile(2752, 2742, 2),
                                        new Tile(2747, 2741, 0),
                                        new Tile(2751, 2731, 0),
                                        new Tile(2758, 2734, 0) };
        private final Tile[] ENDS = { new Tile(2753, 2742, 0),
                                      new Tile(2753, 2742, 2),
                                      new Tile(2747, 2741, 0),
                                      new Tile(2742, 2741, 0),
                                      new Tile(2756, 2731, 0),
                                      new Tile(2770, 2747, 0) };
    
        private int missed = 0;
    
        private boolean isIdle() {
            return !localPlayer().isAnimating() && !localPlayer().isMoving();
        }
    
        private boolean isOnTile(Tile t) {
            Tile currTile = localPlayer().getLocation();
            return currTile.equals(t);
        }
    
        private boolean needStaminaDose() {
            return walking().getRunEnergy() < Math.random() * 40 && !localPlayer().isStaminaActive();
        }
    
        private ItemWidget findStaminaDose() {
            String fmt = "Stamina potion(%d)";
            for (int i = 1; i <= 4; i++) {
                ItemWidget stam = inventory().getItem(String.format(fmt, i));
                if (stam != null) {
                    return stam;
                }
            }
    
            return null;
        }
    
        private boolean shouldExit() {
            if (!getAPIContext().client().isLoggedIn()) {
                return false;
            }
    
            return findStaminaDose() == null && walking().getRunEnergy() < 20;
        }
    
        private void doHumanWait() {
            double p = Math.random();
            if (p < 0.01) {
                int secs = Random.nextInt(90, 150);
                getLogger().info(String.format("Long sleeping for %d seconds", secs));
                mouse().moveOffScreen();
                Time.sleep(secs * 1000);
            } else if (p < 0.04) {
                int secs = Random.nextInt(10, 20);
                getLogger().info(String.format("Sleeping for %d seconds", secs));
                mouse().moveOffScreen();
                Time.sleep(secs * 1000);
            }
        }
    
        private int findCurrentStep(Tile t) {
            for (int i = 0; i < STARTS.length; i++) {
                Tile s = STARTS[i];
                if (t.equals(s)) {
                    return i;
                }
            }
    
            for (int i = 0; i < ENDS.length; i++) {
                Tile e = ENDS[i];
                if (t.equals(e)) {
                    return (i + 1) % ENDS.length;
                }
            }
    
            return -1;
        }
    
        private boolean doCourseStep() throws Exception {
            Tile curr = localPlayer().getLocation();
            int i = findCurrentStep(curr);
            if (i == -1) {
                if (missed >= 10) {
                    throw new Exception("Missed too many obstacles");
                }
                // usually only logs on the stepping stone since it "wakes" when on the stone
                getLogger().info("Did not find current step");
                missed++;
                return false;
            }
    
            missed = 0;
    
            String name = COURSE[i];
            String action = ACTIONS[i];
            Tile s = STARTS[i];
            Tile e = ENDS[i];
    
            getLogger().info(String.format("%s %s: %d", action, name, i));
    
            SceneObject obstacle = objects().query().named(name).results().nearest();
            if (obstacle == null) {  // if we don't see it, move to the start
                walking().walkOnMap(s);
                Time.sleep(4000, () -> isOnTile(s) && isIdle());
            } else {  // if we see it, do the action on it
                if (obstacle.interact(action)) {
                    doHumanWait();
                    Time.sleep(3000, () -> isOnTile(e) && isIdle());
                }
            }
    
            if (i == COURSE.length - 1) {
                laps++;
            }
    
    //        Time.sleep(100);
            return isOnTile(e);
        }
    
        private String convertToHHMMSS(long ms) {
            int total = (int) (ms / 1000);
    
            int h = total / 3600;
            int m = (total % 3600) / 60;
            int s = total % 60;
    
            return String.format("%02d:%02d:%02d", h, m, s);
        }
    
        private int getExpGained() {
            return getAPIContext().skills().agility().getExperience() - originalExperience;
        }
    
        @Override
        protected int loop() {
            if (shouldExit()) {
                return -1;
            }
    
            if (!isIdle()) {
                Time.sleep(600, () -> isIdle());
            } else if (needStaminaDose()) {
                ItemWidget stam = findStaminaDose();
                if (stam != null) {
                    stam.interact("Drink");
                }
            } else {
                try {
                    doCourseStep();
                } catch (Exception e) {
                    getLogger().error(e.toString());
                    return -1;
                }
            }
    
            return 690;
        }
    
        @Override
        public boolean onStart(String... strings) {
            if (!getAPIContext().client().isLoggedIn()) {
                return false;
            }
    
            startTime = System.currentTimeMillis();
            laps = 0;
            originalExperience = getAPIContext().skills().agility().getExperience();
            getLogger().info("Starting script");
    
            ICameraAPI cam = camera();
            cam.setPitch(98, false);
            cam.setYawDeg(0, false);
            return true;
        }
    
        @Override
        protected void onPaint(Graphics2D g, APIContext ctx) {
            if (!getAPIContext().client().isLoggedIn()) {
                Time.sleep(15000, () -> getAPIContext().client().isLoggedIn());
            }
    
            long totalMillis = System.currentTimeMillis() - startTime;
    
            PaintFrame frame = new PaintFrame();
            frame.setTitle("Stats");
            frame.addLine("Time elapsed: ", convertToHHMMSS(totalMillis));
            frame.addLine("Total laps: ", laps);
            frame.addLine("Exp gained: ", getExpGained());
            frame.draw(g, 0, 90, ctx);
        }
    }

     

    • Like 2
×
×
  • Create New...