Equinox

EquinoxGraahkCrafter.java

Sep 11th, 2011
871
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Java 44.75 KB | None | 0 0
  1. import java.awt.*;
  2. import java.awt.event.MouseEvent;
  3. import java.awt.event.MouseListener;
  4. import java.text.DecimalFormat;
  5. import java.util.*;
  6. import java.util.List;
  7.  
  8. import org.rsbot.event.events.MessageEvent;
  9. import org.rsbot.event.listeners.*;
  10. import org.rsbot.script.Script;
  11. import org.rsbot.script.ScriptManifest;
  12. import org.rsbot.script.methods.*;
  13. import org.rsbot.script.methods.Game.Tab;
  14. import org.rsbot.script.wrappers.*;
  15. import org.rsbot.script.wrappers.RSPath.TraversalOption;
  16. import org.rsbot.util.StringUtil;
  17.  
  18. @ScriptManifest(authors = "Equinox_", keywords = { "Runecrafting", "Graahk",
  19.     "Nature", "Karamja" }, name = "EquinoxGraahkCrafter", version = 1.42, description = "Nature Runecrafter with Graahks, pouches and more!")
  20. public class EquinoxGraahkCrafter extends Script implements MessageListener,
  21.     PaintListener, MouseListener {
  22.  
  23.     // Variables
  24.     public final static int NATURE_RUNE_ID = 561;
  25.     public final static int COSMIC_RUNE_ID = 564;
  26.     public final static int ASTRAL_RUNE_ID = 9075;
  27.     public static final int AIR_STAFF_ID = 1405;
  28.     public final static int PURE_ESS_ID = 7936;
  29.     public final static int NATURE_PORTAL_ID = 2460;
  30.     public final static int NATURE_ALTER_ID = 2486;
  31.     public final static int AIR_RUNE_ID = 556;
  32.     public final static int SPIRIT_GRAAHK_POUCH_ID = 12810;
  33.     public final static int OBELISK_OBJ_ID = 29938;
  34.     public final static int KINSHIP_TELEPORT_ANIM = 13652;
  35.     public final static int[] GRAAHK_TELEPORT_ANIM = { 8939, 8941 };
  36.     public final static int NPC_CONTACT_ANIM = 4413;
  37.     public final static int BANKER_ID = 9710;
  38.     public final static int CRAFT_RUNE_ANIM = 791;
  39.     public final static int OMNI_TIARA = 13655;
  40.     public final static int OMNI_STAFF = 13642;
  41.  
  42.     public final static RSTile[][] DAEMONHEIM_MESH = {
  43.         { new RSTile(3453, 3897), new RSTile(3447, 3897) },
  44.         { new RSTile(3448, 3702), new RSTile(3451, 3702) },
  45.         { new RSTile(3451, 3707), new RSTile(3448, 3707) },
  46.         { new RSTile(3448, 3711), new RSTile(3451, 3711) },
  47.         { new RSTile(3451, 3716), new RSTile(3448, 3716) },
  48.         { new RSTile(3448, 3719), new RSTile(3449, 3719),
  49.             new RSTile(3449, 3718) } };
  50.  
  51.     public final static RSTile[][] KARAMJA_MESH = {
  52.         { new RSTile(2793, 3009), new RSTile(2793, 3009) },
  53.         { new RSTile(2798, 3009), new RSTile(2796, 3008) },
  54.         { new RSTile(2808, 3007), new RSTile(2809, 3013) },
  55.         { new RSTile(2815, 3013), new RSTile(2815, 3007) },
  56.         { new RSTile(2822, 3008), new RSTile(2823, 3013) },
  57.         { new RSTile(2829, 3016), new RSTile(2834, 3009) },
  58.         { new RSTile(2838, 3017), new RSTile(2831, 3021) },
  59.         { new RSTile(2837, 3028), new RSTile(2842, 3025) },
  60.         { new RSTile(2847, 3025), new RSTile(2847, 3030) },
  61.         { new RSTile(2852, 3030), new RSTile(2852, 3025) },
  62.         { new RSTile(2855, 3027), new RSTile(2856, 3031) },
  63.         { new RSTile(2861, 3029), new RSTile(2859, 3024) },
  64.         { new RSTile(2864, 3017), new RSTile(2864, 3023) },
  65.         { new RSTile(2869, 3021), new RSTile(2866, 3021),
  66.             new RSTile(2866, 3017), new RSTile(2869, 3017) } };
  67.  
  68.     public final static int POUCH_TRIES = 20;
  69.  
  70.     // Pouch IDs
  71.     public static class Pouch {
  72.     public final static int SMALL = 5509;
  73.     public final static int MEDIUM = 5510;
  74.     public final static int MEDIUM_DEGRADED = 5511;
  75.     public final static int LARGE = 5512;
  76.     public final static int LARGE_DEGRADED = 5513;
  77.     public final static int GIANT = 5514;
  78.     public final static int GIANT_DEGRADED = 5515;
  79.     public final static int[] ALL = { SMALL, MEDIUM, MEDIUM_DEGRADED,
  80.         LARGE, LARGE_DEGRADED, GIANT, GIANT_DEGRADED };
  81.     public final static int[] ALL_REPAIRED = { SMALL, MEDIUM, LARGE, GIANT };
  82.     public final static int[] ALL_DEGRADED = { MEDIUM_DEGRADED,
  83.         LARGE_DEGRADED, GIANT_DEGRADED };
  84.     public final static int[] ALL_DEGRADEABLE = { MEDIUM, MEDIUM_DEGRADED,
  85.         LARGE, LARGE_DEGRADED, GIANT, GIANT_DEGRADED };
  86.     }
  87.  
  88.     public String serverMsg = "";
  89.     public HashMap<PouchType, Boolean> pouches = new HashMap<PouchType, Boolean>();
  90.     State currentState = State.LOST;
  91.     public MeshPath karamjaMeshPath;
  92.     public MeshPath daemonheimMeshPath;
  93.     public NPCContact npcContact = new NPCContact();
  94.     public OptionsClass Options = new OptionsClass();
  95.     public SkillPaint skillPaint;
  96.     public int natsMade = 0;
  97.     public int essUsed = 0;
  98.     public int essPrice = 0, natPrice = 0;
  99.  
  100.     public static class OptionsClass {
  101.     public Range mouseSpeed = new Range(4, 6);
  102.     public boolean hasAirStaff = true;
  103.     public Range summoningRecharge = new Range(20, 25);
  104.     public Range walkingDistance = new Range(4, 6);
  105.     public StaffTiara stafftiara;
  106.  
  107.     public enum StaffTiara {
  108.         OMNI_STAFF(Equipment.WEAPON, "staff", "omni"), OMNI_TIARA(
  109.             Equipment.HELMET, "tiara", "omni"), NATURE_TIARA(
  110.             Equipment.HELMET, "tiara", "nature");
  111.         private String d1;
  112.         private String d2;
  113.         private int slot;
  114.  
  115.         private StaffTiara(int slot, String d1, String d2) {
  116.         this.d1 = d1;
  117.         this.d2 = d2;
  118.         this.slot = slot;
  119.         }
  120.  
  121.         public int getSlot() {
  122.         return slot;
  123.         }
  124.  
  125.         public boolean isValid(RSItem itm) {
  126.         return itm != null
  127.             && itm.getName() != null
  128.             && itm.getName().toLowerCase()
  129.                 .contains(d1.toLowerCase())
  130.             && itm.getName().toLowerCase()
  131.                 .contains(d2.toLowerCase());
  132.         }
  133.  
  134.         public static StaffTiara getCurrent(Equipment e) {
  135.         for (StaffTiara t : values()) {
  136.             if (t.isValid(e.getItem(t.getSlot()))) {
  137.             return t;
  138.             }
  139.         }
  140.         return null;
  141.         }
  142.  
  143.         public String properName() {
  144.         String name = name().replace("_", " ");
  145.         return name.substring(0, 1).toUpperCase()
  146.             + name.substring(1).toLowerCase();
  147.         }
  148.     }
  149.     }
  150.  
  151.     public enum State {
  152.     TELE_TO_BANK, TRAVERSE_DAEMONHEIM, BANK_WITHDRAW_GRAAHK, SUMMON_GRAAHK, DISMISS_WRONG_FAMILIAR, BANK_WITHDRAW_ESS, BANK_DEPOSIT_STUFF, FILL_POUCH, NPC_CONTACT, TELE_TO_KARAMJA, TRAVERSE_KARAMJA, CHARGE_SUMMONING, ENTER_PORTAL, CRAFT_ESSENCE, EMPTY_POUCH, NEAR_BANK, LOST
  153.     }
  154.  
  155.     public enum PouchType {
  156.     Small(Pouch.SMALL), Medium(Pouch.MEDIUM, Pouch.MEDIUM_DEGRADED), Large(
  157.         Pouch.LARGE, Pouch.LARGE_DEGRADED), Giant(Pouch.GIANT,
  158.         Pouch.GIANT_DEGRADED);
  159.     public int[] ids;
  160.  
  161.     private PouchType(int... ids) {
  162.         this.ids = ids;
  163.     }
  164.     }
  165.  
  166.     RSArea NATURE_ALTER = new RSArea(2390, 4835, 2410, 4850);
  167.     RSArea KARAMJA_TRAVEL = new RSArea(2784, 2998, 2872, 3040);
  168.     RSArea DAEMONHEIM_TRAVEL = new RSArea(3435, 3680, 3456, 3726);
  169.  
  170.     public State getState() throws Exception {
  171.     if (objects.getNearest(OBELISK_OBJ_ID) != null
  172.         && summoning.getSummoningPoints() <= Options.summoningRecharge
  173.             .random()
  174.         && calc.tileOnMap(objects.getNearest(OBELISK_OBJ_ID)
  175.             .getLocation())) {
  176.         return State.CHARGE_SUMMONING;
  177.     }
  178.     if (objects.getNearest(NATURE_PORTAL_ID) != null
  179.         && calc.tileOnMap(objects.getNearest(NATURE_PORTAL_ID)
  180.             .getLocation())) {
  181.         return State.ENTER_PORTAL;
  182.     }
  183.     if (objects.getNearest(NATURE_ALTER_ID) != null
  184.         && calc.tileOnMap(objects.getNearest(NATURE_ALTER_ID)
  185.             .getLocation())) {
  186.         if ((inventory.isFull() || !pouches.containsValue(true))
  187.             && inventory.contains(PURE_ESS_ID))
  188.         return State.CRAFT_ESSENCE;
  189.         else if (pouches.containsValue(true))
  190.         return State.EMPTY_POUCH;
  191.         else
  192.         return State.TELE_TO_BANK;
  193.     }
  194.     if (npcs.getNearest(Bank.BANKERS) != null) {
  195.         if (npcs.getNearest(Bank.BANKERS) != null
  196.             && (npcs.getNearest(Bank.BANKERS).isOnScreen() || getMyPlayer()
  197.                 .getLocation()
  198.                 .equals(npcs.getNearest(Bank.BANKERS).getLocation()))) {
  199.         if (summoning.isFamiliarSummoned()) {
  200.             if (summoning.getFamiliar() != null)
  201.             if (!summoning.getFamiliar().getName().toLowerCase()
  202.                 .contains("graahk"))
  203.                 return State.DISMISS_WRONG_FAMILIAR;
  204.         } else if (!summoning.isFamiliarSummoned()) {
  205.             if (!inventory.contains(SPIRIT_GRAAHK_POUCH_ID))
  206.             return State.BANK_WITHDRAW_GRAAHK;
  207.             else
  208.             return State.SUMMON_GRAAHK;
  209.         }
  210.         if (shouldRepairPouches())
  211.             return State.NPC_CONTACT;
  212.         else if (inventory.getCount(Pouch.ALL)
  213.             + inventory.getCount(PURE_ESS_ID) != inventory
  214.                 .getCount())
  215.             return State.BANK_DEPOSIT_STUFF;
  216.         else if (inventory.contains(PURE_ESS_ID)
  217.             && pouches.containsValue(false))
  218.             return State.FILL_POUCH;
  219.         else if (!inventory.isFull())
  220.             return State.BANK_WITHDRAW_ESS;
  221.         } else {
  222.         return State.NEAR_BANK;
  223.         }
  224.     }
  225.     if (KARAMJA_TRAVEL.contains(getMyPlayer().getLocation())) {
  226.         return State.TRAVERSE_KARAMJA;
  227.     }
  228.     if (inventory.isFull() && inventory.contains(PURE_ESS_ID)
  229.         && !inventory.contains(NATURE_RUNE_ID)
  230.         && !pouches.containsKey(false)) {
  231.         return State.TELE_TO_KARAMJA;
  232.     }
  233.     if (DAEMONHEIM_TRAVEL.contains(getMyPlayer().getLocation())) {
  234.         return State.TRAVERSE_DAEMONHEIM;
  235.     }
  236.     return State.LOST;
  237.     }
  238.  
  239.     @Override
  240.     public void messageReceived(MessageEvent msg) {
  241.     if (msg.getID() == MessageEvent.MESSAGE_ACTION
  242.         || msg.getID() == MessageEvent.MESSAGE_SERVER) {
  243.         serverMsg = msg.getMessage().toLowerCase();
  244.     }
  245.     }
  246.  
  247.     public void teleportToKaramja() throws Exception {
  248.     daemonheimMeshPath.clearPath();
  249.     if (summoning.doAction("Interact")) {
  250.         for (byte b = 0; b < 15; b++)
  251.         if (interfaces.getComponent(228, 3) != null
  252.             && interfaces.getComponent(228, 3).isValid())
  253.             break;
  254.         else
  255.             sleep(100, 125);
  256.         if (interfaces.getComponent(228, 3).doClick()) {
  257.         sleep(1000, 1250);
  258.         for (byte b = 0; b < 15
  259.             && players.getMyPlayer().getAnimation() == GRAAHK_TELEPORT_ANIM[0]; b++)
  260.             sleep(125, 175);
  261.         return;
  262.         }
  263.     }
  264.     }
  265.  
  266.     public void teleportToDaemonheim() throws Exception {
  267.     if (getMyPlayer().getAnimation() != KINSHIP_TELEPORT_ANIM)
  268.         for (byte b = 0; b < 5; b++)
  269.         if (equipment.getItem(Equipment.RING) != null) {
  270.             RSComponent comp = equipment.getItem(Equipment.RING)
  271.                 .getComponent();
  272.             Point pt = comp.getCenter();
  273.             pt.translate(random(-2, 3), random(-2, 3));
  274.             mouse.click(pt, false);
  275.             sleep(500, 750);
  276.             if (menu.doAction("Teleport")) {
  277.             for (byte b2 = 0; b2 < 25; b2++)
  278.                 if (getMyPlayer().getAnimation() != KINSHIP_TELEPORT_ANIM)
  279.                 sleep(100, 115);
  280.                 else {
  281.                 // Paint.runsMade++;
  282.                 return;
  283.                 }
  284.             }
  285.         } else {
  286.             log.severe("Somehow we are missing a ring :(");
  287.             stopScript(true);
  288.         }
  289.     }
  290.  
  291.     public boolean shouldRepairPouches() {
  292.     int degraded = inventory.getCount(Pouch.ALL_DEGRADED);
  293.     return degraded > 0;
  294.     }
  295.  
  296.     public boolean openBank() {
  297.     if (bank.isOpen())
  298.         return true;
  299.     RSNPC npc = npcs.getNearest(BANKER_ID);
  300.     if (npc != null)
  301.         npc.interact("Bank F");
  302.     sleep(750, 1000);
  303.     return bank.isOpen();
  304.     }
  305.  
  306.     public void deposit_non_necessities() {
  307.     if (!openBank())
  308.         return;
  309.     if (inventory.getCount(Pouch.ALL) > 0)
  310.         bank.depositAllExcept(Pouch.ALL);
  311.     else
  312.         bank.depositAll();
  313.     }
  314.  
  315.     public boolean withdrawItem(int id, int amount) {
  316.     if (!openBank())
  317.         return false;
  318.     boolean returns = bank.withdraw(id, amount);
  319.     sleep(500, 750);
  320.     return returns;
  321.     }
  322.  
  323.     public boolean withdrawEss() {
  324.     return withdrawItem(PURE_ESS_ID, 0);
  325.     }
  326.  
  327.     public int getCountBankInv(int... id) {
  328.     int count = 0;
  329.     if (bank.isOpen())
  330.         count += bank.getCount(id);
  331.     count += inventory.getCount(true, id);
  332.     return count;
  333.     }
  334.  
  335.     public void emptyPouches() {
  336.     for (PouchType pType : pouches.keySet()) {
  337.         if (inventory.isFull())
  338.         break;
  339.         if (inventory.containsOneOf(pType.ids)) {
  340.         if (pouches.get(pType)) {
  341.             RSItem item = inventory.getItem(pType.ids);
  342.             if (item != null) {
  343.             // int invCount = inventory.getCount();
  344.             if (item.interact("Empty"))
  345.                 for (int i = 0; i < POUCH_TRIES; i++) {
  346.                 if (serverMsg != null)
  347.                     if (serverMsg.contains("pouch has no ess")
  348.                         || serverMsg
  349.                             .contains("are no essences in your pouch")) {
  350.                     pouches.put(pType, false);
  351.                     serverMsg = "";
  352.                     sleep(100, 150);
  353.                     break;
  354.                     }
  355.                 sleep(100, 150);
  356.                 }
  357.             }
  358.         }
  359.         } else {
  360.         pouches.remove(pType);
  361.         }
  362.     }
  363.     }
  364.  
  365.     public void fillPouches() {
  366.     for (PouchType pType : pouches.keySet()) {
  367.         if (!inventory.contains(PURE_ESS_ID))
  368.         break;
  369.         if (inventory.containsOneOf(pType.ids)) {
  370.         if (!pouches.get(pType)) {
  371.             RSItem item = inventory.getItem(pType.ids);
  372.             if (item != null) {
  373.             if (item.interact("Fill")) {
  374.                 for (int i = 0; i < POUCH_TRIES; i++) {
  375.                 if (serverMsg != null)
  376.                     if (serverMsg.contains("pouch is ful")) {
  377.                     pouches.put(pType, true);
  378.                     serverMsg = "";
  379.                     break;
  380.                     }
  381.                 sleep(80, 120);
  382.                 }
  383.             }
  384.             }
  385.         }
  386.         } else {
  387.         pouches.remove(pType);
  388.         }
  389.     }
  390.     }
  391.  
  392.     public void updatePouches() {
  393.     for (PouchType pouch : PouchType.values())
  394.         if (inventory.containsOneOf(pouch.ids)) {
  395.         if (!pouches.containsKey(pouch))
  396.             pouches.put(pouch, false);
  397.         } else if (pouches.containsKey(pouch))
  398.         pouches.remove(pouch);
  399.     }
  400.  
  401.     private void loadPrices() {
  402.     log.info("Loading prices...");
  403.     this.essPrice = grandExchange.lookup(PURE_ESS_ID).getGuidePrice();
  404.     log.info("Essence price: " + this.essPrice);
  405.     this.natPrice = grandExchange.lookup(NATURE_RUNE_ID).getGuidePrice();
  406.     log.info("Nature rune price: " + this.natPrice);
  407.     }
  408.  
  409.     @Override
  410.     public boolean onStart() {
  411.     new Thread() {
  412.         @Override
  413.         public void run() {
  414.         loadPrices();
  415.         }
  416.     }.start();
  417.     karamjaMeshPath = new MeshPath(walking, calc, players, KARAMJA_MESH,
  418.         Options.walkingDistance);
  419.     daemonheimMeshPath = new MeshPath(walking, calc, players,
  420.         DAEMONHEIM_MESH, Options.walkingDistance);
  421.     skillPaint = new SkillPaint(skills, Skills.RUNECRAFTING);
  422.     updatePouches();
  423.     mouse.setSpeed(Options.mouseSpeed.random());
  424.     RSItem wep = equipment.getItem(Equipment.WEAPON);
  425.     if (wep != null) {
  426.         Options.hasAirStaff = (wep.getName().toLowerCase()
  427.             .contains("staff") && wep.getName().toLowerCase()
  428.             .contains("air"));
  429.     }
  430.     RSItem ring = equipment.getItem(Equipment.RING);
  431.     if (ring == null || ring.getName() == null
  432.         || !ring.getName().toLowerCase().contains("ring")
  433.         || !ring.getName().toLowerCase().contains("kinship")) {
  434.         log.severe("You must be weilding a ring of kinship!");
  435.         return false;
  436.     }
  437.     Options.stafftiara = OptionsClass.StaffTiara.getCurrent(equipment);
  438.     if (Options.stafftiara == null) {
  439.         log.severe("You must have a Nature Tiara, Omni Tiara, or Omni Staff equipped!");
  440.         return false;
  441.     }
  442.     camera.setPitch(random(0, 10));
  443.     log.info("Script initiation successful!");
  444.     log.info("--Setup--");
  445.     log.info("Air staff: " + (Options.hasAirStaff ? "Yes" : "No"));
  446.     log.info("Walking range: " + Options.walkingDistance.toString());
  447.     log.info("Summoning recharge: " + Options.summoningRecharge.toString());
  448.     log.info("Alter Access Item: " + Options.stafftiara.properName());
  449.     return true;
  450.     }
  451.  
  452.     @Override
  453.     public int loop() {
  454.     mouse.setSpeed(Options.mouseSpeed.random());
  455.     int essPre = inventory.getCount(true, PURE_ESS_ID);
  456.     int natPre = inventory.getCount(true, NATURE_RUNE_ID);
  457.     try {
  458.         currentState = getState();
  459.         switch (currentState) {
  460.         case NEAR_BANK:
  461.         RSNPC banker = npcs.getNearest(Bank.BANKERS);
  462.         if (banker != null) {
  463.             if (!banker.isOnScreen()) {
  464.             RSTile loc = banker.getLocation();
  465.             if (calc.tileOnMap(loc)) {
  466.                 walking.walkTileMM(loc);
  467.                 for (byte b = 0; b < 22; b++)
  468.                 if (banker.isOnScreen()) {
  469.                     sleep(500);
  470.                     break;
  471.                 } else
  472.                     sleep(100, 115);
  473.             }
  474.             }
  475.         }
  476.         break;
  477.         case BANK_DEPOSIT_STUFF:
  478.         this.deposit_non_necessities();
  479.         break;
  480.         case BANK_WITHDRAW_ESS:
  481.         this.withdrawEss();
  482.         break;
  483.         case BANK_WITHDRAW_GRAAHK:
  484.         if (openBank())
  485.             for (byte b = 0; b < 5 && inventory.contains(PURE_ESS_ID); b++) {
  486.             bank.deposit(PURE_ESS_ID, 1);
  487.             sleep(450, 750);
  488.             }
  489.         withdrawItem(SPIRIT_GRAAHK_POUCH_ID, 1);
  490.         break;
  491.         case SUMMON_GRAAHK:
  492.         RSItem p = inventory.getItem(SPIRIT_GRAAHK_POUCH_ID);
  493.         if (p != null) {
  494.             for (byte b = 0; b < 10 && bank.isOpen(); b++) {
  495.             bank.close();
  496.             sleep(500, 750);
  497.             }
  498.             if (summoning.getSummoningPoints() <= 0) {
  499.             log.severe("Out of summoning points :'(");
  500.             stopScript(true);
  501.             } else if (!bank.isOpen())
  502.             p.interact("Summon");
  503.         }
  504.         break;
  505.         case CHARGE_SUMMONING:
  506.         RSObject obby = objects.getNearest(OBELISK_OBJ_ID);
  507.         if (calc.tileOnMap(obby.getLocation())) {
  508.             if (calc.distanceTo(obby) > 5)
  509.             walking.walkTileMM(obby.getLocation());
  510.             if (!obby.isOnScreen())
  511.             camera.turnTo(obby);
  512.             sleep(125, 175);
  513.             obby.doClick();
  514.             sleep(250, 500);
  515.         }
  516.         break;
  517.         case CRAFT_ESSENCE:
  518.         RSObject alter = objects.getNearest(NATURE_ALTER_ID);
  519.         if (!alter.isOnScreen() && !getMyPlayer().isMoving())
  520.             walking.walkTileMM(alter.getArea().getNearestTile(
  521.                 getMyPlayer().getLocation()));
  522.         if (!alter.isOnScreen())
  523.             camera.turnTo(alter);
  524.         alter.doClick();
  525.         for (byte b = 0; b < 25
  526.             && (getMyPlayer().getAnimation() == CRAFT_RUNE_ANIM || getMyPlayer()
  527.                 .isMoving()); b++)
  528.             sleep(100, 125);
  529.         break;
  530.         case DISMISS_WRONG_FAMILIAR:
  531.         this.summoning.doDismiss();
  532.         sleep(500, 600);
  533.         break;
  534.         case EMPTY_POUCH:
  535.         emptyPouches();
  536.         break;
  537.         case ENTER_PORTAL:
  538.         RSObject obj = objects.getNearest(NATURE_PORTAL_ID);
  539.         if (obj != null) {
  540.             if (!obj.isOnScreen()) {
  541.             walking.walkTileMM(obj.getArea().getNearestTile(
  542.                 getMyPlayer().getLocation()));
  543.             camera.turnTo(obj);
  544.             }
  545.             sleep(750);
  546.             if (obj.isOnScreen()) {
  547.             obj.doClick();
  548.             for (byte b = 0; b < 10
  549.                 && objects.getNearest(NATURE_ALTER_ID) == null; b++)
  550.                 sleep(80, 120);
  551.             karamjaMeshPath.clearPath();
  552.             }
  553.         }
  554.         break;
  555.         case FILL_POUCH:
  556.         fillPouches();
  557.         break;
  558.         case NPC_CONTACT:
  559.         npcContact.main();
  560.         break;
  561.         case TELE_TO_BANK:
  562.         teleportToDaemonheim();
  563.         break;
  564.         case TELE_TO_KARAMJA:
  565.         this.teleportToKaramja();
  566.         break;
  567.         case TRAVERSE_DAEMONHEIM:
  568.         if (!daemonheimMeshPath.hasPath())
  569.             daemonheimMeshPath.findPath(MeshPath.MeshPathType.FULL);
  570.         daemonheimMeshPath.traverse();
  571.         break;
  572.         case TRAVERSE_KARAMJA:
  573.         if (!karamjaMeshPath.hasPath())
  574.             karamjaMeshPath
  575.                 .findPath(MeshPath.MeshPathType.WEIGHT_CENTER);
  576.         karamjaMeshPath.traverse();
  577.         break;
  578.         }
  579.     } catch (Exception e) {
  580.     }
  581.     if (walking.getEnergy() > 50 && !walking.isRunEnabled())
  582.         walking.setRun(true);
  583.     int essUsed = essPre - inventory.getCount(true, PURE_ESS_ID);
  584.     int natsMade = inventory.getCount(true, NATURE_RUNE_ID) - natPre;
  585.     if (natsMade > 0)
  586.         this.natsMade += natsMade;
  587.     if (essUsed > 0)
  588.         this.essUsed += essUsed;
  589.     return random(100, 125);
  590.     }
  591.  
  592.     @Override
  593.     public void onFinish() {
  594.     }
  595.  
  596.     @Override
  597.     public void onRepaint(Graphics g1) {
  598.     Graphics2D g = (Graphics2D) g1;
  599.     try {
  600.         karamjaMeshPath.paintAll(g);
  601.         daemonheimMeshPath.paintAll(g);
  602.         paintPouches(g);
  603.         long elapsed = System.currentTimeMillis()
  604.             - skillPaint.tracker.start;
  605.         int natsHr = (int) (natsMade * 3600000l / elapsed);
  606.         int profit = (natsMade * natPrice) - (essUsed * essPrice);
  607.         int profitHr = (int) (profit * 3600000l / elapsed);
  608.         StringUtil.drawLine(g1, 0,
  609.             "Runtime: " + PaintFormatter.getFormattedTime(elapsed));
  610.         StringUtil.drawLine(g1, 1, "Nats Made: " + natsMade + "@" + natsHr
  611.             + "/hr");
  612.         StringUtil.drawLine(g1, 2, "Profit: " + profit + "@" + profitHr
  613.             + "/hr");
  614.         skillPaint.drawLine(g1, 3);
  615.     } catch (Exception e) {
  616.     }
  617.     }
  618.  
  619.     public void paintPouches(Graphics g) {
  620.     for (PouchType pouch : pouches.keySet()) {
  621.         if (game.getTab().equals(Tab.INVENTORY)) {
  622.         RSItem item = inventory.getItem(pouch.ids);
  623.         if (item != null) {
  624.             if (!pouches.get(pouch))
  625.             g.setColor(new Color(1f, 0f, 0f, 0.5f));
  626.             else
  627.             g.setColor(new Color(0f, 1f, 0f, 0.5f));
  628.  
  629.             RSComponent c = item.getComponent();
  630.             g.fillRect(c.getAbsoluteX(), c.getAbsoluteY(),
  631.                 c.getWidth(), c.getHeight());
  632.             for (int id : Pouch.ALL_DEGRADED)
  633.             if (item.getID() == id) {
  634.                 g.setColor(Color.WHITE);
  635.                 g.drawString("Degraded", c.getAbsoluteX(),
  636.                     c.getAbsoluteY() + c.getHeight());
  637.                 break;
  638.             }
  639.         }
  640.         }
  641.     }
  642.     }
  643.  
  644.     @Override
  645.     public void mouseClicked(MouseEvent arg0) {
  646.     skillPaint.mouseClicked(arg0);
  647.     }
  648.  
  649.     @Override
  650.     public void mouseEntered(MouseEvent arg0) {
  651.  
  652.     }
  653.  
  654.     @Override
  655.     public void mouseExited(MouseEvent arg0) {
  656.  
  657.     }
  658.  
  659.     @Override
  660.     public void mousePressed(MouseEvent arg0) {
  661.  
  662.     }
  663.  
  664.     @Override
  665.     public void mouseReleased(MouseEvent arg0) {
  666.     }
  667.  
  668.     enum npcContactState {
  669.     CAST, SCROLL, SELECT, WAIT, CONTINUE, MENU, WITHDRAW_ASTRAL, WITHDRAW_COSMIC, WITHDRAW_AIR, OUT_OF_RUNES
  670.     }
  671.  
  672.     class NPCContact {
  673.     public npcContactState currentState = npcContactState.WAIT;
  674.     private final int MAIN_FRAME = 88;
  675.     private final int SCROLL_BAR = 20;
  676.     private final int SCROLL_BAR_DOWN = 0;
  677.     private final int VISIBLE_NPCS_CONTAINER = 21;
  678.     private final int NPCS_CONTAINER = 22;
  679.     private final int NPC_CONTACT_ANIM = 4413;
  680.  
  681.     private final int NPC_TO_SELECT = 14;
  682.     private final String[] MENU_ITEM = { "repair", "pouch" };
  683.  
  684.     private npcContactState getState() {
  685.         if (interfaces.get(MAIN_FRAME).isValid()) {
  686.         if (interfaces.get(MAIN_FRAME).getComponent(NPCS_CONTAINER)
  687.             .isValid()) {
  688.             Point npcPoint = interfaces.get(MAIN_FRAME)
  689.                 .getComponent(NPCS_CONTAINER)
  690.                 .getComponent(NPC_TO_SELECT).getCenter();
  691.             Rectangle visible = interfaces.get(MAIN_FRAME)
  692.                 .getComponent(VISIBLE_NPCS_CONTAINER).getArea();
  693.             if (!visible.contains(npcPoint))
  694.             return npcContactState.SCROLL;
  695.             else
  696.             return npcContactState.SELECT;
  697.         }
  698.         }
  699.  
  700.         if (interfaces.canContinue())
  701.         return npcContactState.CONTINUE;
  702.  
  703.         if (getComponent(MENU_ITEM) != null)
  704.         return npcContactState.MENU;
  705.  
  706.         if (!interfaces.canContinue()
  707.             && getMyPlayer().getAnimation() != NPC_CONTACT_ANIM
  708.             && getComponent(MENU_ITEM) == null
  709.             && getComponent("lease wai") == null) {
  710.         if (!inventory.contains(ASTRAL_RUNE_ID))
  711.             return npcContactState.WITHDRAW_ASTRAL;
  712.         if (!inventory.contains(COSMIC_RUNE_ID))
  713.             return npcContactState.WITHDRAW_COSMIC;
  714.         if (inventory.getCount(true, AIR_RUNE_ID) < 2
  715.             && !Options.hasAirStaff)
  716.             return npcContactState.WITHDRAW_AIR;
  717.         return npcContactState.CAST;
  718.         }
  719.         return npcContactState.WAIT;
  720.     }
  721.  
  722.     private RSComponent getComponent(String... s) {
  723.         RSInterface[] valid = interfaces.getAll();
  724.         for (RSInterface iface : valid) {
  725.         if (iface.getIndex() != 137) {
  726.             int len = iface.getChildCount();
  727.             for (int i = 0; i < len; i++) {
  728.             RSComponent child = iface.getComponent(i);
  729.             boolean b = (child.isValid()
  730.                 && child.getAbsoluteX() > 10 && child
  731.                 .getAbsoluteY() > 300);
  732.             for (String sub : s)
  733.                 if (!child.getText().toLowerCase()
  734.                     .contains(sub.toLowerCase()))
  735.                 b = false;
  736.             if (b)
  737.                 return child;
  738.             }
  739.         }
  740.         }
  741.         return null;
  742.     }
  743.  
  744.     boolean invBank(int id) {
  745.         return bank.getCount(id) > 0 || inventory.containsOneOf(id);
  746.     }
  747.  
  748.     int invBankCount(int id) {
  749.         return bank.getCount(id) + inventory.getCount(true, id);
  750.     }
  751.  
  752.     public void main() {
  753.         switch (currentState = getState()) {
  754.         case WITHDRAW_ASTRAL:
  755.         withdrawItem(ASTRAL_RUNE_ID, 1);
  756.         if (!invBank(ASTRAL_RUNE_ID))
  757.             removePouches();
  758.         sleep(500, 650);
  759.         break;
  760.         case WITHDRAW_COSMIC:
  761.         withdrawItem(COSMIC_RUNE_ID, 1);
  762.         if (!invBank(COSMIC_RUNE_ID))
  763.             removePouches();
  764.         sleep(500, 650);
  765.         break;
  766.         case WITHDRAW_AIR:
  767.         if (!inventory.contains(AIR_RUNE_ID))
  768.             withdrawItem(AIR_RUNE_ID, 1);
  769.         withdrawItem(AIR_RUNE_ID, 1);
  770.         if (invBankCount(AIR_RUNE_ID) < 2)
  771.             removePouches();
  772.         sleep(500, 650);
  773.         break;
  774.         case CAST:
  775.         for (byte b = 0; b < 10 && bank.isOpen(); b++) {
  776.             bank.close();
  777.             sleep(500, 750);
  778.         }
  779.         if (!bank.isOpen() && !game.getTab().equals(Tab.MAGIC))
  780.             game.openTab(Tab.MAGIC);
  781.  
  782.         sleep(500, 1250);
  783.         magic.castSpell(Magic.SPELL_NPC_CONTACT);
  784.         sleep(750, 1250);
  785.         break;
  786.         case SCROLL:
  787.         // Scroll
  788.         RSComponent bar = interfaces.get(MAIN_FRAME)
  789.             .getComponent(SCROLL_BAR).getComponent(SCROLL_BAR_DOWN);
  790.         Point p = bar.getCenter();
  791.         p.y = bar.getAbsoluteY() + bar.getHeight() - 5;
  792.         mouse.click(p, true);
  793.         sleep(750, 1250);
  794.         break;
  795.         case SELECT:
  796.         interfaces.get(MAIN_FRAME).getComponent(NPCS_CONTAINER)
  797.             .getComponent(NPC_TO_SELECT).doClick();
  798.         sleep(750, 1250);
  799.         break;
  800.         case WAIT:
  801.         sleep(500, 600);
  802.         break;
  803.         case CONTINUE:
  804.         if (interfaces.canContinue())
  805.             interfaces.clickContinue();
  806.         sleep(500, 650);
  807.         break;
  808.         case MENU:
  809.         if (getComponent(MENU_ITEM) != null)
  810.             getComponent(MENU_ITEM).doClick();
  811.         break;
  812.         }
  813.         sleep(900, 1200);
  814.     }
  815.  
  816.     public void removePouches() {
  817.         if (!openBank())
  818.         return;
  819.         // not enough runes, bank pouches:
  820.         for (int id : Pouch.ALL_DEGRADED)
  821.         if (inventory.contains(id)) {
  822.             bank.deposit(id, 1);
  823.             sleep(500, 600);
  824.         }
  825.         updatePouches();
  826.     }
  827.     }
  828.  
  829.     public static class MeshPath {
  830.     public static final Color BLOCK_PATH_COLOR = new Color(0f, 1f, 0f, 1f);
  831.     public static final Color MESH_BORDER = new Color(0.75f, 0.75f, 0.75f,
  832.         0.75f);
  833.     public static final Color MESH_FILL = new Color(0.5f, 0.5f, 0.5f, 0.75f);
  834.     public static final Color SMOOTH_PATH_COLOR = new Color(0f, 0f, 1f, 1f);
  835.     private List<RSTile> blockPath = new ArrayList<RSTile>();
  836.     private final Calculations calc;
  837.     private boolean end;
  838.     private List<RSTile[]> mesh = new ArrayList<RSTile[]>();
  839.     private final Players players;
  840.     private List<RSTile> smoothPath = new ArrayList<RSTile>();
  841.     private final Walking walking;
  842.     private final Range walkingDistance;
  843.  
  844.     public MeshPath(Walking walking, Calculations calc, Players players) {
  845.         this(walking, calc, players, new Range(7, 9));
  846.     }
  847.  
  848.     public MeshPath(Walking walking, Calculations calc, Players players,
  849.         Range walkingDistance) {
  850.         this.walking = walking;
  851.         this.calc = calc;
  852.         this.players = players;
  853.         this.walkingDistance = walkingDistance;
  854.     }
  855.  
  856.     public MeshPath(Walking walking, Calculations calc, Players players,
  857.         RSTile[][] mesh) {
  858.         this(walking, calc, players);
  859.         setMesh(mesh);
  860.     }
  861.  
  862.     public MeshPath(Walking walking, Calculations calc, Players players,
  863.         RSTile[][] mesh, Range walkingDistance) {
  864.         this(walking, calc, players, walkingDistance);
  865.         setMesh(mesh);
  866.     }
  867.  
  868.     public void addLine(RSTile... tiles) {
  869.         if (mesh.size() == 0) {
  870.         mesh.add(tiles);
  871.         return;
  872.         }
  873.         RSTile first = tiles[0];
  874.         RSTile last = tiles[tiles.length - 1];
  875.         RSTile[] oLine = mesh.get(mesh.size() - 1);
  876.         RSTile oFirst = oLine[0];
  877.         RSTile oLast = oLine[oLine.length - 1];
  878.         double straight = calc.distanceBetween(first, oFirst)
  879.             + calc.distanceBetween(last, oLast);
  880.         double crossed = calc.distanceBetween(first, oLast)
  881.             + calc.distanceBetween(last, oFirst);
  882.         if (straight > crossed) {
  883.         mesh.add(tiles);
  884.         return;
  885.         } else {
  886.         RSTile[] reversed = new RSTile[tiles.length];
  887.         for (int i = 0; i < tiles.length; i++)
  888.             reversed[i] = tiles[tiles.length - 1 - i];
  889.         mesh.add(reversed);
  890.         return;
  891.         }
  892.     }
  893.  
  894.     public void addMesh(RSTile[][] mesh) {
  895.         for (RSTile[] line : mesh)
  896.         addLine(line);
  897.     }
  898.  
  899.     public void clearPath() {
  900.         blockPath.clear();
  901.         smoothPath.clear();
  902.     }
  903.  
  904.     public void findPath() {
  905.         findPath(MeshPathType.WEIGHT_CENTER);
  906.     }
  907.  
  908.     public void findPath(MeshPathType placement) {
  909.         findPath(placement, 0, mesh.size() - 1);
  910.     }
  911.  
  912.     public void findPath(MeshPathType placement, int start, int end) {
  913.         blockPath.clear();
  914.         for (int i = start; i <= end; i++)
  915.         blockPath.add(getTileOnLine(placement, mesh.get(i)));
  916.         smoothPath = smoothPath(blockPath);
  917.     }
  918.  
  919.     public RSTile getEnd() {
  920.         if (smoothPath.size() > 0)
  921.         return smoothPath.get(smoothPath.size() - 1);
  922.         else
  923.         return null;
  924.     }
  925.  
  926.     public RSTile getNext() {
  927.         if (smoothPath.size() > 0)
  928.         for (int i = smoothPath.size() - 1; i >= 0; i--)
  929.             if (calc.tileOnMap(smoothPath.get(i)))
  930.             return smoothPath.get(i);
  931.  
  932.         return null;
  933.     }
  934.  
  935.     public RSTile getStart() {
  936.         if (smoothPath.size() > 0)
  937.         return smoothPath.get(0);
  938.         else
  939.         return null;
  940.     }
  941.  
  942.     public RSTile getTileInMesh(RSTile tile) {
  943.         if (inMesh(tile))
  944.         return tile;
  945.         double bestDist = Double.MAX_VALUE;
  946.         RSTile nearest = null;
  947.         if (mesh.size() > 1) {
  948.         for (int i = 1; i < mesh.size(); i++) {
  949.             RSTile[] lineA = mesh.get(i - 1);
  950.             RSTile[] lineB = mesh.get(i);
  951.             if (lineA != null)
  952.             for (RSTile t : lineA) {
  953.                 double dist = calc.distanceBetween(t, tile);
  954.                 if (dist < bestDist) {
  955.                 nearest = new RSTile(t.getX(), t.getY());
  956.                 bestDist = Double.valueOf(dist);
  957.                 }
  958.             }
  959.             if (lineB != null)
  960.             for (RSTile t : lineB) {
  961.                 double dist = calc.distanceBetween(t, tile);
  962.                 if (dist < bestDist) {
  963.                 nearest = new RSTile(t.getX(), t.getY());
  964.                 bestDist = Double.valueOf(dist);
  965.                 }
  966.             }
  967.         }
  968.         }
  969.         return nearest;
  970.     }
  971.  
  972.     public RSTile getTileOnLine(MeshPathType placement, RSTile... line) {
  973.         List<RSTile> tiles = getTilesOnLines(line);
  974.         int index = 0;
  975.         switch (placement) {
  976.         case ALL_CENTER:
  977.         index = new Range((int) (tiles.size() * .25d),
  978.             (int) (tiles.size() * 0.75d)).random();
  979.         break;
  980.         case FULL:
  981.         index = new Range(0, tiles.size()).random();
  982.         break;
  983.         case WEIGHT_CENTER:
  984.         index = new Range(0, tiles.size()).random();
  985.         break;
  986.         }
  987.  
  988.         if (index < 0)
  989.         index = 0;
  990.         if (index >= tiles.size())
  991.         index = tiles.size() - 1;
  992.  
  993.         if (tiles.size() > 0)
  994.         return tiles.get(index);
  995.         else
  996.         return null;
  997.     }
  998.  
  999.     public RSTile getTileOnLine(RSTile... line) {
  1000.         return getTileOnLine(MeshPathType.WEIGHT_CENTER, line);
  1001.     }
  1002.  
  1003.     public RSTile[] getTilePath() {
  1004.         RSTile[] tiles = new RSTile[smoothPath.size()];
  1005.         for (int i = 0; i < tiles.length; i++)
  1006.         tiles[i] = new RSTile(smoothPath.get(i).getX(), smoothPath.get(
  1007.             i).getY());
  1008.         return tiles;
  1009.     }
  1010.  
  1011.     public List<RSTile> getTilesOnLine(RSTile a, RSTile b) {
  1012.         List<RSTile> sublineTiles = new ArrayList<RSTile>();
  1013.         int deltaX = b.getX() - a.getX();
  1014.         int deltaY = b.getY() - a.getY();
  1015.         double dist = calc.distanceBetween(a, b);
  1016.         if (dist == 0)
  1017.         dist = 1;
  1018.         double eX = deltaX / dist, eY = deltaY / dist;
  1019.         for (int i = 0; i <= dist; i++)
  1020.         sublineTiles.add(new RSTile(a.getX() + (int) (eX * i), a.getY()
  1021.             + (int) (eY * i)));
  1022.         return sublineTiles;
  1023.     }
  1024.  
  1025.     public List<RSTile> getTilesOnLines(RSTile... line) {
  1026.         List<RSTile> sublineTiles = new ArrayList<RSTile>();
  1027.         if (line.length == 1)
  1028.         sublineTiles.add(line[0]);
  1029.         else
  1030.         for (int i = 1; i < line.length; i++) {
  1031.             RSTile a = line[i - 1];
  1032.             RSTile b = line[i];
  1033.             sublineTiles.addAll(getTilesOnLine(a, b));
  1034.         }
  1035.         return sublineTiles;
  1036.     }
  1037.  
  1038.     public boolean hasPath() {
  1039.         return smoothPath.size() > 0;
  1040.     }
  1041.  
  1042.     public boolean inMesh(RSTile tile) {
  1043.         if (mesh.size() > 1) {
  1044.         for (int i = 1; i < mesh.size(); i++) {
  1045.             RSTile[] lineA = mesh.get(i - 1);
  1046.             RSTile[] lineB = mesh.get(i);
  1047.             Polygon poly = new Polygon();
  1048.             if (lineA != null)
  1049.             for (RSTile t : lineA)
  1050.                 poly.addPoint(t.getX(), t.getY());
  1051.             if (lineB != null)
  1052.             for (RSTile t : lineB)
  1053.                 poly.addPoint(t.getX(), t.getY());
  1054.  
  1055.             if (poly.npoints >= 2)
  1056.             if (poly.contains(new Point(tile.getX(), tile.getY())))
  1057.                 return true;
  1058.         }
  1059.         }
  1060.         return false;
  1061.     }
  1062.  
  1063.     public boolean isValid() {
  1064.         return smoothPath.size() > 0 && getNext() != null
  1065.             && !players.getMyPlayer().getLocation().equals(getEnd());
  1066.     }
  1067.  
  1068.     public int meshSize() {
  1069.         return mesh.size();
  1070.     }
  1071.  
  1072.     public void paintAll(Graphics2D g) {
  1073.         paintMesh(g);
  1074.         paintBlockPath(g);
  1075.         paintSmoothPath(g);
  1076.     }
  1077.  
  1078.     public void paintBlockPath(Graphics2D g) {
  1079.         if (blockPath.size() > 1) {
  1080.         g.setColor(BLOCK_PATH_COLOR);
  1081.         Point a = null;
  1082.         for (RSTile t : blockPath) {
  1083.             Point b = calc.tileToMinimap(t);
  1084.             if (b.x > 0 && b.y > 0)
  1085.             g.fillOval(b.x - 2, b.y - 2, 5, 5);
  1086.             if (a != null && a.x > 0 && a.y > 0 && b.x > 0 && b.y > 0)
  1087.             g.drawLine(a.x, a.y, b.x, b.y);
  1088.             a = b;
  1089.         }
  1090.         }
  1091.     }
  1092.  
  1093.     public void paintMesh(Graphics2D g) {
  1094.         if (mesh.size() > 1) {
  1095.         Point[] oldLine = null;
  1096.         for (int i = 0; i < mesh.size(); i++) {
  1097.             RSTile[] lineB = mesh.get(i);
  1098.             Point[] thisLine = new Point[lineB.length];
  1099.             Polygon poly = new Polygon();
  1100.             boolean onMap = true;
  1101.             for (int tile = 0; tile < thisLine.length; tile++) {
  1102.             Point p = calc.tileToMinimap(lineB[tile]);
  1103.             thisLine[tile] = p;
  1104.             poly.addPoint(p.x, p.y);
  1105.             if (p.x == -1 || p.y == -1)
  1106.                 onMap = false;
  1107.             }
  1108.             if (oldLine != null) {
  1109.             for (Point p : oldLine) {
  1110.                 poly.addPoint(p.x, p.y);
  1111.                 if (p.x == -1 || p.y == -1)
  1112.                 onMap = false;
  1113.             }
  1114.             if (poly.npoints >= 2 && onMap) {
  1115.                 g.setColor(MESH_BORDER);
  1116.                 g.draw(poly);
  1117.                 g.setColor(MESH_FILL);
  1118.                 g.fill(poly);
  1119.             }
  1120.             }
  1121.             oldLine = thisLine;
  1122.         }
  1123.         }
  1124.     }
  1125.  
  1126.     public void paintSmoothPath(Graphics2D g) {
  1127.         if (smoothPath.size() > 1) {
  1128.         g.setColor(SMOOTH_PATH_COLOR);
  1129.         Point a = null;
  1130.         for (RSTile t : smoothPath) {
  1131.             Point b = calc.tileToMinimap(t);
  1132.             if (b.x > 0 && b.y > 0)
  1133.             g.fillOval(b.x - 2, b.y - 2, 5, 5);
  1134.             if (a != null && a.x > 0 && a.y > 0 && b.x > 0 && b.y > 0)
  1135.             g.drawLine(a.x, a.y, b.x, b.y);
  1136.             a = b;
  1137.         }
  1138.         }
  1139.     }
  1140.  
  1141.     public MeshPath reverse() {
  1142.         MeshPath m = new MeshPath(walking, calc, players);
  1143.         for (int i = mesh.size() - 1; i >= 0; i--) {
  1144.         m.addLine(blockPath.get(i));
  1145.         }
  1146.         return m;
  1147.     }
  1148.  
  1149.     public void setMesh(RSTile[][] mesh) {
  1150.         this.mesh.clear();
  1151.         addMesh(mesh);
  1152.     }
  1153.  
  1154.     public List<RSTile> smoothPath(List<RSTile> path) {
  1155.         List<RSTile> smoothed = new ArrayList<RSTile>();
  1156.         if (path.size() >= 3) {
  1157.         for (int i = 0; i < path.size(); i++) {
  1158.             if (i + 2 < path.size()) {
  1159.             RSTile tile1 = path.get(i);
  1160.             RSTile tile2 = path.get(i + 1);
  1161.             RSTile tile3 = path.get(i + 2);
  1162.             if (i == 0)
  1163.                 smoothed.add(tile1);
  1164.             double x2, y2;
  1165.             double t = 0.5d;
  1166.             x2 = (tile1.getX() + t
  1167.                 * (-tile1.getX() * 3 + t
  1168.                     * (3 * tile1.getX() - tile1.getX() * t)))
  1169.                 + t
  1170.                 * (3 * tile2.getX() + t
  1171.                     * (-6 * tile2.getX() + tile2.getX() * 3
  1172.                         * t))
  1173.                 + t
  1174.                 * t
  1175.                 * (tile2.getX() * 3 - tile2.getX() * 3 * t)
  1176.                 + tile3.getX() * t * t * t;
  1177.             y2 = (tile1.getY() + t
  1178.                 * (-tile1.getY() * 3 + t
  1179.                     * (3 * tile1.getY() - tile1.getY() * t)))
  1180.                 + t
  1181.                 * (3 * tile2.getY() + t
  1182.                     * (-6 * tile2.getY() + tile2.getY() * 3
  1183.                         * t))
  1184.                 + t
  1185.                 * t
  1186.                 * (tile2.getY() * 3 - tile2.getY() * 3 * t)
  1187.                 + tile3.getY() * t * t * t;
  1188.             smoothed.add(getTileInMesh(new RSTile((int) x2,
  1189.                 (int) y2)));
  1190.             } else {
  1191.             smoothed.add(path.get(i));
  1192.             }
  1193.         }
  1194.         }
  1195.         return smoothed;
  1196.     }
  1197.  
  1198.     public boolean traverse() {
  1199.         return this.traverse(EnumSet.of(TraversalOption.HANDLE_RUN,
  1200.             TraversalOption.SPACE_ACTIONS));
  1201.     }
  1202.  
  1203.     public boolean traverse(EnumSet<TraversalOption> options) {
  1204.         RSTile next = getNext();
  1205.         if (next == null) {
  1206.         return false;
  1207.         }
  1208.         if (next.equals(getEnd())) {
  1209.         if (calc.distanceTo(next) <= 1
  1210.             || (end && players.getMyPlayer().isMoving())
  1211.             || next.equals(walking.getDestination())) {
  1212.             return false;
  1213.         }
  1214.         end = true;
  1215.         } else {
  1216.         end = false;
  1217.         }
  1218.         if (options.contains(TraversalOption.HANDLE_RUN)
  1219.             && !walking.isRunEnabled() && walking.getEnergy() > 50) {
  1220.         walking.setRun(true);
  1221.         }
  1222.         if (options.contains(TraversalOption.SPACE_ACTIONS)) {
  1223.         RSTile dest = walking.getDestination();
  1224.         if (dest != null
  1225.             && players.getMyPlayer().isMoving()
  1226.             && calc.distanceTo(dest) > 5
  1227.             && calc.distanceBetween(next, dest) < walkingDistance
  1228.                 .random()) {
  1229.             return true;
  1230.         }
  1231.         }
  1232.         return walking.walkTileMM(next, 0, 0);
  1233.     }
  1234.  
  1235.     public int getNearestIndexTo(RSTile t) {
  1236.         int len = Integer.MAX_VALUE;
  1237.         int bestIndex = -1;
  1238.         if (hasPath())
  1239.         for (int i = 0; i < smoothPath.size(); i++)
  1240.             if (calc.distanceBetween(t, smoothPath.get(i)) < len) {
  1241.             bestIndex = i;
  1242.             len = calc.distanceTo(t);
  1243.             }
  1244.         return bestIndex;
  1245.     }
  1246.  
  1247.     public enum MeshPathType {
  1248.         ALL_CENTER, FULL, WEIGHT_CENTER
  1249.     }
  1250.     }
  1251.  
  1252.     public static class PaintFormatter {
  1253.     public static String getFormattedMoney(long money) {
  1254.         return new DecimalFormat("###,###,###,###,###,###").format(money);
  1255.     }
  1256.  
  1257.     public static String getFormattedTime(final long timeMillis) {
  1258.         return getFormattedTime(timeMillis, ":", false);
  1259.     }
  1260.  
  1261.     public static String getFormattedTime(final long timeMillis,
  1262.         String sep, boolean millisInc) {
  1263.         long millis = timeMillis;
  1264.         final long days = millis / (24 * 1000 * 60 * 60);
  1265.         millis -= days * (24 * 1000 * 60 * 60);
  1266.         final long hours = millis / (1000 * 60 * 60);
  1267.         millis -= hours * 1000 * 60 * 60;
  1268.         final long minutes = millis / (1000 * 60);
  1269.         millis -= minutes * 1000 * 60;
  1270.         final long _seconds = millis / 1000;
  1271.         millis -= _seconds * 1000;
  1272.         String dayString = String.valueOf(days);
  1273.         String hoursString = String.valueOf(hours);
  1274.         String minutesString = String.valueOf(minutes);
  1275.         String secondsString = String.valueOf(_seconds);
  1276.         if (hours < 10) {
  1277.         hoursString = 0 + hoursString;
  1278.         }
  1279.         if (minutes < 10) {
  1280.         minutesString = 0 + minutesString;
  1281.         }
  1282.         if (_seconds < 10) {
  1283.         secondsString = 0 + secondsString;
  1284.         }
  1285.         String s = "";
  1286.         if (days > 0)
  1287.         s = dayString + sep;
  1288.         s += hoursString + sep + minutesString + sep + secondsString;
  1289.         if (millisInc)
  1290.         s += sep + String.valueOf(millis);
  1291.         return s;
  1292.     }
  1293.  
  1294.     public static String properCaseAll(String s) {
  1295.         String[] words = s.split(" ");
  1296.         String result = "";
  1297.         for (int i = 0; i < words.length; i++) {
  1298.         String f = words[i].substring(0, 1).toUpperCase();
  1299.         words[i] = f + words[i].substring(1).toLowerCase();
  1300.         result += " " + words[i];
  1301.         }
  1302.         return result.substring(1);
  1303.     }
  1304.  
  1305.     public static String properCaseFirst(String s) {
  1306.         String[] sentences = new String[] { s };
  1307.         if (s.contains("."))
  1308.         sentences = s.split(".");
  1309.         String result = "";
  1310.         for (int i = 0; i < sentences.length; i++) {
  1311.         String f = sentences[i].substring(0, 1).toUpperCase();
  1312.         sentences[i] = f + sentences[i].substring(1).toLowerCase();
  1313.         result += " " + sentences[i];
  1314.         }
  1315.         return result.substring(1);
  1316.     }
  1317.     }
  1318.  
  1319.     private static class SkillPaint implements MouseListener, TextPaintListener {
  1320.     private int[] goalLevels;
  1321.     private Map<Integer, Rectangle> goalMap = new HashMap<Integer, Rectangle>();
  1322.     private Rectangle resetTracker = null;
  1323.     private int[] skillIDs;
  1324.     private Skills skills;
  1325.     private SkillTracker tracker;
  1326.  
  1327.     public SkillPaint(Skills skills, int... skillIDs) {
  1328.         this.skills = skills;
  1329.         this.skillIDs = skillIDs;
  1330.         this.tracker = new SkillTracker(skills);
  1331.         goalLevels = new int[Skills.SKILL_NAMES.length];
  1332.     }
  1333.  
  1334.     @Override
  1335.     public int drawLine(Graphics render, int line) {
  1336.         StringUtil.drawLine(render, line, "Reset Tracker");
  1337.         final FontMetrics metrics = render.getFontMetrics();
  1338.         final int height = metrics.getHeight() + 4;
  1339.         resetTracker = render.getFontMetrics()
  1340.             .getStringBounds("Reset Tracker", render).getBounds();
  1341.         resetTracker.x = 7;
  1342.         resetTracker.y = line * height + 15 + 19;
  1343.         line++;
  1344.         if (skillIDs.length > 0) {
  1345.         for (int skill : skillIDs) {
  1346.             if (skills.getCurrentExp(skill) == -1)
  1347.             continue;
  1348.             if (tracker.hasRecentlyTrained(skill)) {
  1349.             drawSkillLine(line, skill, render);
  1350.             line++;
  1351.             } else {
  1352.             goalMap.remove(skill);
  1353.             }
  1354.         }
  1355.         } else {
  1356.         for (int skill = 0; skill < Skills.SKILL_NAMES.length; skill++) {
  1357.             if (skills.getCurrentExp(skill) == -1)
  1358.             continue;
  1359.             if (tracker.hasRecentlyTrained(skill)) {
  1360.             drawSkillLine(line, skill, render);
  1361.             line++;
  1362.             } else {
  1363.             goalMap.remove(skill);
  1364.             }
  1365.         }
  1366.         }
  1367.         return line;
  1368.     }
  1369.  
  1370.     @Override
  1371.     public void mouseClicked(MouseEvent e) {
  1372.         for (Integer skill : goalMap.keySet()) {
  1373.         Rectangle r = goalMap.get(skill);
  1374.         if (r.contains(e.getPoint())) {
  1375.             int cLvl = goalLevels[skill.intValue()];
  1376.             if (e.getPoint().x < r.x + (r.width / 2)) {
  1377.             cLvl -= 1;
  1378.             } else {
  1379.             cLvl += 1;
  1380.             }
  1381.             if (cLvl > tracker.getCurrentLevel(skill)
  1382.                 && cLvl <= tracker.getMaxLevel(skill)) {
  1383.             goalLevels[skill.intValue()] = cLvl;
  1384.             return;
  1385.             }
  1386.         }
  1387.         }
  1388.  
  1389.         if (resetTracker != null && resetTracker.contains(e.getPoint())) {
  1390.         this.tracker = new SkillTracker(skills);
  1391.         goalLevels = new int[Skills.SKILL_NAMES.length];
  1392.         }
  1393.     }
  1394.  
  1395.     @Override
  1396.     public void mouseEntered(MouseEvent arg0) {
  1397.     }
  1398.  
  1399.     @Override
  1400.     public void mouseExited(MouseEvent arg0) {
  1401.     }
  1402.  
  1403.     @Override
  1404.     public void mousePressed(MouseEvent arg0) {
  1405.     }
  1406.  
  1407.     @Override
  1408.     public void mouseReleased(MouseEvent arg0) {
  1409.     }
  1410.  
  1411.     private void drawSkillLine(int row, int skill, Graphics render) {
  1412.         final String skillName = PaintFormatter
  1413.             .properCaseAll(Skills.SKILL_NAMES[skill]);
  1414.         if (goalLevels[skill] <= tracker.getCurrentLevel(skill))
  1415.         goalLevels[skill] = tracker.getCurrentLevel(skill) + 1;
  1416.         int goalLevel = goalLevels[skill];
  1417.         final String ttg = PaintFormatter.getFormattedTime(tracker
  1418.             .getMillisToLevel(skill, goalLevel));
  1419.         final String perHour = PaintFormatter
  1420.             .getFormattedMoney((int) tracker.getExpPerHour(skill))
  1421.             + " exp/hr";
  1422.         final String line = skillName + ": " + ttg + " 'till " + goalLevel
  1423.             + " @ " + perHour;
  1424.         final FontMetrics metrics = render.getFontMetrics();
  1425.         final int height = metrics.getHeight() + 4; // height + gap
  1426.         final int y = row * height + 15 + 19;
  1427.         final String buttons = (goalLevel > tracker.getCurrentLevel(skill) + 1 ? "<"
  1428.             : " ")
  1429.             + "  "
  1430.             + (goalLevel < tracker.getMaxLevel(skill) ? ">" : " ");
  1431.         Rectangle rect = metrics.getStringBounds(buttons, render)
  1432.             .getBounds();
  1433.         rect = new Rectangle(6, y - rect.height + 3, rect.width + 2,
  1434.             rect.height - 2);
  1435.         this.goalMap.put(skill, rect);
  1436.         render.setColor(Color.GREEN);
  1437.         render.drawString(buttons, 7, y);
  1438.         render.drawString(line, 7 + rect.width + 5, y);
  1439.     }
  1440.  
  1441.     private static class SkillTracker {
  1442.         private long[] lastTrained;
  1443.         private int[] newExp;
  1444.         private Skills skills;
  1445.         private long start;
  1446.         private int[] startExp;
  1447.  
  1448.         public SkillTracker(Skills skills) {
  1449.         this.skills = skills;
  1450.         this.start = System.currentTimeMillis();
  1451.         this.startExp = new int[Skills.SKILL_NAMES.length];
  1452.         this.lastTrained = new long[Skills.SKILL_NAMES.length];
  1453.         this.newExp = new int[Skills.SKILL_NAMES.length];
  1454.         for (int i = 0; i < Skills.SKILL_NAMES.length; i++) {
  1455.             this.startExp[i] = skills.getCurrentExp(i);
  1456.             this.newExp[i] = this.startExp[i];
  1457.         }
  1458.         }
  1459.  
  1460.         public long getElapsedTime() {
  1461.         return System.currentTimeMillis() - start;
  1462.         }
  1463.  
  1464.         public int getExpGain(int skill) {
  1465.         return skills.getCurrentExp(skill) - startExp[skill];
  1466.         }
  1467.  
  1468.         public double getExpPerHour(int skill) {
  1469.         return getExpPerSecond(skill) * 3600d;
  1470.         }
  1471.  
  1472.         public double getExpPerMilli(int skill) {
  1473.         double gain = getExpGain(skill);
  1474.         double time = getElapsedTime();
  1475.         return gain / time;
  1476.         }
  1477.  
  1478.         public double getExpPerSecond(int skill) {
  1479.         return getExpPerMilli(skill) * 1000d;
  1480.         }
  1481.  
  1482.         public int getMaxLevel(int skill) {
  1483.         return skill == Skills.DUNGEONEERING ? 120 : 99;
  1484.         }
  1485.  
  1486.         public long getMillisToExp(int skill, int exp) {
  1487.         int expNeed = exp - skills.getCurrentExp(skill);
  1488.         if (expNeed <= 0 || getExpGain(skill) <= 0)
  1489.             return 0;
  1490.         return (long) (((double) expNeed) / getExpPerMilli(skill));
  1491.         }
  1492.  
  1493.         public long getMillisToLevel(int skill, int level) {
  1494.         if (level > getMaxLevel(skill) || level < 0)
  1495.             return 0;
  1496.         return getMillisToExp(skill, Skills.XP_TABLE[level]);
  1497.         }
  1498.  
  1499.         public boolean hasRecentlyTrained(int skill) {
  1500.         int cExp = skills.getCurrentExp(skill);
  1501.         if (newExp[skill] < cExp) {
  1502.             lastTrained[skill] = System.currentTimeMillis();
  1503.         }
  1504.         newExp[skill] = cExp;
  1505.         return lastTrained[skill] + 600000 > System.currentTimeMillis();
  1506.         }
  1507.  
  1508.         private int getCurrentLevel(int skill) {
  1509.         int sLvl = skills.getRealLevel(skill);
  1510.         if (sLvl > getMaxLevel(skill))
  1511.             sLvl = getMaxLevel(skill);
  1512.         return sLvl;
  1513.         }
  1514.     }
  1515.     }
  1516.  
  1517.     public static class Range {
  1518.     private int min, max;
  1519.  
  1520.     public Range(int min, int max) {
  1521.         this.min = min;
  1522.         this.max = max;
  1523.     }
  1524.  
  1525.     public int random() {
  1526.         return (int) ((Math.random() * (max - min)) + min);
  1527.     }
  1528.  
  1529.     @Override
  1530.     public String toString() {
  1531.         return min + " to " + max;
  1532.     }
  1533.     }
  1534. }
Advertisement
Add Comment
Please, Sign In to add comment