Guest User

Untitled

a guest
Oct 25th, 2019
236
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.92 KB | None | 0 0
  1. /**
  2. * @filename Necromancer.js
  3. * @author kolton
  4. * @desc Necromancer attack sequence
  5. */
  6.  
  7. var ClassAttack = {
  8. skillRange: [],
  9. skillHand: [],
  10. skillElement: [],
  11. curseState: [],
  12. novaTick: 0,
  13.  
  14. init: function () {
  15. var i;
  16.  
  17. for (i = 0; i < Config.LowManaSkill.length; i += 1) {
  18. Config.AttackSkill.push(Config.LowManaSkill[i]);
  19. }
  20.  
  21. for (i = 0; i < Config.AttackSkill.length; i += 1) {
  22. this.skillHand[i] = getBaseStat("skills", Config.AttackSkill[i], "leftskill");
  23. this.skillElement[i] = Attack.getSkillElement(Config.AttackSkill[i]);
  24.  
  25. switch (Config.AttackSkill[i]) {
  26. case 0: // Normal Attack
  27. this.skillRange[i] = Attack.usingBow() ? 20 : 2;
  28. this.skillHand[i] = 2; // shift bypass
  29.  
  30. break;
  31. case 73: // Poison Dagger
  32. this.skillRange[i] = 2;
  33.  
  34. break;
  35. case 92: // Poison Nova
  36. this.skillRange[i] = 8;
  37.  
  38. break;
  39. case 67: // Teeth
  40. case 84: // Bone Spear
  41. case 93: // Bone Spirit
  42. this.skillRange[i] = 15;
  43.  
  44. break;
  45. case 500: // Summoner
  46. this.skillRange[i] = 5;
  47.  
  48. break;
  49. default: // Every other skill
  50. this.skillRange[i] = 20;
  51.  
  52. break;
  53. }
  54. }
  55.  
  56. for (i = 0; i < Config.Curse.length; i += 1) {
  57. switch (Config.Curse[i]) {
  58. case 0: //nothing
  59. this.curseState[i] = 0;
  60.  
  61. break;
  62. case 66: //amplify damage
  63. this.curseState[i] = 9;
  64.  
  65. break;
  66. case 71: //dim vision
  67. this.curseState[i] = 23;
  68.  
  69. break;
  70. case 72: //weaken
  71. this.curseState[i] = 19;
  72.  
  73. break;
  74. case 76: //iron maiden
  75. this.curseState[i] = 55;
  76.  
  77. break;
  78. case 77: //terror
  79. this.curseState[i] = 56;
  80.  
  81. break;
  82. case 81: //confuse
  83. this.curseState[i] = 59;
  84.  
  85. break;
  86. case 82: //life tap
  87. this.curseState[i] = 58;
  88.  
  89. break;
  90. case 86: //attract
  91. this.curseState[i] = 57;
  92.  
  93. break;
  94. case 87: //decrepify
  95. this.curseState[i] = 60;
  96.  
  97. break;
  98. case 91: //lower resist
  99. this.curseState[i] = 61;
  100.  
  101. break;
  102. default:
  103. Config.Curse[i] = 0;
  104. print("Invalid curse id");
  105.  
  106. break;
  107. }
  108. }
  109. },
  110.  
  111. doAttack: function (unit, preattack) {
  112. if (Config.MercWatch && Town.needMerc()) {
  113. Town.visitTown();
  114. }
  115.  
  116. if (preattack && Config.AttackSkill[0] > 0 && Attack.checkResist(unit, this.skillElement[0]) && (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[0]))) {
  117. if (Math.round(getDistance(me, unit)) > this.skillRange[0] || checkCollision(me, unit, 0x4)) {
  118. if (!Attack.getIntoPosition(unit, this.skillRange[0], 0x4)) {
  119. return 1;
  120. }
  121. }
  122.  
  123. if (!Skill.cast(Config.AttackSkill[0], this.skillHand[0], unit)) {
  124. return 2;
  125. }
  126.  
  127. return 3;
  128. }
  129.  
  130. var index;
  131.  
  132. index = ((unit.spectype & 0x7) || unit.type === 0) ? 1 : 3;
  133.  
  134. if (Config.Curse[0] > 0 && this.isCursable(unit) && (unit.spectype & 0x7) && !unit.getState(this.curseState[0])) {
  135. if (getDistance(me, unit) > 25 || checkCollision(me, unit, 0x4)) {
  136. if (!Attack.getIntoPosition(unit, 25, 0x4)) {
  137. return 1;
  138. }
  139. }
  140.  
  141. if (!Skill.cast(Config.Curse[0], 0, unit)) {
  142. return 2;
  143. }
  144.  
  145. return 3;
  146. }
  147.  
  148. if (Config.Curse[1] > 0 && this.isCursable(unit) && !(unit.spectype & 0x7) && !unit.getState(this.curseState[1])) {
  149. if (getDistance(me, unit) > 25 || checkCollision(me, unit, 0x4)) {
  150. if (!Attack.getIntoPosition(unit, 25, 0x4)) {
  151. return 1;
  152. }
  153. }
  154.  
  155. if (!Skill.cast(Config.Curse[1], 0, unit)) {
  156. return 2;
  157. }
  158.  
  159. return 3;
  160. }
  161.  
  162. if (Attack.checkResist(unit, this.skillElement[index])) {
  163. switch (this.doCast(unit, index)) {
  164. case 0: // total fail
  165. return 1;
  166. case false: // fail to cast
  167. return 2;
  168. }
  169.  
  170. if (Config.ActiveSummon) {
  171. this.raiseArmy();
  172. }
  173.  
  174. this.explodeCorpses(unit);
  175.  
  176. return 3;
  177. }
  178.  
  179. if (Config.AttackSkill[5] > -1 && Attack.checkResist(unit, this.skillElement[5])) {
  180. switch (this.doCast(unit, 5)) {
  181. case 0: // total fail
  182. return 1;
  183. case false: // fail to cast
  184. return 2;
  185. }
  186.  
  187. if (Config.ActiveSummon) {
  188. this.raiseArmy();
  189. }
  190.  
  191. this.explodeCorpses(unit);
  192.  
  193. return 3;
  194. }
  195.  
  196. if (Attack.checkResist(unit, "physical") && me.getMerc()) {
  197. if (Config.TeleStomp && getDistance(me, unit) > 3) {
  198. Pather.moveToUnit(unit);
  199. }
  200.  
  201. if (Config.ActiveSummon) {
  202. this.raiseArmy();
  203. }
  204.  
  205. this.explodeCorpses(unit);
  206. delay(300);
  207.  
  208. return 3;
  209. }
  210.  
  211. return 1;
  212. },
  213.  
  214. afterAttack: function () {
  215. Precast.doPrecast(false);
  216. this.raiseArmy();
  217. this.novaTick = 0;
  218. },
  219.  
  220. doCast: function (unit, index) {
  221. var i,
  222. timed = index,
  223. untimed = index + 1;
  224.  
  225. // Low mana timed skill
  226. if (Config.AttackSkill[timed] > -1 && Config.AttackSkill[Config.AttackSkill.length - 2] > -1 && Skill.getManaCost(Config.AttackSkill[timed]) > me.mp) {
  227. timed = Config.AttackSkill.length - 2;
  228. }
  229.  
  230. if (Config.AttackSkill[timed] === 92) {
  231. if (!this.novaTick || getTickCount() - this.novaTick > Config.PoisonNovaDelay * 1000) {
  232. if (Math.round(getDistance(me, unit)) > this.skillRange[timed] || checkCollision(me, unit, 0x4)) {
  233. if (!Attack.getIntoPosition(unit, this.skillRange[timed], 0x4)) {
  234. return 0;
  235. }
  236. }
  237.  
  238. if (Skill.cast(Config.AttackSkill[timed], this.skillHand[timed], unit)) {
  239. this.novaTick = getTickCount();
  240.  
  241. return true;
  242. }
  243.  
  244. return false;
  245. }
  246. } else if (!me.getState(121) || !Skill.isTimed(Config.AttackSkill[timed])) {
  247. if (Math.round(getDistance(me, unit)) > this.skillRange[timed] || checkCollision(me, unit, 0x4)) {
  248. if (!Attack.getIntoPosition(unit, this.skillRange[timed], 0x4)) {
  249. return 0;
  250. }
  251. }
  252.  
  253. if (Config.AttackSkill[timed] === 500) {
  254. delay(300);
  255.  
  256. return true;
  257. }
  258.  
  259. return Skill.cast(Config.AttackSkill[timed], this.skillHand[timed], unit);
  260. }
  261.  
  262. // Low mana untimed skill
  263. if (Config.AttackSkill[untimed] > -1 && Config.AttackSkill[Config.AttackSkill.length - 1] > -1 && Skill.getManaCost(Config.AttackSkill[untimed]) > me.mp) {
  264. untimed = Config.AttackSkill.length - 1;
  265. }
  266.  
  267. if (Config.AttackSkill[untimed] > -1) {
  268. if (Math.round(getDistance(me, unit)) > this.skillRange[untimed] || checkCollision(me, unit, 0x4)) {
  269. if (!Attack.getIntoPosition(unit, this.skillRange[untimed], 0x4)) {
  270. return 0;
  271. }
  272. }
  273.  
  274. return Skill.cast(Config.AttackSkill[untimed], this.skillHand[untimed], unit);
  275. }
  276.  
  277. for (i = 0; i < 25; i += 1) {
  278. delay(40);
  279.  
  280. if (!me.getState(121)) {
  281. break;
  282. }
  283. }
  284.  
  285. while (this.novaTick && getTickCount() - this.novaTick < Config.PoisonNovaDelay * 1000) {
  286. delay(40);
  287. }
  288.  
  289. return false;
  290. },
  291.  
  292. isCursable: function (unit) {
  293. if (typeof copyUnit(unit).name === "undefined" || unit.name.indexOf(getLocaleString(11086)) > -1) { // "Possessed"
  294. return false;
  295. }
  296.  
  297. if (unit.getState(57)) { // attract can't be overridden
  298. return false;
  299. }
  300.  
  301. switch (unit.classid) {
  302. case 206: // Foul Crow Nest
  303. case 258: // Water Watcher
  304. case 261: // Water Watcher
  305. case 266: // Flavie
  306. case 528: // Evil Demon Hut
  307. return false;
  308. }
  309.  
  310. return true;
  311. },
  312.  
  313. raiseArmy: function (range) {
  314. var i, tick, count, corpse, corpseList, skill, maxSkeletons, maxMages, maxRevives;
  315.  
  316. if (!range) {
  317. range = 25;
  318. }
  319.  
  320. if (Config.Skeletons === "max") {
  321. skill = me.getSkill(70, 1);
  322. maxSkeletons = skill < 4 ? skill : (Math.floor(skill / 3) + 2);
  323. } else {
  324. maxSkeletons = Config.Skeletons;
  325. }
  326.  
  327. if (Config.SkeletonMages === "max") {
  328. skill = me.getSkill(80, 1);
  329. maxMages = skill < 4 ? skill : (Math.floor(skill / 3) + 2);
  330. } else {
  331. maxMages = Config.SkeletonMages;
  332. }
  333.  
  334. if (Config.Revives === "max") {
  335. skill = me.getSkill(95, 1);
  336. maxRevives = skill;
  337. } else {
  338. maxRevives = Config.Revives;
  339. }
  340.  
  341. for (i = 0; i < 3; i += 1) {
  342. corpse = getUnit(1, -1, 12);
  343. corpseList = [];
  344.  
  345. if (corpse) {
  346. do {
  347. if (getDistance(me, corpse) <= range && this.checkCorpse(corpse)) { // within casting distance
  348. corpseList.push(copyUnit(corpse));
  349. }
  350. } while (corpse.getNext());
  351. }
  352.  
  353. MainLoop:
  354. while (corpseList.length > 0) {
  355. corpse = corpseList.shift();
  356.  
  357. if (me.getMinionCount(4) < maxSkeletons) {
  358. if (!Skill.cast(70, 0, corpse)) {
  359. return false;
  360. }
  361.  
  362. count = me.getMinionCount(4);
  363. tick = getTickCount();
  364.  
  365. while (getTickCount() - tick < 200) {
  366. if (me.getMinionCount(4) > count) {
  367. break;
  368. }
  369.  
  370. delay(10);
  371. }
  372. } else if (me.getMinionCount(5) < maxMages) {
  373. if (!Skill.cast(80, 0, corpse)) {
  374. return false;
  375. }
  376.  
  377. count = me.getMinionCount(5);
  378. tick = getTickCount();
  379.  
  380. while (getTickCount() - tick < 200) {
  381. if (me.getMinionCount(5) > count) {
  382. break;
  383. }
  384.  
  385. delay(10);
  386. }
  387. } else if (me.getMinionCount(6) < maxRevives) {
  388. if (!this.checkCorpse(corpse, true)) {
  389. continue MainLoop;
  390. }
  391.  
  392. print("Reviving " + corpse.name);
  393.  
  394. if (!Skill.cast(95, 0, corpse)) {
  395. return false;
  396. }
  397.  
  398. count = me.getMinionCount(6);
  399. tick = getTickCount();
  400.  
  401. while (getTickCount() - tick < 200) {
  402. if (me.getMinionCount(6) > count) {
  403. break;
  404. }
  405.  
  406. delay(10);
  407. }
  408. } else {
  409. return true;
  410. }
  411. }
  412. }
  413.  
  414. return true;
  415. },
  416.  
  417. explodeCorpses: function (unit) {
  418. if (Config.ExplodeCorpses === 0 || unit.mode === 0 || unit.mode === 12) {
  419. return false;
  420. }
  421.  
  422. var corpseList = [],
  423. range = Math.floor((me.getSkill(Config.ExplodeCorpses, 1) + 7) / 3),
  424. corpse = getUnit(1, -1, 12);
  425.  
  426. if (corpse) {
  427. do {
  428. if (getDistance(unit, corpse) <= range && this.checkCorpse(corpse)) {
  429. corpseList.push(copyUnit(corpse));
  430.  
  431. if (corpseList.length >= 2) { // Explode 2 corpses per cycle, so we can leave some for summoning
  432. break;
  433. }
  434. }
  435. } while (corpse.getNext());
  436. }
  437.  
  438. while (corpseList.length > 0) {
  439. corpse = corpseList.shift();
  440.  
  441. me.overhead("Exploding: " + corpse.classid + " " + corpse.name);
  442.  
  443. if (Skill.cast(Config.ExplodeCorpses, 0, corpse)) {
  444. delay(200);
  445. }
  446. }
  447.  
  448. return true;
  449. },
  450.  
  451. checkCorpse: function (unit, revive) {
  452. if (unit.mode !== 12) {
  453. return false;
  454. }
  455.  
  456. if (typeof revive === "undefined") {
  457. revive = false;
  458. }
  459.  
  460. var baseId = getBaseStat("monstats", unit.classid, "baseid"),
  461. badList = [312, 571];
  462.  
  463. if (revive && ((unit.spectype & 0x7) || badList.indexOf(baseId) > -1 || (Config.ReviveUnstackable && getBaseStat("monstats2", baseId, "sizex") === 3))) {
  464. return false;
  465. }
  466.  
  467. if (!getBaseStat("monstats2", baseId, revive ? "revive" : "corpseSel")) {
  468. return false;
  469. }
  470.  
  471. if (getDistance(me, unit) <= 25 && !checkCollision(me, unit, 0x4) &&
  472. !unit.getState(1) && // freeze
  473. !unit.getState(96) && // revive
  474. !unit.getState(99) && // redeemed
  475. !unit.getState(104) && // nodraw
  476. !unit.getState(107) && // shatter
  477. !unit.getState(118) // noselect
  478. ) {
  479. return true;
  480. }
  481.  
  482. return false;
  483. }
  484. };
Advertisement
Add Comment
Please, Sign In to add comment