Jump to content
smokehut

Hill Giant Killer C&C

Recommended Posts

I'm providing the full script to the second script I've written, I've tried to make best use of the API. However, on loop methods aren't my strong point and I'm looking for criticisms and preferably ways to improve this script for future developments.

After my account surpassed the requirement for my first 'chicken killer' script, I decided to move onto an area that would provide a little more exp as well as loot. This is a Hill Giant Killer; it prioritises looting over killing and banks when the inventory is full or when out of food. It has a conditional wait after each kill to prevent running around back and forth after a kill to then loot.

Please let me know your opinions as well as any improvements I could apply.

 

import org.osbot.rs07.api.filter.NameFilter;
import org.osbot.rs07.api.map.Area;
import org.osbot.rs07.api.map.Position;
import org.osbot.rs07.api.map.constants.Banks;
import org.osbot.rs07.api.model.GroundItem;
import org.osbot.rs07.api.model.NPC;
import org.osbot.rs07.api.ui.Skill;
import org.osbot.rs07.script.Script;


import org.osbot.rs07.script.ScriptManifest;
import org.osbot.rs07.utility.ConditionalSleep;

import java.awt.*;

@ScriptManifest(name = "Hill Giant Killer", author = "Smokehut", version = 1.0, info = "", logo = "")

public class Main extends Script {

    public static String updateString;
    public static int currentHealth;
    public static int currentEnergy;
    public static String foodType = "Tuna";
    public String[] lootTable = {"Big Bones", "Law rune", "Chaos rune", "Death rune", "Limpwurt root", "Giant key", "Uncut Emerald", "Uncut Sapphire", "Nature rune"};
    public NPC currentGiant;
    public Area cave;
    public int counter = 0;
    public int combatCounter = 0;
    public boolean waitAfterCombat = false;

    @Override

    public void onStart() {
        //Code here will execute before the loop is started
        updateString = "Loading Variables";
        cave = new Area(3095,9853,3125,9824);
    }

    @Override

    public void onExit() {

        //Code here will execute after the script ends

    }

    @Override

    public int onLoop() {
        currentHealth = getSkills().getDynamic(Skill.HITPOINTS);
        currentEnergy = getSettings().getRunEnergy();

        if (currentHealth < getSkills().getStatic(Skill.HITPOINTS) /2 && getInventory().contains(foodType)) {
            getInventory().interact("Eat", foodType);
            updateString = "Eating Food";
        }

        if (isAttackingGiant() && !waitAfterCombat) {
            combatCounter++;
            if (combatCounter > 8) {
                combatCounter = 0;
                waitAfterCombat = true;
                updateString = "Conditional Wait Initiated.";
                return random(700,2000);
            }
        } else {
            combatCounter = 0;
        }

        if (waitAfterCombat && !isAttackingGiant()) {
            counter++;
            if (counter > 9) {
                counter = 0;
                waitAfterCombat = false;
            }
        }

        if (!getInventory().contains(foodType) || inventory.isFull()) {
            //we need to bank!

            if (Banks.VARROCK_WEST.contains(myPlayer().getPosition())) {
                //We're in the bank, lets sort our inventory.
                updateString = "We're in the bank!";

                if (bank.isOpen()) {
                    if (inventory.isEmpty()) {
                        bankHandling();
                    } else {
                        bank.depositAll();
                    }
                } else {
                    getObjects().closest("Bank booth").interact("Bank");
                }
            } else {
                //We're not quite at the bank, lets walk there.
                updateString = "Walking to bank";
                getWalking().webWalk(Banks.VARROCK_WEST);
            }

        } else {
            //we're okay to fight
            if (cave.contains(myPlayer().getPosition())){

                //Sets run energy
                if (currentEnergy > 50 && !getSettings().isRunning()) {
                    getSettings().setRunning(true);
                    updateString = "Setting Run Energy";
                }

                if (lootExists() && !myPlayer().isMoving() && !isAttackingGiant() && !inventory.isFull()) {
                    updateString = "Collecting loot";
                    //Collect Loot
                    pickupLoot();
                } else {
                    //Fight
                    if (!isAttackingGiant() && !myPlayer().isMoving() && !waitAfterCombat) {
                        updateString = "Looking to fight!";
                        attackGiant();
                    }
                }
            } else {
                getWalking().webWalk(cave);
            }
        }
        return random(700,800); //The amount of time in milliseconds before the loop starts over
    }
    //Fighting Methods
    private boolean isAttackingGiant() {
        return currentGiant != null && currentGiant.exists() && currentGiant.getHealthPercent() > 0 && myPlayer().isInteracting(currentGiant) && currentGiant.isUnderAttack();
    }

