Air Rune Crafter



  • First script for RSPeer.
    I'm just hobby programmer and hate java please be kind 🙂

    I would really appreciate some input. Especially minimizing scene object interactions - script interacts 2-3 times with altar, portal, ruins etc.

    import org.rspeer.runetek.api.component.Bank;
    import org.rspeer.runetek.api.component.tab.Inventory;
    import org.rspeer.runetek.api.component.tab.Skill;
    import org.rspeer.runetek.api.component.tab.Skills;
    import org.rspeer.runetek.api.movement.Movement;
    import org.rspeer.runetek.api.movement.position.Area;
    import org.rspeer.runetek.api.movement.position.Position;
    import org.rspeer.runetek.api.scene.Players;
    import org.rspeer.runetek.event.listeners.RenderListener;
    import org.rspeer.runetek.event.types.RenderEvent;
    import org.rspeer.script.Script;
    import org.rspeer.script.ScriptCategory;
    import org.rspeer.script.ScriptMeta;
    import org.rspeer.ui.Log;
    import org.rspeer.runetek.api.scene.SceneObjects;
    import org.rspeer.runetek.adapter.scene.SceneObject;
    
    import java.awt.*;
    import java.time.LocalTime;
    
    @ScriptMeta(developer = "merc", desc = "Crafts Air Runes", name = "mercRCAir", category = ScriptCategory.RUNECRAFTING)
    public class mercRCAir extends Script implements RenderListener {
    
        enum metaLocations {BANK, RUINS, ALTAR, UNKNOWN}
        Long startTime = 0L;
        int startXp = 0;
        int startLevel = 0;
        int gainedXp = 0;
        int gainedLevel = 0;
        int xpPerHour = 0;
        String timeRunningString = "";
    
        @Override
        public void onStart() {
            startTime = System.currentTimeMillis();
            startXp = Skills.getExperience(Skill.RUNECRAFTING);
            startLevel = Skills.getLevel(Skill.RUNECRAFTING);
        }
    
        @Override
        public int loop() {
    
            metaLocations loc = getMetaLocation();
    
            if(isInventoryReady()){ // Going towards ruins
                if(loc == metaLocations.RUINS) {
                    return enterRuins();
                } else if (loc == metaLocations.ALTAR){
                    return craftRunes();
                } else {
                    return walkToRuin();
                }
            } else { // Going towards bank
                if(loc == metaLocations.BANK){
                    return doBank();
                } else {
                    if(loc == metaLocations.ALTAR){
                        return leaveAltar();
                    } else {
                        return walkToBank();
                    }
                }
            }
    
        }
    
    
        int doBank(){
            if (Movement.isDestinationSet() || Players.getLocal().isMoving())
                return 500;
    
            if (Bank.isClosed()) {
                Bank.open();
                return 1500;
            }
    
            if (!Bank.containsAll(7936, 2552)) {
                Log.info("Bank ran out of resources");
                setStopping(true);
                return 500;
            }
    
            if (Inventory.containsAnyExcept(7936, 2552)) {
                Bank.depositInventory();
                return 1000;
            }
            if (Inventory.getFreeSlots() > 0) {
                Bank.withdrawAll(7936);
                return 1000;
            }
    
            return 500;
        }
    
        int enterRuins() {
            if (Movement.isDestinationSet() || Players.getLocal().isMoving() || Players.getLocal().isAnimating())
                return 300;
    
            SceneObject ruins = SceneObjects.getNearest("Mysterious ruins");
            ruins.interact("Enter");
            return 1000;
        }
    
        int craftRunes(){
            if (Movement.isDestinationSet() || Players.getLocal().isMoving() || Players.getLocal().isAnimating())
                return 300;
    
            SceneObject altar = SceneObjects.getNearest("Altar");
            altar.interact("Craft-rune");
            return 1500;
        }
    
        int leaveAltar(){
            SceneObject portal = SceneObjects.getNearest("Portal");
    
            if (Players.getLocal().isMoving() || Players.getLocal().isAnimating() || (Movement.isDestinationSet() && portal.getPosition().distance(Movement.getDestination()) < 3))
                return 300;
    
    
            portal.interact("Use");
            if (!Movement.isRunEnabled() && Movement.getRunEnergy() > 80) {
                Movement.toggleRun(true);
            }
            calcProgress();
            return 1500;
        }
    
        int walkToBank() {
            Position bank = new Position(3012, 3357, 0);
            if (!Movement.isDestinationSet() || Movement.getDestinationDistance() < 7 || !Players.getLocal().isMoving()) {
                Movement.walkToRandomized(bank);
            }
            return 300;
        }
    
        int walkToRuin() {
            Position ruin = new Position(2990, 3295, 0);
            if (!Movement.isDestinationSet() || Movement.getDestinationDistance() < 7 || !Players.getLocal().isMoving()) {
                Movement.walkToRandomized(ruin);
            }
            return 300;
        }
    
    
         metaLocations getMetaLocation(){
            Area faladorWestBank = Area.rectangular(3003, 3364, 3027, 3346);
            Area airRuins = Area.rectangular(2973, 3302, 2996, 3283);
            Area airAltar = Area.rectangular(2836, 4841, 2852, 4825);
    
            Position pos = Players.getLocal().getPosition();
    
            if (faladorWestBank.contains(pos)){
                return metaLocations.BANK;
            } else if (airRuins.contains(pos)){
                return metaLocations.RUINS;
            } else if (airAltar.contains(pos)){
                return metaLocations.ALTAR;
            } else {
                return metaLocations.UNKNOWN;
            }
        }
    
        boolean isInventoryReady(){
            return !Inventory.containsAnyExcept(7936,2552) && Inventory.getFreeSlots() == 0;
        }
    
        void calcProgress(){
            gainedXp = Skills.getExperience(Skill.RUNECRAFTING) - startXp;
            gainedLevel = Skills.getLevel(Skill.RUNECRAFTING) - startLevel;
            Long elapsedTime = System.currentTimeMillis() - startTime;
            xpPerHour = 3600000 / elapsedTime.intValue() * gainedXp;
            timeRunningString = LocalTime.ofSecondOfDay(elapsedTime / 1000).toString();
    
        }
    
        @Override
        public void notify(RenderEvent renderEvent) {
            Graphics g = renderEvent.getSource();
    
    
    
            int x = 4;
            int y = 4;
    
            g.setColor(new Color(0, 0, 0, 0.9f));
            g.fillRect(x, y, 512, 20);
            g.setColor(Color.red);
    
            g.setColor(Color.decode("#00f6ff"));
            g.setFont(new Font("Arial", Font.BOLD, 12));
            g.drawString("mercRCAir", x + 5, y + 15);
            g.setColor(Color.white);
            String str = String.format("Runtime: %s   XP/hr: %sk   Level: %s (+%s)",
                    timeRunningString,
                    xpPerHour / 1000,
                    (startLevel + gainedLevel),
                    gainedLevel
                    );
            g.drawString(str, x + 75, y + 15);
        }
    
    }
    

  • Script Writer

    Nice job on your first script!

    If you want to minimize interactions, you should use Time.sleepUntil() or Time.sleepWhile(), this will have the script sleep until a condition is met or it has timed out.

    For example, after you interact with the altar, you can use something like this:

    final String RUNE_ESSENCE = "Rune essence";
    Time.sleepWhile(() -> Inventory.contains(RUNE_ESSENCE), 2000); 
    

    This will make the script sleep while your inventory contains rune essence, if the condition still remains true after 2000ms (2 seconds) then the sleep method will time out and the script will move on.



  • @Constellation Thanks for the input.
    Yeah I'll use those conditional sleeps in future scripts.
    The accuracy of the client is unreal - so much easier to script with this than the clients I used in the past.



  • Nice work! This is my first time scripting as well and I wanted a RC'er for F2P. I made a few changes to this to suit my needs:

    • Changed it from pure essence to use rune essence
    • Removed need for tele ring
    • Added a few more outputs for each step

    Using your structure it shouldn't be too hard to implement other runes as well. I might do that when I get some time. Good stuff mate!

    I don't understand the return values (500, 1000, 1500) can anyone explain that? Has it got something to do with the loop function executing a wait depending on what it returns?

    import org.rspeer.runetek.api.component.Bank;
    import org.rspeer.runetek.api.component.tab.Inventory;
    import org.rspeer.runetek.api.component.tab.Skill;
    import org.rspeer.runetek.api.component.tab.Skills;
    import org.rspeer.runetek.api.movement.Movement;
    import org.rspeer.runetek.api.movement.position.Area;
    import org.rspeer.runetek.api.movement.position.Position;
    import org.rspeer.runetek.api.scene.Players;
    import org.rspeer.runetek.event.listeners.RenderListener;
    import org.rspeer.runetek.event.types.RenderEvent;
    import org.rspeer.script.Script;
    import org.rspeer.script.ScriptCategory;
    import org.rspeer.script.ScriptMeta;
    import org.rspeer.ui.Log;
    import org.rspeer.runetek.api.scene.SceneObjects;
    import org.rspeer.runetek.adapter.scene.SceneObject;
    
    import java.awt.*;
    import java.time.LocalTime;
    
    @ScriptMeta(developer = "merc", desc = "Crafts Air Runes", name = "mercRCAir", category = ScriptCategory.RUNECRAFTING)
    public class AirCraft extends Script implements RenderListener {
    
        enum metaLocations {BANK, RUINS, ALTAR, UNKNOWN}
        Long startTime = 0L;
        int startXp = 0;
        int startLevel = 0;
        int gainedXp = 0;
        int gainedLevel = 0;
        int xpPerHour = 0;
        String timeRunningString = "";
    
        @Override
        public void onStart() {
            startTime = System.currentTimeMillis();
            startXp = Skills.getExperience(Skill.RUNECRAFTING);
            startLevel = Skills.getLevel(Skill.RUNECRAFTING);
        }
    
        @Override
        public int loop() {
    
            metaLocations loc = getMetaLocation();
    
            if(isInventoryReady()){ // Going towards ruins
                if(loc == metaLocations.RUINS) {
                    return enterRuins();
                } else if (loc == metaLocations.ALTAR){
                    return craftRunes();
                } else {
                    return walkToRuin();
                }
            } else { // Going towards bank
                if(loc == metaLocations.BANK){
                    return doBank();
                } else {
                    if(loc == metaLocations.ALTAR){
                        return leaveAltar();
                    } else {
                        return walkToBank();
                    }
                }
            }
    
        }
    
    
        int doBank(){
            if (Movement.isDestinationSet() || Players.getLocal().isMoving()) {
                return 500;
            }
            Log.info("getting mats");
            if (Bank.isClosed()) {
                Bank.open();
                return 1500;
            }
    
            if (!Bank.containsAll(1436)) {
                Log.info("Bank ran out of resources");
                setStopping(true);
                return 500;
            }
    
            if (Inventory.containsAnyExcept(1436)) {
                Bank.depositInventory();
                return 1000;
            }
            if (Inventory.getFreeSlots() > 0) {
                Bank.withdrawAll(1436);
                return 1000;
            }
    
            return 500;
        }
    
        int enterRuins() {
            if (Movement.isDestinationSet() || Players.getLocal().isMoving() || Players.getLocal().isAnimating())
                return 300;
            Log.info("entering ruins");
            SceneObject ruins = SceneObjects.getNearest("Mysterious ruins");
            ruins.interact("Enter");
            return 1000;
        }
    
        int craftRunes(){
            if (Movement.isDestinationSet() || Players.getLocal().isMoving() || Players.getLocal().isAnimating())
                return 300;
            Log.info("Crafting runes");
            SceneObject altar = SceneObjects.getNearest("Altar");
            altar.interact("Craft-rune");
            return 1500;
        }
    
        int leaveAltar(){
            SceneObject portal = SceneObjects.getNearest("Portal");
    
            if (Players.getLocal().isMoving() || Players.getLocal().isAnimating() || (Movement.isDestinationSet() && portal.getPosition().distance(Movement.getDestination()) < 3))
                return 300;
    
            Log.info("leaving altar");
            portal.interact("Use");
            if (!Movement.isRunEnabled() && Movement.getRunEnergy() > 80) {
                Movement.toggleRun(true);
            }
            calcProgress();
            return 1500;
        }
    
        int walkToBank() {
            Position bank = new Position(3012, 3357, 0);
            if (!Movement.isDestinationSet() || Movement.getDestinationDistance() < 7 || !Players.getLocal().isMoving()) {
                Log.info("walking to bank");
                Movement.walkToRandomized(bank);
            }
            return 300;
        }
    
        int walkToRuin() {
            Position ruin = new Position(2990, 3295, 0);
            if (!Movement.isDestinationSet() || Movement.getDestinationDistance() < 7 || !Players.getLocal().isMoving()) {
                Log.info("walking to ruin");
                Movement.walkToRandomized(ruin);
            }
            return 300;
        }
    
    
        metaLocations getMetaLocation(){
            Area faladorWestBank = Area.rectangular(3003, 3364, 3027, 3346);
            Area airRuins = Area.rectangular(2973, 3302, 2996, 3283);
            Area airAltar = Area.rectangular(2836, 4841, 2852, 4825);
    
            Position pos = Players.getLocal().getPosition();
    
            if (faladorWestBank.contains(pos)){
                return metaLocations.BANK;
            } else if (airRuins.contains(pos)){
                return metaLocations.RUINS;
            } else if (airAltar.contains(pos)){
                return metaLocations.ALTAR;
            } else {
                return metaLocations.UNKNOWN;
            }
        }
    
        boolean isInventoryReady(){
            return !Inventory.containsAnyExcept(1436) && Inventory.getFreeSlots() == 0;
        }
    
        void calcProgress(){
            gainedXp = Skills.getExperience(Skill.RUNECRAFTING) - startXp;
            gainedLevel = Skills.getLevel(Skill.RUNECRAFTING) - startLevel;
            Long elapsedTime = System.currentTimeMillis() - startTime;
            xpPerHour = 3600000 / elapsedTime.intValue() * gainedXp;
            timeRunningString = LocalTime.ofSecondOfDay(elapsedTime / 1000).toString();
    
        }
    
        @Override
        public void notify(RenderEvent renderEvent) {
            Graphics g = renderEvent.getSource();
    
    
    
            int x = 4;
            int y = 4;
    
            g.setColor(new Color(0, 0, 0, 0.9f));
            g.fillRect(x, y, 512, 20);
            g.setColor(Color.red);
    
            g.setColor(Color.decode("#00f6ff"));
            g.setFont(new Font("Arial", Font.BOLD, 12));
            g.drawString("mercRCAir", x + 5, y + 15);
            g.setColor(Color.white);
            String str = String.format("Runtime: %s   XP/hr: %sk   Level: %s (+%s)",
                    timeRunningString,
                    xpPerHour / 1000,
                    (startLevel + gainedLevel),
                    gainedLevel
            );
            g.drawString(str, x + 75, y + 15);
        }
    
    }
    


  • @EdwardBudge said in Air Rune Crafter:

    I don't understand the return values (500, 1000, 1500) can anyone explain that? Has it got something to do with the loop function executing a wait depending on what it returns?

    Yep - return value is wait timer.


 

82
Online

11.2k
Users

1.1k
Topics

14.6k
Posts