import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; /** * Trains at the Pirate Hut west of the Mage Arena. *

* Required: * Start script at the Pirate Hut. * Inventory: lockpick, sleeping bag, weapon, body, legs/shield, str ammy, cape of legends. * Bank: lockpicks, sleeping bags, str ammies, capes of legends. * Amulet and cape are optional. *

* Optional Parameter: * (default strength) *

* Notes: * PathWalker is used to return to the Pirate Hut if pked. * Protect item is enabled if hits drop below 35. * Eats the half a red berry pie spawn to heal. *

* * @Author Chomp */ public class AA_PirateHut extends AA_Script { private static final Coordinate COORDINATE_LOAD_PIRATE_HUT = new Coordinate(291, 141); private static final Coordinate COORDINATE_LOAD_DRAYNOR_BANK = new Coordinate(176, 642); private static final Coordinate COORDINATE_HALF_A_REDBERRY_PIE = new Coordinate(265, 102); private static final Coordinate COORDINATE_WALKBACK_DRAYNOR = new Coordinate(214, 632); private static final Coordinate COORDINATE_WALKBACK_ICE_PLATEAU = new Coordinate(330, 160); private static final Pattern PATTERN_PROJECTILE_SHOT = Pattern.compile("Warning! (.+) is shooting at you!"); private static final int[] ITEM_IDS_LOOT = new int[]{1277, 1092}; private static final int NPC_ID_PIRATE = 137; private static final int NPC_XP_PIRATE = 76; private static final int ITEM_ID_LOCKPICK = 714; private static final int ITEM_ID_LEGENDS_CAPE = 1288; private static final int ITEM_ID_STEEL_GAUNTLETS = 698; private static final int ITEM_ID_RUBY_AMULET_OF_STRENGTH = 316; private static final int ITEM_ID_HALF_A_REDBERRY_PIE = 262; private static final int ITEM_ID_PIE_DISH = 251; private static final int PRAYER_INDEX_PROTECT_ITEMS = 8; private static final int FOOD_HEAL_AMOUNT = 3; private static final int MINIMUM_HITS_PROTECT_ITEM = 35; private static final int MAXIMUM_FATIGUE = 99; private final Set pkers = new HashSet<>(3); private final Map spawnMap = new HashMap<>(); private Coordinate nextRespawn; private String attackers = ""; private State state; private PathWalker pathWalker; private double initialCombatXp; private long startTime; private long actionTimeout; private int playerX; private int playerY; private int eatAt; private int amuletCount; private int attackedCount; private int deathCount; private boolean attacked; private boolean died; private boolean collectPies; public AA_PirateHut(final Extension extension) { super(extension); } @Override public void init(final String parameters) { if (!parameters.isEmpty()) combatStyle = CombatStyle.valueOf(parameters.toUpperCase()); setCombatStyle(combatStyle.getIndex()); eatAt = getBaseHits() - FOOD_HEAL_AMOUNT; initialCombatXp = getTotalCombatXp(); setState(State.KILL); startTime = System.currentTimeMillis(); } @Override public int main() { if (died) { if (isDead()) return 0; died = false; } playerX = getX(); playerY = getY(); if (bot.getCombatStyle() != combatStyle.getIndex()) setCombatStyle(combatStyle.getIndex()); switch (state) { case KILL: return kill(); case BANK: return bank(); case WALKBACK: return walkback(); default: return exit("Invalid script state."); } } @Override public void onServerMessage(final String message) { if (message.startsWith("Warning")) { if (attacked) return; final Matcher matcher = PATTERN_PROJECTILE_SHOT.matcher(message); if (!matcher.matches()) return; final String rsn = matcher.group(1); setAttacked(rsn); } else if (message.startsWith("eat", 4) || message.startsWith("fail", 4) || message.startsWith("manage", 4) || message.endsWith("it") || message.endsWith("web") || message.endsWith("lever") || message.endsWith("shut") || message.endsWith("open") || message.endsWith("door")) { actionTimeout = System.currentTimeMillis() + TIMEOUT_ONE_TICK; } else { super.onServerMessage(message); } } @Override public void onDeath() { System.out.printf("[%s] Oh dear! You are dead...%n", this); attacked = false; deathCount++; died = true; resetSpawns(); setState(State.BANK); } private void resetSpawns() { spawnMap.clear(); nextRespawn = null; } private void setAttacked(final String rsn) { System.out.printf("[%s] Attacked by: %s%n", this, rsn); attacked = true; attackedCount++; if (!pkers.contains(rsn)) { pkers.add(rsn); attackers += rsn + " "; } } private int kill() { if (Area.PIRATE_HUT.contains(playerX, playerY)) { if (inCombat()) return 0; if (getCurrentHits() <= eatAt) { final int pieIndex = getInventoryIndex(ITEM_ID_HALF_A_REDBERRY_PIE); if (pieIndex != -1) { if (System.currentTimeMillis() <= actionTimeout) return 0; useItem(pieIndex); actionTimeout = System.currentTimeMillis() + TIMEOUT_ONE_SECOND; return 0; } if (!collectPies) collectPies = true; } final int pieDishIndex = getInventoryIndex(ITEM_ID_PIE_DISH); if (pieDishIndex != -1) { dropItem(pieDishIndex); return SLEEP_ONE_TICK; } final int[] loot = getItemById(ITEM_IDS_LOOT); if (loot[0] != -1) { pickupItem(loot[0], loot[1], loot[2]); return SLEEP_ONE_TICK; } if (getFatigue() >= MAXIMUM_FATIGUE) { if (System.currentTimeMillis() <= actionTimeout) return 0; final Coordinate door = Object.PIRATE_HUT_DOOR.getCoordinate(); atWallObject(door.getX(), door.getY()); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } if (collectPies) { if (getInventoryCount() == MAX_INV_SIZE) { collectPies = false; } else if (isItemAt(ITEM_ID_HALF_A_REDBERRY_PIE, COORDINATE_HALF_A_REDBERRY_PIE.getX(), COORDINATE_HALF_A_REDBERRY_PIE.getY())) { pickupItem(ITEM_ID_HALF_A_REDBERRY_PIE, COORDINATE_HALF_A_REDBERRY_PIE.getX(), COORDINATE_HALF_A_REDBERRY_PIE.getY()); return SLEEP_ONE_TICK; } } final int[] pirate = getNpcById(NPC_ID_PIRATE); if (pirate[0] != -1) { attackNpc(pirate[0]); return SLEEP_ONE_TICK; } if (nextRespawn != null && (playerX != nextRespawn.getX() || playerY != nextRespawn.getY())) { walkTo(nextRespawn.getX(), nextRespawn.getY()); return SLEEP_ONE_TICK; } return 0; } if (playerX <= COORDINATE_LOAD_PIRATE_HUT.getX()) { final Coordinate door = Object.PIRATE_HUT_DOOR.getCoordinate(); if (playerX == door.getX() && playerY == door.getY()) { if (getFatigue() >= MAXIMUM_FATIGUE) return sleep(); if (System.currentTimeMillis() <= actionTimeout) return 0; atWallObject2(door.getX(), door.getY()); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } walkTo(door.getX(), door.getY()); return SLEEP_ONE_TICK; } final Coordinate gate = Object.GATE.getCoordinate(); if (playerY < gate.getY()) { walkTo(COORDINATE_LOAD_PIRATE_HUT.getX(), COORDINATE_LOAD_PIRATE_HUT.getY()); return SLEEP_ONE_TICK; } if (distanceTo(gate.getX(), gate.getY()) <= 1) { if (inCombat()) { walkTo(playerX, playerY); return SLEEP_ONE_TICK; } atObject(gate.getX(), gate.getY()); return SLEEP_ONE_SECOND; } walkTo(gate.getX(), gate.getY()); return SLEEP_ONE_TICK; } private int bank() { if (Area.BANK.contains(playerX, playerY)) { if (!isBanking()) return openBank(); if (System.currentTimeMillis() <= actionTimeout) return 0; final int lootIndex = getInventoryIndex(ITEM_IDS_LOOT); if (lootIndex != -1) { deposit(lootIndex, 1); return SLEEP_ONE_TICK; } if (!hasInventoryItem(ITEM_ID_RUBY_AMULET_OF_STRENGTH) && hasBankItem(ITEM_ID_RUBY_AMULET_OF_STRENGTH)) { amuletCount++; withdraw(ITEM_ID_RUBY_AMULET_OF_STRENGTH, 1); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } if (!hasInventoryItem(ITEM_ID_LEGENDS_CAPE) && hasBankItem(ITEM_ID_LEGENDS_CAPE)) { withdraw(ITEM_ID_LEGENDS_CAPE, 1); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } if (!hasInventoryItem(ITEM_ID_LOCKPICK)) { if (!hasBankItem(ITEM_ID_LOCKPICK)) return exit("Out of lockpicks."); withdraw(ITEM_ID_LOCKPICK, 1); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } if (!hasInventoryItem(ITEM_ID_SLEEPING_BAG)) { if (!hasBankItem(ITEM_ID_SLEEPING_BAG)) return exit("Out of sleeping bags."); withdraw(ITEM_ID_SLEEPING_BAG, 1); actionTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS; return 0; } closeBank(); setState(State.WALKBACK); return 0; } if (playerX >= COORDINATE_LOAD_DRAYNOR_BANK.getX()) { final Coordinate doors = Object.BANK_DOORS.getCoordinate(); if (distanceTo(doors.getX(), doors.getY()) <= 1) { if (getObjectIdFromCoords(doors.getX(), doors.getY()) == Object.BANK_DOORS.id) { atObject(doors.getX(), doors.getY()); return SLEEP_ONE_SECOND; } walkTo(doors.getX(), doors.getY() + 1); return SLEEP_ONE_TICK; } walkTo(doors.getX(), doors.getY()); return SLEEP_ONE_TICK; } if (isPrayerEnabled(PRAYER_INDEX_PROTECT_ITEMS)) { disablePrayer(PRAYER_INDEX_PROTECT_ITEMS); return SLEEP_ONE_TICK; } walkTo(COORDINATE_LOAD_DRAYNOR_BANK.getX(), COORDINATE_LOAD_DRAYNOR_BANK.getY()); return SLEEP_ONE_TICK; } private int walkback() { if (pathWalker != null) { if (pathWalker.walkPath()) return 0; pathWalker = null; setState(State.KILL); return 0; } if (playerX == COORDINATE_WALKBACK_DRAYNOR.getX() && playerY == COORDINATE_WALKBACK_DRAYNOR.getY()) { pathWalker = new PathWalker(bot); pathWalker.init(null); final PathWalker.Path path = pathWalker.calcPath(COORDINATE_WALKBACK_DRAYNOR.getX(), COORDINATE_WALKBACK_DRAYNOR.getY(), COORDINATE_WALKBACK_ICE_PLATEAU.getX(), COORDINATE_WALKBACK_ICE_PLATEAU.getY()); if (path == null) return exit("Failed to calculate path from Draynor to Ice Plateau."); pathWalker.setPath(path); return 0; } if (Area.BANK.contains(playerX, playerY)) { final int legendsCapeIndex = getInventoryIndex(ITEM_ID_LEGENDS_CAPE); if (legendsCapeIndex != -1 && !isItemEquipped(legendsCapeIndex)) { wearItem(legendsCapeIndex); return SLEEP_ONE_TICK; } final int steelGauntletsIndex = getInventoryIndex(ITEM_ID_STEEL_GAUNTLETS); if (steelGauntletsIndex != -1 && !isItemEquipped(steelGauntletsIndex)) { wearItem(steelGauntletsIndex); return SLEEP_ONE_TICK; } final int amuletIndex = getInventoryIndex(ITEM_ID_RUBY_AMULET_OF_STRENGTH); if (amuletIndex != -1 && !isItemEquipped(amuletIndex)) { wearItem(amuletIndex); return SLEEP_ONE_TICK; } final Coordinate doors = Object.BANK_DOORS.getCoordinate(); if (getObjectIdFromCoords(doors.getX(), doors.getY()) == Object.BANK_DOORS.id) { atObject(doors.getX(), doors.getY()); return SLEEP_ONE_SECOND; } } walkTo(COORDINATE_WALKBACK_DRAYNOR.getX(), COORDINATE_WALKBACK_DRAYNOR.getY()); return SLEEP_ONE_TICK; } private void setState(final State state) { this.state = state; } @Override public void paint() { int y = PAINT_OFFSET_Y; drawString("@yel@Pirate Hut", PAINT_OFFSET_X, y, 1, 0); drawString(String.format("@yel@Runtime: @whi@%s", toDuration(startTime)), PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT, 1, 0); final double xpGained = getTotalCombatXp() - initialCombatXp; drawString(String.format("@yel@Xp: @whi@%s @cya@(@whi@%s xp@cya@/@whi@hr@cya@)", DECIMAL_FORMAT.format(xpGained), toUnitsPerHour((int) xpGained, startTime)), PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT * 2, 1, 0); final int kills = (int) xpGained / NPC_XP_PIRATE; drawString(String.format("@yel@Kills: @whi@%d @cya@(@whi@%s per@cya@/@whi@hr@cya@)", kills, toUnitsPerHour(kills, startTime)), PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT, 1, 0); if (attackers.isEmpty()) return; drawString(String.format("@yel@Attacked by: @whi@%s", attackers), PAINT_OFFSET_X, y + PAINT_OFFSET_Y_INCREMENT * 2, 1, 0); } @Override public void onPlayerDamaged(final java.lang.Object player) { if (!inCombat() || player != bot.getPlayer()) return; if (bot.getPlayerCount() > 1 && !attacked) { final String pkerName = getPkerName(); if (pkerName != null) setAttacked(pkerName); } if (getCurrentHits() <= MINIMUM_HITS_PROTECT_ITEM && getCurrentLevel(Skill.PRAYER.getIndex()) > 0 && !isPrayerEnabled(PRAYER_INDEX_PROTECT_ITEMS)) { enablePrayer(PRAYER_INDEX_PROTECT_ITEMS); } } @Override public void onNpcSpawned(final java.lang.Object npc) { if (bot.getNpcId(npc) != NPC_ID_PIRATE) return; final int npcX = getX(npc); final int npcY = getY(npc); final int serverIndex = getServerIndex(npc); final Spawn spawn = spawnMap.get(serverIndex); if (spawn != null) { spawn.getCoordinate().set(npcX, npcY); spawn.setTimestamp(Long.MAX_VALUE); } else { spawnMap.put(serverIndex, new Spawn(new Coordinate(npcX, npcY), Long.MAX_VALUE)); } nextRespawn = getNextRespawn(); } @Override public void onNpcDespawned(final java.lang.Object npc) { final int serverIndex = getServerIndex(npc); final Spawn spawn = spawnMap.get(serverIndex); if (spawn == null) return; spawn.setTimestamp(System.currentTimeMillis()); nextRespawn = getNextRespawn(); } private Coordinate getNextRespawn() { if (spawnMap.isEmpty()) return null; return spawnMap.values().stream().min(Comparator.naturalOrder()).get().getCoordinate(); } private String getPkerName() { for (int index = 0; index < bot.getPlayerCount(); index++) { final java.lang.Object player = bot.getPlayer(index); if (player == bot.getPlayer() || !bot.isMobInCombat(player) || getPlayerX(index) != playerX || getPlayerY(index) != playerY) { continue; } return getPlayerName(index); } return null; } private enum State { KILL, BANK, WALKBACK } private enum Area implements RSArea { BANK(new Coordinate(216, 634), new Coordinate(223, 638)), PIRATE_HUT(new Coordinate(263, 100), new Coordinate(269, 110)); private final Coordinate lowerBoundingCoordinate; private final Coordinate upperBoundingCoordinate; Area(final Coordinate lowerBoundingCoordinate, final Coordinate upperBoundingCoordinate) { this.lowerBoundingCoordinate = lowerBoundingCoordinate; this.upperBoundingCoordinate = upperBoundingCoordinate; } public Coordinate getLowerBoundingCoordinate() { return lowerBoundingCoordinate; } public Coordinate getUpperBoundingCoordinate() { return upperBoundingCoordinate; } } private enum Object implements RSObject { BANK_DOORS(64, new Coordinate(219, 633)), PIRATE_HUT_DOOR(99, new Coordinate(270, 104)), GATE(346, new Coordinate(331, 142)); private final int id; private final Coordinate coordinate; Object(final int id, final Coordinate coordinate) { this.id = id; this.coordinate = coordinate; } public int getId() { return id; } public Coordinate getCoordinate() { return coordinate; } } }