    private void attackGiant() {
        currentGiant = getClosestGiant();

        if (currentGiant != null && currentGiant.interact("Attack")) {
            new ConditionalSleep(5000) {
                @Override
                public boolean condition() throws InterruptedException {
                    return myPlayer().isInteracting(currentGiant) || !isAttackableTarget(currentGiant);
                }
            };
        }
    }

    public NPC getClosestGiant() {
        return getNpcs().closest(new NameFilter<>("Hill Giant"), this::isAttackableTarget);
    }

    private boolean isAttackableTarget(final NPC target) {
        return target != null && target.exists() && target.getHealthPercent() > 0 && !target.isUnderAttack() && !isSplashed(target) && isInArea(target.getPosition());
    }

    private boolean isSplashed(NPC target) {
        return !getPlayers().filter(p -> p.isInteracting(target)).isEmpty();
    }

    private boolean isInArea(Position target) {
        return cave.contains(target);
    }

    //Looting Methods

    private boolean lootExists() {
        for (int i = 0; i < lootTable.length; i++) {
            GroundItem item = groundItems.closest(lootTable[i]);
            if (item != null && item.exists()) {
                return true;
            }
        }
        return false;
    }

    private void pickupLoot() {
        for (int i = 0; i < lootTable.length; i++) {
            GroundItem item = groundItems.closest(lootTable[i]);

            if (item != null && item.exists()) {
                if (item.isVisible()) {
                    item.interact("Take");
                } else {
                    getWalking().walk(item.getPosition());
                }
            }
        }
    }

    //Banking Methods

    private void bankHandling() {
        bank.withdraw("Brass key", 1);
        bank.withdraw(foodType, 5);
        bank.close();
    }

    @Override

    public void onPaint(Graphics2D g) {

        g.setColor(Color.WHITE);

        //This is where you will put your code for paint(s)
        g.drawString(updateString, 10, 10);

        // Get current mouse position
        Point mP = getMouse().getPosition();

        // Draw a line from top of screen (0), to bottom (500), with mouse x coordinate
        g.drawLine(mP.x, 0, mP.x, 500);

        // Draw a line from left of screen (0), to right (800), with mouse y coordinate
        g.drawLine(0, mP.y, 800, mP.y);

        //This is where you will put your code for paint(s)

    }

}

This is merely provided to assist my improvement, if people are not happy with me sharing a full script or it devalues another, please let me know and I'll remove.

Edited by smokehut
Link to comment
Share on other sites

59 minutes ago, El_Maestro said:

I would recommend breaking up your scripts into multiple classes and using github to share them. It's bad practice put everything into one class. As for the use of the API, I am also new to it so all I can say is congratz on release!:D

Yeah I can imagine that will help once I develop a script that requires a lot more code. I've made quite a few changes to it since I've posted it here. For instance, there's now an allocated loot item as opposed to two separate loot loops, I found it would dance between the two loot items. I've also removed the splash method as it needs work, as I think it it recognises the player's own interaction.

Link to comment
Share on other sites

Your loop method is a little unwieldy. Try to make it a series of calls instead:

updateValues(); // get health etc

if (isFighting()) {
  if (hasFood()) {
    if (lowHealth()) {
      eat();
    }
  } else {
    if (lowHealth()) {
      goToBank();
    }
  }
} else if (isLootValid()) {
  loot();
} else {
  // etc.
}

This is a ad hoc example of a high-level loop function. Instead of crunching numbers, we do some logic instead. That way, you can tell what the script is doing and what you can expect it to do.

Link to comment
Share on other sites

10 minutes ago, liverare said:

Your loop method is a little unwieldy. Try to make it a series of calls instead:


updateValues(); // get health etc

if (isFighting()) {
  if (hasFood()) {
    if (lowHealth()) {
      eat();
    }
  } else {
    if (lowHealth()) {
      goToBank();
    }
  }
} else if (isLootValid()) {
  loot();
} else {
  // etc.
}

This is a ad hoc example of a high-level loop function. Instead of crunching numbers, we do some logic instead. That way, you can tell what the script is doing and what you can expect it to do.

Thanks for the tip, this does make a lot more sense to approach it this way.

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.

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...