import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
/**
* Kills Chaos Druids at the Chaos Druid Tower and banks loot at Ardougne North Bank.
*
* Requirements:
* Start script at the Chaos Druid Tower or Ardougne North Bank with sleeping bag in inventory.
*
* Optional Parameter
* (default strength)
*
*
* @Author Chomp
*/
public class AA_ChaosDruidTower extends AA_Script {
private static final Coordinate COORDINATE_LOAD_BANK = new Coordinate(587, 592);
private static final Coordinate COORDINATE_LOAD_TOWER = new Coordinate(600, 591);
private static final int[] ITEM_IDS_LOOT = new int[]{
10, 33, 34, 35, 36, 40, 42,
157, 158, 159, 160, 165,
435, 436, 437, 438, 439, 440, 441, 442, 443, 464, 469,
526, 527, 1092, 1277};
private static final int[] ITEM_IDS_PREMIUM_LOOT = new int[]{438, 439, 441, 442, 443, 469, 526, 527, 1092, 1277};
private static final int NPC_ID_CHAOS_DRUID = 270;
private static final int NPC_XP_CHAOS_DRUID = 58;
private static final int MAXIMUM_FATIGUE = 99;
private static final int MAXIMUM_DISTANCE_FROM_OBJECT = 18;
private static final int MINIMUM_THIEVING = 46;
private final int[] loot = new int[3];
private final Map premiumLoot = new TreeMap<>();
private final Map spawnMap = new HashMap<>();
private Coordinate nextRespawn;
private long startTime;
private double initialCombatXp;
private long towerDoorTimeout;
private int playerX;
private int playerY;
public AA_ChaosDruidTower(final Extension extension) {
super(extension);
}
@Override
public void init(final String parameters) {
if (getLevel(Skill.THIEVING.getIndex()) < MINIMUM_THIEVING) {
throw new IllegalStateException(String.format("You must have L%d+ thieving to use this script.", MINIMUM_THIEVING));
}
if (!hasInventoryItem(ITEM_ID_SLEEPING_BAG)) {
throw new IllegalStateException("Sleeping bag missing from inventory.");
}
if (!parameters.isEmpty()) combatStyle = CombatStyle.valueOf(parameters.toUpperCase());
setCombatStyle(combatStyle.getIndex());
initialCombatXp = getTotalCombatXp();
startTime = System.currentTimeMillis();
}
@Override
public int main() {
playerX = getX();
playerY = getY();
if (bot.getCombatStyle() != combatStyle.getIndex()) setCombatStyle(combatStyle.getIndex());
if (getInventoryCount() == MAX_INV_SIZE || isBanking()) {
return bank();
}
return kill();
}
@Override
public void onServerMessage(final String message) {
if (message.startsWith("fail", 4) || message.startsWith("go", 4)) {
towerDoorTimeout = 0L;
} else {
super.onServerMessage(message);
}
}
private int bank() {
if (Area.BANK.contains(playerX, playerY)) {
if (!isBanking()) {
return openBank();
}
for (int index = 0; index < getInventoryCount(); index++) {
final int itemId = getInventoryId(index);
if (!inArray(ITEM_IDS_LOOT, itemId)) {
continue;
}
deposit(itemId, getInventoryCount(itemId));
return SLEEP_ONE_TICK;
}
updateBankLoot();
closeBank();
return SLEEP_ONE_SECOND;
}
if (!Area.CHAOS_DRUIDS.contains(playerX, playerY)) {
if (playerY > COORDINATE_LOAD_BANK.getY()) {
walkTo(COORDINATE_LOAD_BANK.getX(), COORDINATE_LOAD_BANK.getY());
} else {
walkTo(Area.BANK.upperBoundingCoordinate.getX(), Area.BANK.lowerBoundingCoordinate.getY());
}
return SLEEP_ONE_TICK;
}
if (System.currentTimeMillis() <= towerDoorTimeout) {
return 0;
}
atWallObject(Object.TOWER_DOOR.coordinate.getX(), Object.TOWER_DOOR.coordinate.getY());
towerDoorTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS;
return 0;
}
private int kill() {
if (Area.CHAOS_DRUIDS.contains(playerX, playerY)) {
if (inCombat()) {
return 0;
}
if (getFatigue() >= MAXIMUM_FATIGUE) {
return sleep();
}
final int[] druid = getNpcById(NPC_ID_CHAOS_DRUID);
if (druid[0] != -1) {
attackNpc(druid[0]);
return SLEEP_ONE_TICK;
}
updateLoot();
if (loot[0] != -1) {
pickupItem(loot[0], loot[1], loot[2]);
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_TOWER.getX()) {
if (playerX == Object.TOWER_DOOR.coordinate.getX() && playerY == Object.TOWER_DOOR.coordinate.getY()) {
if (System.currentTimeMillis() <= towerDoorTimeout) {
return 0;
}
atWallObject2(Object.TOWER_DOOR.coordinate.getX(), Object.TOWER_DOOR.coordinate.getY());
towerDoorTimeout = System.currentTimeMillis() + TIMEOUT_TWO_SECONDS;
return 0;
}
walkTo(Object.TOWER_DOOR.coordinate.getX(), Object.TOWER_DOOR.coordinate.getY());
if (getFatigue() != 0 && isWalking()) {
return sleep();
}
return SLEEP_ONE_TICK;
}
walkTo(COORDINATE_LOAD_TOWER.getX(), COORDINATE_LOAD_TOWER.getY());
return SLEEP_ONE_TICK;
}
private void updateBankLoot() {
for (final int itemId : ITEM_IDS_PREMIUM_LOOT) {
final int bankCount = bankCount(itemId);
if (bankCount == 0) {
continue;
}
premiumLoot.put(itemId, bankCount);
}
}
private void updateLoot() {
loot[0] = -1;
int currentDistance = Integer.MAX_VALUE;
for (int index = 0; index < getGroundItemCount(); index++) {
final int groundItemId = getGroundItemId(index);
if (!inArray(ITEM_IDS_LOOT, groundItemId)) {
continue;
}
final int groundItemX = getItemX(index);
final int groundItemY = getItemY(index);
if (!Area.CHAOS_DRUIDS.contains(groundItemX, groundItemY)) {
continue;
}
final int distance = distanceTo(groundItemX, groundItemY);
if (distance < currentDistance) {
loot[0] = groundItemId;
loot[1] = groundItemX;
loot[2] = groundItemY;
currentDistance = distance;
}
}
}
@Override
public void paint() {
int y = PAINT_OFFSET_Y;
drawString("@yel@Chaos Druid Tower", 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_CHAOS_DRUID;
drawString(String.format("@yel@Kills: @whi@%d @cya@(@whi@%s kills@cya@/@whi@hr@cya@)",
kills, toUnitsPerHour(kills, startTime)),
PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT, 1, 0);
if (premiumLoot.isEmpty()) return;
drawString("", PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT, 1, 0);
for (final Map.Entry entry : premiumLoot.entrySet()) {
drawString(String.format("@gre@%s: @whi@%d", getItemNameId(entry.getKey()), entry.getValue()),
PAINT_OFFSET_X, y += PAINT_OFFSET_Y_INCREMENT, 1, 0);
}
}
@Override
public void onNpcSpawned(final java.lang.Object npc) {
if (bot.getNpcId(npc) != NPC_ID_CHAOS_DRUID) {
return;
}
final int npcX = bot.getMobLocalX(npc) + bot.getAreaX();
final int npcY = bot.getMobLocalY(npc) + bot.getAreaY();
final int serverIndex = bot.getMobServerIndex(npc);
final Spawn spawn = spawnMap.get(serverIndex);
if (spawn != null) {
spawn.getCoordinate().set(npcX, npcY);
spawn.setTimestamp(System.currentTimeMillis());
} else {
spawnMap.put(serverIndex, new Spawn(new Coordinate(npcX, npcY), System.currentTimeMillis()));
}
nextRespawn = spawnMap.isEmpty() ? null : spawnMap.values().stream().sorted().findFirst().get().getCoordinate();
}
private enum Area implements RSArea {
CHAOS_DRUIDS(new Coordinate(616, 550), new Coordinate(619, 555)) {
@Override
public boolean contains(final int x, final int y) {
return super.contains(x, y) || ((x == 620 || x == 615) && y > 551 && y < 554);
}
},
BANK(new Coordinate(577, 572), new Coordinate(585, 576));
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 {
TOWER_DOOR(96, new Coordinate(617, 556));
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;
}
}
}