Advertisement
kolton

Untitled

Dec 2nd, 2012
119
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.28 KB | None | 0 0
  1. /**
  2. * @filename Town.js
  3. * @author kolton
  4. * @desc do town chores like buying, selling and gambling
  5. */
  6.  
  7. var NPC = {
  8. Akara: getLocaleString(2892).toLowerCase(),
  9. Gheed: getLocaleString(2891).toLowerCase(),
  10. Charsi: getLocaleString(2894).toLowerCase(),
  11. Kashya: getLocaleString(2893).toLowerCase(),
  12.  
  13. Fara: getLocaleString(3025).toLowerCase(),
  14. Drognan: getLocaleString(3023).toLowerCase(),
  15. Elzix: getLocaleString(3030).toLowerCase(),
  16. Greiz: getLocaleString(3031).toLowerCase(),
  17. Lysander: getLocaleString(3026).toLowerCase(),
  18.  
  19. Ormus: getLocaleString(1011).toLowerCase(),
  20. Alkor: getLocaleString(1010).toLowerCase(),
  21. Hratli: getLocaleString(1009).toLowerCase(),
  22. Asheara: getLocaleString(1008).toLowerCase(),
  23.  
  24. Jamella: getLocaleString(1016).toLowerCase(),
  25. Halbu: getLocaleString(1017).toLowerCase(),
  26. Tyrael: getLocaleString(1013).toLowerCase(),
  27.  
  28. Malah: getLocaleString(22478).toLowerCase(),
  29. Anya: getLocaleString(22477).toLowerCase(),
  30. Larzuk: getLocaleString(22476).toLowerCase(),
  31. "Qual-Kehk": getLocaleString(22480).toLowerCase()
  32. };
  33.  
  34. var Town = {
  35. sellTimer: getTickCount(), // shop speedup test
  36.  
  37. tasks: [
  38. {Heal: NPC.Akara, Shop: NPC.Akara, Gamble: NPC.Gheed, Repair: NPC.Charsi, Merc: NPC.Kashya, Key: NPC.Akara},
  39. {Heal: NPC.Fara, Shop: NPC.Drognan, Gamble: NPC.Elzix, Repair: NPC.Fara, Merc: NPC.Greiz, Key: NPC.Lysander},
  40. {Heal: NPC.Ormus, Shop: NPC.Ormus, Gamble: NPC.Alkor, Repair: NPC.Hratli, Merc: NPC.Asheara, Key: NPC.Hratli},
  41. {Heal: NPC.Jamella, Shop: NPC.Jamella, Gamble: NPC.Jamella, Repair: NPC.Halbu, Merc: NPC.Tyrael, Key: NPC.Jamella},
  42. {Heal: NPC.Malah, Shop: NPC.Malah, Gamble: NPC.Anya, Repair: NPC.Larzuk, Merc: NPC["Qual-Kehk"], Key: NPC.Malah}
  43. ],
  44.  
  45. ignoredItemTypes: [ // Items that won't be stashed
  46. 5, // Arrows
  47. 6, // Bolts
  48. 18, // Book (Tome)
  49. 22, // Scroll
  50. 38, // Missile Potion
  51. 41, // Key
  52. 76, // Healing Potion
  53. 77, // Mana Potion
  54. 78, // Rejuvenation Potion
  55. 79, // Stamina Potion
  56. 80, // Antidote Potion
  57. 81 // Thawing Potion
  58. ],
  59.  
  60. // Do town chores
  61. doChores: function () {
  62. if (!me.inTown) {
  63. this.goToTown();
  64. }
  65.  
  66. var i,
  67. cancelFlags = [0x01, 0x02, 0x04, 0x08, 0x14, 0x16, 0x0c, 0x0f];
  68.  
  69. if (me.classid === 4 && Config.FindItem && Config.FindItemSwitch) { // weapon switch fix in case last game dropped with item find switch on
  70. Precast.weaponSwitch(Math.abs(Config.FindItemSwitch - 1));
  71. }
  72.  
  73. if (Config.MFSwitchPercent) {
  74. Precast.weaponSwitch(Math.abs(Config.MFSwitch - 1));
  75. }
  76.  
  77. this.heal();
  78. this.fillTome("tbk");
  79.  
  80. if (Config.FieldID) {
  81. this.fillTome("ibk");
  82. }
  83.  
  84. this.buyPotions();
  85. this.identify();
  86. this.shopItems();
  87. this.buyKeys();
  88. this.repair();
  89. this.gamble();
  90. this.reviveMerc();
  91. Cubing.doCubing();
  92. Runewords.makeRunewords();
  93. this.stash(true);
  94.  
  95. for (i = 0; i < cancelFlags.length; i += 1) {
  96. if (getUIFlag(cancelFlags[i])) {
  97. delay(500);
  98. me.cancel();
  99.  
  100. break;
  101. }
  102. }
  103.  
  104. me.cancel();
  105.  
  106. return true;
  107. },
  108.  
  109. // Start a task and return the NPC Unit
  110. initNPC: function (task) {
  111. //print(task);
  112.  
  113. var npc = getInteractedNPC();
  114.  
  115. if (npc && npc.name.toLowerCase() !== this.tasks[me.act - 1][task]) {
  116. me.cancel();
  117.  
  118. npc = null;
  119. }
  120.  
  121. if (!npc) {
  122. npc = getUnit(1, this.tasks[me.act - 1][task]);
  123.  
  124. if (!npc) {
  125. this.move(this.tasks[me.act - 1][task]);
  126.  
  127. npc = getUnit(1, this.tasks[me.act - 1][task]);
  128. }
  129. }
  130.  
  131. if (!npc || (!getUIFlag(0x08) && !npc.openMenu())) {
  132. return false;
  133. }
  134.  
  135. switch (task) {
  136. case "Shop":
  137. case "Repair":
  138. case "Gamble":
  139. if (!getUIFlag(0x0C) && !npc.startTrade(task)) {
  140. return false;
  141. }
  142.  
  143. break;
  144. case "Key":
  145. if (!getUIFlag(0x0C) && !npc.startTrade(me.act === 3 ? "Repair" : "Shop")) {
  146. return false;
  147. }
  148.  
  149. break;
  150. }
  151.  
  152. return npc;
  153. },
  154.  
  155. // Go to a town healer
  156. heal: function () {
  157. if (!this.needHealing()) {
  158. return true;
  159. }
  160.  
  161. if (!this.initNPC("Heal")) {
  162. return false;
  163. }
  164.  
  165. return true;
  166. },
  167.  
  168. // Check if healing is needed, based on character config
  169. needHealing: function () {
  170. if (me.hp * 100 / me.hpmax <= Config.HealHP || me.mp * 100 / me.mpmax <= Config.HealMP) {
  171. return true;
  172. }
  173.  
  174. // Status effects
  175. if (Config.HealStatus && (me.getState(2) || me.getState(9) || me.getState(61))) {
  176. return true;
  177. }
  178.  
  179. return false;
  180. },
  181.  
  182. // Buy potions from a NPC
  183. buyPotions: function () {
  184. var i, j, pot, npc, beltSize, col,
  185. emptyColumns = 0,
  186. useShift = true;
  187.  
  188. col = this.checkColumns();
  189. beltSize = Storage.BeltSize();
  190.  
  191. // Check if we need to buy potions based on Config.MinColumn
  192. for (i = 0; i < 4; i += 1) {
  193. if (["hp", "mp"].indexOf(Config.BeltColumn[i]) > -1 && col[i] > (beltSize - Config.MinColumn[i])) {
  194. break;
  195. }
  196. }
  197.  
  198. if (i === 4) {
  199. return true;
  200. }
  201.  
  202. npc = this.initNPC("Shop");
  203.  
  204. if (!npc) {
  205. return false;
  206. }
  207.  
  208. for (i = 0; i < 4; i += 1) {
  209. switch (Config.BeltColumn[i]) {
  210. case "hp":
  211. case "mp": // Increase emptyColumns if a buyable column is empty
  212. if (col[i] === beltSize) {
  213. emptyColumns += 1;
  214. }
  215.  
  216. break;
  217. case "rv": // can't use shift buy if "rv" column is empty
  218. if (col[i] === beltSize) {
  219. useShift = false;
  220. }
  221.  
  222. break;
  223. }
  224. }
  225.  
  226. for (i = 0; i < 4; i += 1) {
  227. if (col[i] > 0) {
  228. pot = this.getPotion(npc, Config.BeltColumn[i]);
  229.  
  230. if (pot) {
  231. //print("ÿc2column ÿc0" + i + "ÿc2 needs ÿc0" + col[i] + " ÿc2potions");
  232.  
  233. // Shift+buy will trigger if there's no empty columns or if only the current column is empty
  234. if (useShift && (emptyColumns === 0 || (emptyColumns === 1 && col[i] === beltSize))) {
  235. pot.buy(true);
  236. } else {
  237. for (j = 0; j < col[i]; j += 1) {
  238. pot.buy(false);
  239. }
  240. }
  241. }
  242. }
  243.  
  244. // Switch to shift+buy on the fly (if possible, happens if 2+ buyable potion columns are empty)
  245. if (col[i] === beltSize && emptyColumns > 0) {
  246. emptyColumns -= 1;
  247. }
  248.  
  249. col = this.checkColumns(); // Re-initialize columns (needed because 1 shift-buy can fill multiple columns)
  250. }
  251.  
  252. return true;
  253. },
  254.  
  255. // Return column status (needed potions in each column)
  256. checkColumns: function () {
  257. var beltSize = Storage.BeltSize(),
  258. col = [beltSize, beltSize, beltSize, beltSize],
  259. pot = me.getItem(-1, 2); // Mode 2 = in belt
  260.  
  261. if (!pot) { // No potions
  262. return col;
  263. }
  264.  
  265. do {
  266. col[pot.x % 4] -= 1;
  267. } while (pot.getNext());
  268.  
  269. return col;
  270. },
  271.  
  272. // Get the highest potion from current npc
  273. getPotion: function (npc, type) {
  274. var i, result;
  275.  
  276. if (!type) {
  277. return false;
  278. }
  279.  
  280. if (type === "hp" || type === "mp") {
  281. for (i = 5; i > 0; i -= 1) {
  282. result = npc.getItem(type + i);
  283.  
  284. if (result) {
  285. return result;
  286. }
  287. }
  288. }
  289.  
  290. return false;
  291. },
  292.  
  293. fillTome: function (code) {
  294. if (this.checkScrolls(code) >= 13) {
  295. return true;
  296. }
  297.  
  298. var scroll, tome,
  299. npc = this.initNPC("Shop");
  300.  
  301. if (!npc) {
  302. return false;
  303. }
  304.  
  305. delay(500); // this was at the top
  306.  
  307. if (!me.findItem("tbk", 0, 3)) {
  308. tome = npc.getItem("tbk");
  309.  
  310. if (tome) {
  311. try {
  312. tome.buy();
  313. } catch (e1) {
  314. print(e1);
  315. }
  316. }
  317. }
  318.  
  319. scroll = npc.getItem(code === "tbk" ? "tsc" : "isc");
  320.  
  321. if (!scroll) {
  322. return false;
  323. }
  324.  
  325. try {
  326. scroll.buy(true);
  327. } catch (e2) {
  328. print(e2.message);
  329.  
  330. return false;
  331. }
  332.  
  333. return true;
  334. },
  335.  
  336. checkScrolls: function (id) {
  337. var tome = me.findItem(id, 0, 3);
  338.  
  339. if (!tome) {
  340. switch (id) {
  341. case "ibk":
  342. return 20; // Ignore missing ID tome
  343. case "tbk":
  344. return 0; // Force TP tome check
  345. }
  346. }
  347.  
  348. return tome.getStat(70);
  349. },
  350.  
  351. identify: function () {
  352. var i, item, tome, scroll, npc, list, timer, tpTome, result,
  353. tpTomePos = {};
  354.  
  355. this.cainID();
  356.  
  357. list = Storage.Inventory.Compare(Config.Inventory);
  358.  
  359. if (!list) {
  360. return false;
  361. }
  362.  
  363. // Avoid unnecessary NPC visits
  364. for (i = 0; i < list.length; i += 1) {
  365. // Only unid items or sellable junk (low level) should trigger a NPC visit
  366. if ((!list[i].getFlag(0x10) || Config.LowGold > 0) && [-1, 4].indexOf(Pickit.checkItem(list[i]).result) > -1) {
  367. break;
  368. }
  369. }
  370.  
  371. if (i === list.length) {
  372. return false;
  373. }
  374.  
  375. npc = this.initNPC("Shop");
  376.  
  377. if (!npc) {
  378. return false;
  379. }
  380.  
  381. tome = me.findItem("ibk", 0, 3);
  382.  
  383. if (tome && tome.getStat(70) < list.length) {
  384. this.fillTome("ibk");
  385. }
  386.  
  387. MainLoop:
  388. while (list.length > 0) {
  389. item = list.shift();
  390. result = Pickit.checkItem(item);
  391.  
  392. if (item.location === 3 && this.ignoredItemTypes.indexOf(item.itemType) === -1) {
  393. switch (result.result) {
  394. // Items for gold, will sell magics, etc. w/o id, but at low levels
  395. // magics are often not worth iding.
  396. case 4:
  397. item.sell();
  398.  
  399. break;
  400. case -1:
  401. if (tome) {
  402. this.identifyItem(item, tome);
  403. } else {
  404. scroll = npc.getItem("isc");
  405.  
  406. if (scroll) {
  407. if (!Storage.Inventory.CanFit(scroll)) {
  408. tpTome = me.findItem("tbk", 0, 3);
  409.  
  410. if (tpTome) {
  411. tpTomePos = {x: tpTome.x, y: tpTome.y};
  412.  
  413. tpTome.sell();
  414. delay(500);
  415. }
  416. }
  417.  
  418. delay(500);
  419. scroll.buy();
  420. }
  421.  
  422. scroll = me.findItem("isc", 0, 3);
  423.  
  424. if (!scroll) {
  425. break MainLoop;
  426. }
  427.  
  428. this.identifyItem(item, scroll);
  429. }
  430.  
  431. result = Pickit.checkItem(item);
  432.  
  433. switch (result.result) {
  434. case 1:
  435. Misc.logItem("Kept", item, result.line);
  436.  
  437. break;
  438. case -1:
  439. case 2:
  440. case 3: // just in case
  441. break;
  442. default:
  443. item.sell();
  444.  
  445. timer = getTickCount() - this.sellTimer; // shop speedup test
  446.  
  447. //print("sell timer: " + timer);
  448.  
  449. if (timer > 0 && timer < 500) {
  450. delay(timer);
  451. }
  452.  
  453. break;
  454. }
  455.  
  456. break;
  457. }
  458. }
  459. }
  460.  
  461. this.fillTome("tbk"); // Check for TP tome in case it got sold for ID scrolls
  462.  
  463. return true;
  464. },
  465.  
  466. cainID: function () {
  467. if (!Config.CainID.Enable) {
  468. return false;
  469. }
  470.  
  471. // Check if we're already in a shop. It would be pointless to go to Cain if so.
  472. var i, cain, unids, result,
  473. npc = getInteractedNPC();
  474.  
  475. if (npc && npc.name.toLowerCase() === this.tasks[me.act - 1].Shop) {
  476. return false;
  477. }
  478.  
  479. // Check if we may use Cain - minimum gold
  480. if (me.getStat(14) + me.getStat(15) < Config.CainID.MinGold) {
  481. //print("Can't use Cain - not enough gold.");
  482.  
  483. return false;
  484. }
  485.  
  486. me.cancel();
  487. this.stash(false);
  488.  
  489. unids = this.getUnids();
  490.  
  491. if (unids) {
  492. // Check if we may use Cain - number of unid items
  493. if (unids.length < Config.CainID.MinUnids) {
  494. //print("Can't use Cain - not enough unid items.");
  495.  
  496. return false;
  497. }
  498.  
  499. // Check if we may use Cain - kept unid items
  500. for (i = 0; i < unids.length; i += 1) {
  501. if (Pickit.checkItem(unids[i]).result > 0) {
  502. //print("Can't use Cain - can't id a valid item.");
  503.  
  504. return false;
  505. }
  506. }
  507.  
  508. this.move("cain");
  509.  
  510. cain = getUnit(1, getLocaleString(2890));
  511.  
  512. if (!cain) {
  513. return false;
  514. }
  515.  
  516. if (cain && cain.openMenu()) {
  517. //cain.useMenu(0x0FB4);
  518. Misc.useMenu(0x0FB4);
  519. delay(1000);
  520. me.cancel();
  521. }
  522.  
  523. for (i = 0; i < unids.length; i += 1) {
  524. result = Pickit.checkItem(unids[i]);
  525.  
  526. switch (result.result) {
  527. case 0:
  528. unids[i].drop();
  529.  
  530. break;
  531. case 1:
  532. Misc.logItem("Kept", unids[i], result.line);
  533.  
  534. break;
  535. default:
  536. break;
  537. }
  538. }
  539. }
  540.  
  541. return true;
  542. },
  543.  
  544. fieldID: function () { // not exactly a town function but whateva
  545. var list, tome, item, result;
  546.  
  547. list = this.getUnids();
  548.  
  549. if (!list) {
  550. return false;
  551. }
  552.  
  553. tome = me.findItem("ibk", 0, 3);
  554.  
  555. if (!tome || tome.getStat(70) < list.length) {
  556. return false;
  557. }
  558.  
  559. while (list.length > 0) {
  560. item = list.shift();
  561. result = Pickit.checkItem(item);
  562.  
  563. if (result.result === -1) { // unid item that should be identified
  564. this.identifyItem(item, tome);
  565. delay(me.ping + 1);
  566.  
  567. result = Pickit.checkItem(item);
  568.  
  569. switch (result.result) {
  570. case 0:
  571. item.drop();
  572.  
  573. break;
  574. case 1:
  575. Misc.logItem("Field Kept", item, result.line);
  576.  
  577. break;
  578. default:
  579. break;
  580. }
  581. }
  582. }
  583.  
  584. delay(200);
  585. me.cancel();
  586.  
  587. return true;
  588. },
  589.  
  590. getUnids: function () {
  591. var i,
  592. list = [],
  593. items = me.getItems();
  594.  
  595. if (!items || !items.length) {
  596. return false;
  597. }
  598.  
  599. for (i = 0; i < items.length; i += 1) {
  600. if (items[i].location === 3 && !items[i].getFlag(0x10)) {
  601. list.push(items[i]);
  602. }
  603. }
  604.  
  605. if (!list.length) {
  606. return false;
  607. }
  608.  
  609. return list;
  610. },
  611.  
  612. identifyItem: function (unit, tome) {
  613. var i, tick;
  614.  
  615. if (!unit || unit.getFlag(0x10)) {
  616. return false;
  617. }
  618.  
  619. this.sellTimer = getTickCount(); // shop speedup test
  620.  
  621. for (i = 0; i < 3; i += 1) {
  622. clickItem(1, tome);
  623.  
  624. tick = getTickCount();
  625.  
  626. while (getTickCount() - tick < 500) {
  627. if (getCursorType() === 6) {
  628. break;
  629. }
  630.  
  631. delay(10);
  632. }
  633. }
  634.  
  635. if (getCursorType() !== 6) {
  636. return false;
  637. }
  638.  
  639. delay(270);
  640.  
  641. for (i = 0; i < 3; i += 1) {
  642. if (getCursorType() === 6) {
  643. clickItem(0, unit);
  644. }
  645.  
  646. tick = getTickCount();
  647.  
  648. while (getTickCount() - tick < 500) {
  649. if (unit.getFlag(0x10)) {
  650. delay(50);
  651.  
  652. return true;
  653. }
  654.  
  655. delay(10);
  656. }
  657.  
  658. delay(300);
  659. }
  660.  
  661. return false;
  662. },
  663.  
  664. shopItems: function () {
  665. if (!Config.MiniShopBot) {
  666. return true;
  667. }
  668.  
  669. var i, items, result,
  670. npc = getInteractedNPC();
  671.  
  672. if (!npc || !getUIFlag(0x0C) || !npc.itemcount) {
  673. return false;
  674. }
  675.  
  676. items = npc.getItems();
  677.  
  678. if (!items || !items.length) {
  679. return false;
  680. }
  681.  
  682. print("ÿc4MiniShopBotÿc0: Scanning " + items.length + " items.");
  683.  
  684. for (i = 0; i < items.length; i += 1) {
  685. if (this.ignoredItemTypes.indexOf(items[i].itemType) === -1) {
  686. result = Pickit.checkItem(items[i]);
  687.  
  688. if (result.result === 1) {
  689. try {
  690. if (Storage.Inventory.CanFit(items[i]) && me.getStat(14) + me.getStat(15) >= items[i].getItemCost(0)) {
  691. Misc.logItem("Shopped", items[i], result.line);
  692. items[i].buy();
  693. }
  694. } catch (e) {
  695. print(e);
  696. }
  697. }
  698.  
  699. delay(2);
  700. }
  701. }
  702.  
  703. return true;
  704. },
  705.  
  706. gamble: function () {
  707. if (!this.needGamble() || !Config.GambleItems.length) {
  708. return true;
  709. }
  710.  
  711. if (getUIFlag(0x0C)) {
  712. me.cancel(); // cancel trade screen so it doesn't buy certain sold items back from Jamella
  713. }
  714.  
  715. var i, items, npc, newItem, result,
  716. list = [];
  717.  
  718. npc = this.initNPC("Gamble");
  719.  
  720. if (!npc) {
  721. return false;
  722. }
  723.  
  724. items = me.findItems(-1, 0, 3);
  725.  
  726. while (items.length > 0) {
  727. list.push(items.shift().gid);
  728. }
  729.  
  730. me.cancel();
  731.  
  732. while (me.getStat(14) + me.getStat(15) >= Config.GambleGoldStop) {
  733. if (!getInteractedNPC()) {
  734. npc.startTrade("Gamble");
  735. }
  736.  
  737. items = npc.getItems();
  738.  
  739. if (items) {
  740. for (i = 0; i < items.length; i += 1) {
  741. if (Config.GambleItems.indexOf(items[i].classid) > -1) {
  742. if (!Storage.Inventory.CanFit(items[i])) {
  743. return false;
  744. }
  745.  
  746. items[i].buy();
  747.  
  748. newItem = this.getGambledItem(list);
  749.  
  750. if (newItem) {
  751. result = Pickit.checkItem(newItem);
  752.  
  753. switch (result.result) {
  754. case 1:
  755. Misc.logItem("Gambled", newItem, result.line);
  756. list.push(newItem.gid);
  757.  
  758. break;
  759. case 2:
  760. list.push(newItem.gid);
  761. Cubing.buildLists();
  762.  
  763. break;
  764. default:
  765. newItem.sell();
  766. delay(500);
  767.  
  768. break;
  769. }
  770. }
  771. }
  772. }
  773. }
  774.  
  775. me.cancel();
  776. }
  777.  
  778. return true;
  779. },
  780.  
  781. needGamble: function () {
  782. return Config.Gamble && me.getStat(14) + me.getStat(15) >= Config.GambleGoldStart;
  783. },
  784.  
  785. getGambledItem: function (list) {
  786. var i, j,
  787. items = me.findItems(-1, 0, 3);
  788.  
  789. for (i = 0; i < items.length; i += 1) {
  790. if (list.indexOf(items[i].gid) === -1) {
  791. for (j = 0; j < 3; j += 1) {
  792. if (items[i].getFlag(0x10)) {
  793. break;
  794. }
  795.  
  796. delay(100);
  797. }
  798.  
  799. return items[i];
  800. }
  801. }
  802.  
  803. return false;
  804. },
  805.  
  806. buyKeys: function () {
  807. if (!this.wantKeys()) {
  808. return true;
  809. }
  810.  
  811. var key,
  812. npc = this.initNPC("Key");
  813.  
  814. if (!npc) {
  815. return false;
  816. }
  817.  
  818. key = npc.getItem("key");
  819.  
  820. if (!key) {
  821. return false;
  822. }
  823.  
  824. try {
  825. key.buy(true);
  826. } catch (e) {
  827. print(e.message);
  828.  
  829. return false;
  830. }
  831.  
  832. return true;
  833. },
  834.  
  835. checkKeys: function (min) {
  836. if (!Config.OpenChests || me.classid === 6) {
  837. return false;
  838. }
  839.  
  840. var key = me.findItem("key", 0, 3);
  841.  
  842. if (key && key.getStat(70) > min) {
  843. return false;
  844. }
  845.  
  846. return true;
  847. },
  848.  
  849. needKeys: function () {
  850. return this.checkKeys(0);
  851. },
  852.  
  853. wantKeys: function () {
  854. return this.checkKeys(6);
  855. },
  856.  
  857. repair: function () {
  858. var quiver, myQuiver, npc, repairCheck, bowCheck;
  859.  
  860. repairCheck = this.needRepair();
  861.  
  862. if (!repairCheck) {
  863. return true;
  864. }
  865.  
  866. npc = this.initNPC("Repair");
  867.  
  868. if (!npc) {
  869. return false;
  870. }
  871.  
  872. //print("Repair trigger: " + repairCheck);
  873.  
  874. switch (repairCheck) {
  875. case "durability":
  876. case "charges":
  877. case "quantity":
  878. me.repair();
  879.  
  880. break;
  881. case "quiver":
  882. bowCheck = Attack.usingBow();
  883.  
  884. if (bowCheck) {
  885. switch (bowCheck) {
  886. case "bow":
  887. quiver = npc.getItem("aqv");
  888.  
  889. break;
  890. case "crossbow":
  891. quiver = npc.getItem("cqv");
  892.  
  893. break;
  894. }
  895.  
  896. if (quiver) {
  897. myQuiver = me.getItem(quiver.code, 1);
  898.  
  899. if (myQuiver) {
  900. myQuiver.sell();
  901. delay(500);
  902. }
  903.  
  904. quiver.buy();
  905. }
  906. }
  907.  
  908. break;
  909. }
  910.  
  911. //this.shopItems();
  912.  
  913. return true;
  914. },
  915.  
  916. needRepair: function () {
  917. if (me.getStat(14) + me.getStat(15) < me.getRepairCost()) { // Check if we can afford repairs
  918. return false;
  919. }
  920.  
  921. var i, durability, quantity, charge, quiver, bowCheck,
  922. repairPercent = 40, // TODO: Move this somewhere else
  923. item = me.getItem(-1, 1); // Id -1 = any, Mode 1 = equipped
  924.  
  925. if (!item) { // No equipped items
  926. return false;
  927. }
  928.  
  929. do {
  930. if (!item.getFlag(0x400000)) { // Skip ethereal items
  931. switch (item.itemType) {
  932. // Quantity check
  933. case 42: // Throwing knives
  934. case 43: // Throwing axes
  935. case 44: // Javelins
  936. case 87: // Amazon javelins
  937. quantity = item.getStat(70);
  938.  
  939. if (typeof quantity === "number" && quantity * 100 / (getBaseStat("items", item.classid, "maxstack") + item.getStat(254)) <= repairPercent) { // Stat 254 = increased stack size
  940. return "quantity";
  941. }
  942.  
  943. break;
  944. // Durability check
  945. default:
  946. durability = item.getStat(72);
  947.  
  948. if (typeof durability === "number" && durability * 100 / item.getStat(73) <= repairPercent) {
  949. return "durability";
  950. }
  951.  
  952. break;
  953. }
  954.  
  955. // Charged item check
  956. charge = item.getStat(-2)[204];
  957.  
  958. if (typeof (charge) === "object") {
  959. if (charge instanceof Array) {
  960. for (i = 0; i < charge.length; i += 1) {
  961. if (typeof charge[i] !== "undefined" && charge[i].hasOwnProperty("charges") && charge[i].charges * 100 / charge[i].maxcharges <= repairPercent) {
  962. return "charges";
  963. }
  964. }
  965. } else if (charge.charges * 100 / charge.maxcharges <= repairPercent) {
  966. return "charges";
  967. }
  968. }
  969. }
  970. } while (item.getNext());
  971.  
  972. // Arrow/Bolt check
  973. bowCheck = Attack.usingBow();
  974.  
  975. if (bowCheck) {
  976. switch (bowCheck) {
  977. case "bow":
  978. quiver = me.getItem("aqv", 1); // Equipped arrow quiver
  979. break;
  980. case "crossbow":
  981. quiver = me.getItem("cqv", 1); // Equipped bolt quiver
  982. break;
  983. }
  984.  
  985. if (!quiver) { // Out of arrows/bolts
  986. return "quiver";
  987. }
  988.  
  989. quantity = quiver.getStat(70);
  990.  
  991. if (typeof quantity === "number" && quantity * 100 / getBaseStat("items", quiver.classid, "maxstack") <= repairPercent) {
  992. return "quiver";
  993. }
  994. }
  995.  
  996. return false;
  997. },
  998.  
  999. reviveMerc: function () {
  1000. if (!this.needMerc()) {
  1001. return true;
  1002. }
  1003.  
  1004. var i, tick,
  1005. npc = this.initNPC("Merc");
  1006.  
  1007. if (!npc) {
  1008. return false;
  1009. }
  1010.  
  1011. MainLoop:
  1012. for (i = 0; i < 3; i += 1) {
  1013. //npc.useMenu(0x1507);
  1014. Misc.useMenu(0x1507);
  1015. delay(1000);
  1016.  
  1017. tick = getTickCount();
  1018.  
  1019. while (getTickCount() - tick < 1000) {
  1020. if (me.getMerc()) {
  1021. break MainLoop;
  1022. }
  1023.  
  1024. delay(100);
  1025. }
  1026. }
  1027.  
  1028. delay(750);
  1029. Attack.checkInfinity();
  1030.  
  1031. return !!me.getMerc();
  1032. },
  1033.  
  1034. needMerc: function () {
  1035. var i, merc;
  1036.  
  1037. if (me.gametype === 0 || !Config.UseMerc || me.getStat(14) + me.getStat(15) < me.mercrevivecost) { // gametype 0 = classic
  1038. return false;
  1039. }
  1040.  
  1041. // me.getMerc() might return null if called right after taking a portal, that's why there's retry attempts
  1042. for (i = 0; i < 3; i += 1) {
  1043. merc = me.getMerc();
  1044.  
  1045. if (merc && merc.mode !== 0 && merc.mode !== 12) {
  1046. return false;
  1047. }
  1048.  
  1049. delay(100);
  1050. }
  1051.  
  1052. if (!me.mercrevivecost) { // In case we never had a merc and Config.UseMerc is still set to true for some odd reason
  1053. return false;
  1054. }
  1055.  
  1056. return true;
  1057. },
  1058.  
  1059. stash: function (stashGold) {
  1060. if (typeof stashGold === "undefined") {
  1061. stashGold = true;
  1062. }
  1063.  
  1064. if (!this.needStash()) {
  1065. return true;
  1066. }
  1067.  
  1068. me.cancel();
  1069.  
  1070. var i,
  1071. items = Storage.Inventory.Compare(Config.Inventory);
  1072.  
  1073. if (items) {
  1074. for (i = 0; i < items.length; i += 1) {
  1075. if (this.ignoredItemTypes.indexOf(items[i].itemType) === -1 && ((Pickit.checkItem(items[i]).result > 0 && Pickit.checkItem(items[i]).result < 4) || Cubing.keepItem(items[i]) || Runewords.keepItem(items[i]))) {
  1076. Storage.Stash.MoveTo(items[i]);
  1077. }
  1078. }
  1079. }
  1080.  
  1081. // Stash gold
  1082. if (stashGold) {
  1083. if (me.getStat(14) >= Config.StashGold && me.getStat(15) < 25e5 && this.openStash()) {
  1084. gold(me.getStat(14), 3);
  1085. delay(500);
  1086. me.cancel();
  1087. }
  1088. }
  1089.  
  1090. return true;
  1091. },
  1092.  
  1093. needStash: function () {
  1094. if (Config.StashGold && me.getStat(14) >= Config.StashGold && me.getStat(15) < 25e5) {
  1095. return true;
  1096. }
  1097.  
  1098. var i,
  1099. items = Storage.Inventory.Compare(Config.Inventory);
  1100.  
  1101. for (i = 0; i < items.length; i += 1) {
  1102. if (Storage.Stash.CanFit(items[i])) {
  1103. return true;
  1104. }
  1105. }
  1106.  
  1107. return false;
  1108. },
  1109.  
  1110. openStash: function () {
  1111. if (!this.move("stash")) {
  1112. return false;
  1113. }
  1114.  
  1115. if (getUIFlag(0x19)) {
  1116. return true;
  1117. }
  1118.  
  1119. var i, tick,
  1120. useTK = me.classid === 1 && me.getSkill(43, 1),
  1121. stash = getUnit(2, 267);
  1122.  
  1123. if (stash) {
  1124. for (i = 0; i < 5; i += 1) {
  1125. if (useTK) {
  1126. Skill.cast(43, 0, stash);
  1127. } else {
  1128. stash.interact();
  1129. }
  1130.  
  1131. tick = getTickCount();
  1132.  
  1133. while (getTickCount() - tick < 1000) {
  1134. if (getUIFlag(0x19)) {
  1135. delay(200);
  1136.  
  1137. return true;
  1138. }
  1139.  
  1140. delay(10);
  1141. }
  1142.  
  1143. if (i > 1) {
  1144. Packet.flash(me.gid);
  1145. this.move("waypoint");
  1146. this.move("stash");
  1147. }
  1148. }
  1149. }
  1150.  
  1151. return false;
  1152. },
  1153.  
  1154. getCorpse: function () {
  1155. var i, corpse;
  1156.  
  1157. for (i = 0; i < 3; i += 1) {
  1158. corpse = getUnit(0, me.name, 17);
  1159.  
  1160. if (corpse && getDistance(me, corpse) <= 20) {
  1161. while (copyUnit(corpse).x) {
  1162. if (me.dead) {
  1163. return false;
  1164. }
  1165.  
  1166. Pather.moveToUnit(corpse, rand(-2, 2), rand(-2, 2));
  1167. corpse.interact();
  1168. delay(500);
  1169. }
  1170. }
  1171. }
  1172.  
  1173. if (me.gametype === 0) {
  1174. this.checkShard();
  1175. }
  1176.  
  1177. return true;
  1178. },
  1179.  
  1180. checkShard: function () {
  1181. var shard,
  1182. check = {left: false, right: false},
  1183. item = me.getItem("bld", 0);
  1184.  
  1185. if (item) {
  1186. do {
  1187. if (item.location === 3 && item.quality === 7) {
  1188. shard = copyUnit(item);
  1189.  
  1190. break;
  1191. }
  1192. } while (item.getNext());
  1193. }
  1194.  
  1195. if (!shard) {
  1196. return true;
  1197. }
  1198.  
  1199. item = me.getItem(-1, 1);
  1200.  
  1201. if (item) {
  1202. do {
  1203. if (item.bodylocation === 4) {
  1204. check.right = true;
  1205. }
  1206.  
  1207. if (item.bodylocation === 5) {
  1208. check.left = true;
  1209. }
  1210. } while (item.getNext());
  1211. }
  1212.  
  1213. if (!check.right) {
  1214. shard.toCursor();
  1215.  
  1216. while (me.itemoncursor) {
  1217. clickItem(0, 4);
  1218. delay(500);
  1219. }
  1220. } else if (!check.left) {
  1221. shard.toCursor();
  1222.  
  1223. while (me.itemoncursor) {
  1224. clickItem(0, 5);
  1225. delay(500);
  1226. }
  1227. }
  1228.  
  1229. return true;
  1230. },
  1231.  
  1232. // TODO: Determine if this func can be avoided with better potion pickup code.
  1233. clearBelt: function () {
  1234. var item = me.getItem(-1, 2),
  1235. clearList = [];
  1236.  
  1237. if (item) {
  1238. do {
  1239. switch (item.itemType) {
  1240. case 76: // Healing
  1241. if (Config.BeltColumn[item.x % 4] !== "hp") {
  1242. clearList.push(copyUnit(item));
  1243. }
  1244.  
  1245. break;
  1246. case 77: // Mana
  1247. if (Config.BeltColumn[item.x % 4] !== "mp") {
  1248. clearList.push(copyUnit(item));
  1249. }
  1250.  
  1251. break;
  1252. case 78: // Rejuvenation
  1253. if (Config.BeltColumn[item.x % 4] !== "rv") {
  1254. clearList.push(copyUnit(item));
  1255. }
  1256.  
  1257. break;
  1258. }
  1259. } while (item.getNext());
  1260.  
  1261. while (clearList.length > 0) {
  1262. clearList.shift().interact();
  1263. delay(200);
  1264. }
  1265. }
  1266.  
  1267. return true;
  1268. },
  1269.  
  1270. clearInventory: function () {
  1271. var i, loseItemAction,
  1272. dropAction = 0,
  1273. sellAction = 1,
  1274. items = me.getItems();
  1275.  
  1276. if (items) {
  1277. for (i = 0; i < items.length; i += 1) {
  1278. if (items[i].mode === 0 && items[i].location === 3) {
  1279. switch (items[i].itemType) {
  1280. case 76:
  1281. if (!Config.HPBuffer) {
  1282. items[i].interact();
  1283. delay(200);
  1284. }
  1285.  
  1286. break;
  1287. case 77:
  1288. if (!Config.MPBuffer) {
  1289. items[i].interact();
  1290. delay(200);
  1291. }
  1292.  
  1293. break;
  1294. case 78:
  1295. if (!Config.RejuvBuffer) {
  1296. items[i].interact();
  1297. delay(200);
  1298. }
  1299.  
  1300. break;
  1301. }
  1302. }
  1303. }
  1304. }
  1305.  
  1306. // Any leftover items from a failed ID (crashed game, disconnect etc.)
  1307. items = Storage.Inventory.Compare(Config.Inventory);
  1308.  
  1309. // If low on gold
  1310. if (me.getStat(14) + me.getStat(15) < Config.LowGold) {
  1311. this.initNPC("Shop");
  1312.  
  1313. loseItemAction = sellAction;
  1314. } else {
  1315. loseItemAction = dropAction;
  1316. }
  1317.  
  1318. for (i = 0; !!items && i < items.length; i += 1) {
  1319. if ([18, 41, 78].indexOf(items[i].itemType) === -1 &&
  1320. (items[i].code !== "tsc" || !!me.findItem("tbk", 0, 3)) &&
  1321. (items[i].code !== "isc" || !!me.findItem("ibk", 0, 3)) &&
  1322. (Pickit.checkItem(items[i]).result === 0 ||
  1323. Pickit.checkItem(items[i]).result === 4) &&
  1324. !Cubing.keepItem(items[i]) &&
  1325. !Runewords.keepItem(items[i])) {
  1326. try {
  1327. if (loseItemAction === sellAction) {
  1328. items[i].sell();
  1329. } else {
  1330. items[i].drop();
  1331. }
  1332. } catch (e) {
  1333. print(e);
  1334. }
  1335. }
  1336. }
  1337.  
  1338. return true;
  1339. },
  1340.  
  1341. act : [{}, {}, {}, {}, {}],
  1342. initialize: function () {
  1343. //print("Initialize town " + me.act);
  1344.  
  1345. switch (me.act) {
  1346. case 1:
  1347. var fire,
  1348. wp = getPresetUnit(1, 2, 119),
  1349. fireUnit = getPresetUnit(1, 2, 39);
  1350.  
  1351. if (!fireUnit) {
  1352. return false;
  1353. }
  1354.  
  1355. fire = [fireUnit.roomx * 5 + fireUnit.x, fireUnit.roomy * 5 + fireUnit.y];
  1356.  
  1357. this.act[0].spot = {};
  1358. this.act[0].spot.stash = [fire[0] - 7, fire[1] - 12];
  1359. this.act[0].spot.warriv = [fire[0] - 5, fire[1] - 2];
  1360. this.act[0].spot.cain = [fire[0] + 6, fire[1] - 5];
  1361. this.act[0].spot[NPC.Kashya] = [fire[0] + 14, fire[1] - 4];
  1362. this.act[0].spot[NPC.Akara] = [fire[0] + 56, fire[1] - 30];
  1363. this.act[0].spot[NPC.Charsi] = [fire[0] - 39, fire[1] - 25];
  1364. this.act[0].spot[NPC.Gheed] = [fire[0] - 34, fire[1] + 36];
  1365. this.act[0].spot.portalspot = [fire[0] + 10, fire[1] + 18];
  1366. this.act[0].spot.waypoint = [wp.roomx * 5 + wp.x, wp.roomy * 5 + wp.y];
  1367. this.act[0].initialized = true;
  1368.  
  1369. break;
  1370. case 2:
  1371. this.act[1].spot = {};
  1372. this.act[1].spot[NPC.Fara] = [5124, 5082];
  1373. this.act[1].spot.cain = [5124, 5082];
  1374. this.act[1].spot[NPC.Lysander] = [5118, 5104];
  1375. this.act[1].spot[NPC.Greiz] = [5033, 5053];
  1376. this.act[1].spot[NPC.Elzix] = [5032, 5102];
  1377. this.act[1].spot.palace = [5088, 5153];
  1378. this.act[1].spot.sewers = [5221, 5181];
  1379. this.act[1].spot.meshif = [5205, 5058];
  1380. this.act[1].spot[NPC.Drognan] = [5097, 5035];
  1381. this.act[1].spot.atma = [5140, 5055];
  1382. this.act[1].spot.warriv = [5152, 5201];
  1383. this.act[1].spot.portalspot = [5168, 5055];
  1384. this.act[1].spot.stash = [5124, 5082];
  1385. this.act[1].spot.waypoint = [5070, 5083];
  1386. this.act[1].initialized = true;
  1387.  
  1388. break;
  1389. case 3:
  1390. this.act[2].spot = {};
  1391. this.act[2].spot.meshif = [5118, 5168];
  1392. this.act[2].spot[NPC.Hratli] = [5223, 5048, 5127, 5172];
  1393. this.act[2].spot[NPC.Ormus] = [5129, 5093];
  1394. this.act[2].spot[NPC.Asheara] = [5043, 5093];
  1395. this.act[2].spot[NPC.Alkor] = [5083, 5016];
  1396. this.act[2].spot.cain = [5148, 5066];
  1397. this.act[2].spot.stash = [5144, 5059];
  1398. this.act[2].spot.portalspot = [5156, 5063];
  1399. this.act[2].spot.waypoint = [5158, 5050];
  1400. this.act[2].initialized = true;
  1401.  
  1402. break;
  1403. case 4:
  1404. this.act[3].spot = {};
  1405. this.act[3].spot.cain = [5027, 5027];
  1406. this.act[3].spot[NPC.Halbu] = [5089, 5031];
  1407. this.act[3].spot[NPC.Tyrael] = [5027, 5027];
  1408. this.act[3].spot[NPC.Jamella] = [5088, 5054];
  1409. this.act[3].spot.stash = [5022, 5040];
  1410. this.act[3].spot.portalspot = [5045, 5042];
  1411. this.act[3].spot.waypoint = [5043, 5018];
  1412. this.act[3].initialized = true;
  1413.  
  1414. break;
  1415. case 5:
  1416. this.act[4].spot = {};
  1417. this.act[4].spot.portalspot = [5098, 5019];
  1418. this.act[4].spot.stash = [5129, 5061];
  1419. this.act[4].spot[NPC.Larzuk] = [5141, 5045];
  1420. this.act[4].spot[NPC.Malah] = [5078, 5029];
  1421. this.act[4].spot.cain = [5119, 5061];
  1422. this.act[4].spot[NPC["Qual-Kehk"]] = [5066, 5083];
  1423. this.act[4].spot[NPC.Anya] = [5112, 5120];
  1424. this.act[4].spot.portal = [5118, 5120];
  1425. this.act[4].spot.waypoint = [5113, 5068];
  1426. this.act[4].spot.nihlathak = [5071, 5111];
  1427. this.act[4].initialized = true;
  1428.  
  1429. break;
  1430. }
  1431.  
  1432. return true;
  1433. },
  1434.  
  1435. move: function (spot) {
  1436. if (!me.inTown && !this.goToTown()) { // To prevent long trips if tp to town failed
  1437. throw new Error("Town.move: Failed to go to town!");
  1438. }
  1439.  
  1440. /*while (!me.idle) {
  1441. delay(40);
  1442. }*/
  1443.  
  1444. var i, townSpot, path,
  1445. useTK = me.classid === 1 && ((me.getSkill(43, 1) && ["stash", "portalspot"].indexOf(spot) > -1) || spot === "waypoint");
  1446.  
  1447. if (!this.act[me.act - 1].initialized) {
  1448. this.initialize();
  1449. }
  1450.  
  1451. if (typeof (this.act[me.act - 1].spot[spot]) === "object") {
  1452. townSpot = this.act[me.act - 1].spot[spot];
  1453. } else {
  1454. return false;
  1455. }
  1456.  
  1457. // Act 5 hack
  1458. if (me.act === 5 && spot === "portalspot" && getDistance(me, 5113, 5068) <= 8) {
  1459. me.overhead("a5 path override");
  1460.  
  1461. path = [5113, 5068, 5108, 5051, 5106, 5046, 5104, 5041, 5102, 5027, 5098, 5018];
  1462.  
  1463. for (i = 0; i < path.length; i += 2) {
  1464. Pather.walkTo(path[i], path[i + 1]);
  1465. }
  1466.  
  1467. return true;
  1468. }
  1469.  
  1470. if (useTK) {
  1471. if (getDistance(me, townSpot[0], townSpot[1]) > 14) {
  1472. Attack.getIntoPosition({x: townSpot[0], y: townSpot[1]}, 13, 0x4);
  1473. }
  1474. } else {
  1475. print("Townmove: " + spot + " " + townSpot);
  1476. Pather.moveTo(townSpot[0], townSpot[1]);
  1477.  
  1478. // If unit has more than one location and it's not here, search
  1479. if (townSpot.length > 2 && !getUnit(1, spot)) {
  1480. for (i = 0; i < townSpot.length / 2; i += 1) {
  1481. Pather.moveTo(townSpot[i * 2], townSpot[i * 2 + 1]);
  1482.  
  1483. if (!!getUnit(1, spot)) {
  1484. break;
  1485. }
  1486. }
  1487. }
  1488. }
  1489.  
  1490. return true;
  1491. },
  1492.  
  1493. goToTown: function (act) {
  1494. var towns = [1, 40, 75, 103, 109];
  1495.  
  1496. if (!me.inTown) {
  1497. if (!Pather.makePortal()) {
  1498. throw new Error("Town.goToTown: Failed to make TP");
  1499. }
  1500.  
  1501. if (!Pather.usePortal(null, me.name)) {
  1502. throw new Error("Town.goToTown: Failed to take TP");
  1503. }
  1504. }
  1505.  
  1506. if (typeof act === "undefined") {
  1507. return true;
  1508. }
  1509.  
  1510. if (act < 1 || act > 5) {
  1511. throw new Error("Town.goToTown: Invalid act!");
  1512. }
  1513.  
  1514. if (act !== me.act) {
  1515. if (!Pather.useWaypoint(towns[act - 1])) {
  1516. throw new Error("Town.goToTown: Failed to go to town");
  1517. }
  1518. }
  1519.  
  1520. return true;
  1521. },
  1522.  
  1523. visitTown: function () {
  1524. if (me.inTown) {
  1525. this.doChores();
  1526. this.move("stash");
  1527.  
  1528. return true;
  1529. }
  1530.  
  1531. var preArea = me.area;
  1532.  
  1533. try { // not an essential function -> handle thrown errors
  1534. this.goToTown();
  1535. } catch (e) {
  1536. return false;
  1537. }
  1538.  
  1539. this.doChores();
  1540. this.move("portalspot");
  1541.  
  1542. if (!Pather.usePortal(preArea, me.name)) { // this part is essential
  1543. throw new Error("Town.VisitTown: Failed to go back from town.");
  1544. }
  1545.  
  1546. if (Config.PublicMode) {
  1547. Pather.makePortal();
  1548. }
  1549.  
  1550. return true;
  1551. }
  1552. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement