hugmeir

Untitled

Sep 27th, 2018
92
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 32.08 KB | None | 0 0
  1. $ cat combat_macro.ash
  2. // hugmeir's combat script. WIP forever.
  3. import <zlib.ash>
  4.  
  5. boolean [string] mm;
  6. boolean monster_modifiers_may_stop_actions() {
  7. if ( mm["annoying"] || mm["phase-shifting"] || mm["restless"] )
  8. return true;
  9. return false;
  10. }
  11.  
  12. int get_property_int(string prop) {
  13. return get_property(prop).to_int();
  14. }
  15.  
  16. boolean can_use_skill(skill this_skill) {
  17. if ( !have_skill(this_skill) )
  18. return false;
  19.  
  20. if ( !this_skill.is_unrestricted() )
  21. return false;
  22.  
  23. boolean can_use_skill = true;
  24. switch ( this_skill ) {
  25. case $skill[KGB tranquilizer dart]:
  26. if ( get_property_int("_kgbTranquilizerDartUses") >= 3 )
  27. return false;
  28. break;
  29. case $skill[Snokebomb]:
  30. if ( get_property_int("_snokebombUsed") >= 3 )
  31. return false;
  32. break;
  33. case $skill[Shattering Punch]:
  34. if ( get_property_int("_shatteringPunchUsed") >= 3 )
  35. return false;
  36. break;
  37. case $skill[Macrometeorite]:
  38. if ( get_property_int("_macrometeoriteUses") >= 10 )
  39. return false;
  40. break;
  41. }
  42.  
  43. if ( mp_cost(this_skill) > my_mp() )
  44. return false;
  45.  
  46. return true;
  47. }
  48.  
  49. string [int] macro_list;
  50. void push_turnless_macro(string elem) {
  51. int idx = macro_list.count();
  52. macro_list[idx] = elem;
  53. return;
  54. }
  55.  
  56. int rounds_so_far = 0;
  57. void push_action(string elem) {
  58. push_turnless_macro(elem);
  59. rounds_so_far += 1;
  60. return;
  61. }
  62.  
  63. void push_blockable_action(string action) {
  64. push_action(action);
  65. if ( monster_modifiers_may_stop_actions() ) {
  66. string [int] bullshit;
  67. if ( mm["phase-shifting"] )
  68. bullshit[bullshit.count()] = "blinks out of existence";
  69. if ( mm["annoying"] )
  70. bullshit[bullshit.count()] = "stopping you in your tracks";
  71. if ( mm["restless"] )
  72. bullshit[bullshit.count()] = "moves out of the way before you can";
  73. bullshit[bullshit.count()] = "moved by the time you can finish";
  74. if ( mm["cartwheeling"] )
  75. bullshit[bullshit.count()] = "cartwheels out of the way";
  76.  
  77. buffer repeat_macro;
  78. repeat_macro.append("repeat ");
  79. foreach idx, match_string in bullshit {
  80. if ( idx != 0 )
  81. repeat_macro.append(" || ");
  82. repeat_macro.append("match \"" + match_string +"\"");
  83. }
  84.  
  85. push_turnless_macro(repeat_macro.to_string());
  86. }
  87. }
  88.  
  89. string compose_combat_macro() {
  90. buffer result;
  91.  
  92. foreach idx, macro in macro_list {
  93. if ( idx == 0 ) {
  94. result.append(macro);
  95. }
  96. else {
  97. result.append(";");
  98. result.append(macro);
  99. }
  100. }
  101. return result.to_string();
  102. }
  103.  
  104. void push_item_multiuse_if_possible(item this_item) {
  105. int item_amount = this_item.item_amount();
  106. if ( item_amount > 0) {
  107. if ( item_amount == 1 ) {
  108. push_blockable_action("use " + this_item.to_string());
  109. }
  110. else {
  111. push_blockable_action("use " + this_item.to_string() + ", " + this_item.to_string());
  112. }
  113. }
  114. }
  115.  
  116. void push_skill (skill this_skill) {
  117. push_turnless_macro("if hasskill " + this_skill.to_int());
  118. push_blockable_action("skill " + this_skill.to_string());
  119. push_turnless_macro("endif");
  120. }
  121.  
  122. void push_skill (string skill_as_string) {
  123. push_blockable_action("skill " + skill_as_string);
  124. }
  125.  
  126. boolean [location, monster] yellow_ray_targets;
  127. // Filthworms:
  128. yellow_ray_targets[ $location[The Hatching Chamber] ][ $monster[larval filthworm] ] = true;
  129.  
  130. // War Hippies, for the outfit:
  131. yellow_ray_targets[ $location[Wartime Hippy Camp (frat disguise)] ][ $monster[War Hippy drill sergeant] ] = true;
  132. yellow_ray_targets[ $location[Wartime Hippy Camp (frat disguise)] ][ $monster[War Hippy (space) cadet] ] = true;
  133.  
  134. // drum machine (maybe?)
  135. yellow_ray_targets[ $location[The Oasis] ][ $monster[blur] ] = true;
  136.  
  137. boolean yellow_ray_target(monster foe) {
  138. location where = my_location();
  139. if ( ! (yellow_ray_targets contains where) )
  140. return false;
  141. if ( ! (yellow_ray_targets[where] contains foe) )
  142. return false;
  143.  
  144. return true;
  145. }
  146.  
  147. void yellow_ray (monster foe) {
  148. // DO NOT YELLOW RAY WHEN WE HAVE SQUINT ON
  149. if ( $effect[Steely-Eyed Squint].have_effect() > 0 )
  150. return;
  151.  
  152. // See if we can even yellow ray:
  153. if ( $effect[Everything Looks Yellow].have_effect() > 0 )
  154. return;
  155.  
  156. // TODO: check if we have enough +item to make this not neccessary
  157. return;
  158. }
  159.  
  160. void instakill_macro(monster foe) {
  161. if ( yellow_ray_target(foe) ) {
  162. yellow_ray(foe);
  163. }
  164. foreach this_item in $items[exploding cigar] {
  165. push_item_multiuse_if_possible(this_item);
  166. }
  167.  
  168. foreach this_skill in $skills[shattering punch, macrometeorite, cleesh] {
  169. if ( can_use_skill( this_skill ) )
  170. push_skill(this_skill);
  171. }
  172.  
  173. push_turnless_macro("abort \"I bring bad news\"");
  174. }
  175.  
  176. void get_stun_macro() {
  177. if ( can_use_skill($skill[noodles of fire]) ) {
  178. push_skill($skill[noodles of fire]);
  179. return;
  180. }
  181.  
  182. switch ( my_class() ) {
  183. case $class[pastamancer]:
  184. push_skill($skill[entangling noodles]);
  185. return;
  186. case $class[seal clubber]:
  187. // todo if club is equipped
  188. if (
  189. $slot[weapon].equipped_item().item_type() == "club"
  190. &&
  191. my_fury() > 1
  192. &&
  193. can_use_skill($skill[club foot])
  194. ) {
  195. push_skill($skill[club foot]);
  196. return;
  197. }
  198. break;
  199. case $class[sauceror]:
  200. if ( my_soulsauce() > 5 && can_use_skill($skill[soul bubble]) ) {
  201. push_skill($skill[soul bubble]);
  202. return;
  203. }
  204. break;
  205. case $class[accordion thief]:
  206. if (
  207. $slot[weapon].equipped_item().item_type() == "accordion"
  208. &&
  209. can_use_skill($skill[accordion bash])
  210. ) {
  211. push_skill($skill[accordion bash]);
  212. return;
  213. }
  214. break;
  215. // TODO TT love.
  216. // case $class[turtle tamer]:
  217. // if hasskill shell up && (haseffect 1422 || haseffect 1423 || haseffect 1424)
  218. // if ( can_use_skill($skill[shell up]) && )
  219. // break;
  220. default:
  221. break;
  222. }
  223.  
  224. if ( can_use_skill($skill[shadow noodles]) && false ) {
  225. push_skill($skill[shadow noodles]);
  226. return;
  227. }
  228. return;
  229. }
  230.  
  231. void push_olfaction() {
  232. if ( can_use_skill($skill[Transcendent Olfaction]) && $effect[On the Trail].have_effect() == 0 ) {
  233. // push_turnless_macro("if hasskill Transcendent Olfaction");
  234. push_skill($skill[Transcendent Olfaction]);
  235. // push_turnless_macro("endif");
  236. }
  237. }
  238.  
  239. void gallappagos_macro() {
  240. if ( can_use_skill($skill[Gallapagosian Mating Call]) ) {
  241. push_turnless_macro("if hasskill Gallapagosian Mating Call");
  242. push_skill($skill[Gallapagosian Mating Call]);
  243. push_turnless_macro("endif");
  244. }
  245. }
  246.  
  247. void nosy_nose_olfact_macro() {
  248. if ( my_familiar() == $familiar[Nosy Nose] ) {
  249. push_blockable_action("skill 7166");
  250. }
  251. }
  252.  
  253. void micrometeorite_macro () {
  254. push_turnless_macro("if hasskill micrometeorite");
  255. push_skill("micrometeorite");
  256. push_turnless_macro("endif");
  257. }
  258.  
  259. int _expected_damage(monster foe, stat this_stat) {
  260. int player_stat = my_buffedstat(this_stat);
  261. float attack_type_multiplier = 1.0; // no lunging permed yet
  262. float weapon_type_multiplier = 0.75;
  263.  
  264. int initial_damage = floor(
  265. player_stat * attack_type_multiplier * weapon_type_multiplier
  266. );
  267.  
  268. if ( initial_damage < 0 )
  269. initial_damage = 0;
  270.  
  271. int damage_minus_def = initial_damage - foe.base_defense;
  272.  
  273. // TODO fists?
  274. item weapon = $slot[weapon].equipped_item();
  275. int weapon_damage = weapon.get_power();
  276.  
  277. int crit_multiplier = 1; // eh
  278. int weapon_damage_total = weapon_damage * crit_multiplier * attack_type_multiplier;
  279.  
  280. int bonus_weapon_damage = numeric_modifier("Weapon Damage").to_int();
  281.  
  282. int bonus_prism = numeric_modifier("Prismatic Damage");
  283.  
  284. int total = damage_minus_def + weapon_damage_total + bonus_weapon_damage + bonus_prism;
  285.  
  286. // wiki formula stops at total, but that gives results almost twice
  287. // as high as the actual damage dealt. I probably have one of
  288. // the inputs wrong. In any case, let's just go very conservative
  289. // and just return half of the damage the formula gave us.
  290. return floor(total / 2);
  291. }
  292.  
  293. int expected_ranged_damage(monster foe) {
  294. int ranged_damage = _expected_damage(foe, $stat[moxie]);
  295. int bonus_ranged_damage = numeric_modifier("Ranged Damage").to_int();
  296.  
  297. return ranged_damage + bonus_ranged_damage;
  298. }
  299.  
  300. int expected_weapon_damage(monster foe) {
  301. return _expected_damage(foe, $stat[muscle]);
  302. }
  303.  
  304. void release_the_boots(monster foe) {
  305. if ( my_familiar() != $familiar[Pair of Stomping Boots] ) {
  306. return;
  307. }
  308.  
  309. push_turnless_macro("if hasskill Release the Boots");
  310. push_skill($skill[Release the Boots]);
  311. push_turnless_macro("endif");
  312. }
  313.  
  314. void default_fight_macro(monster foe) {
  315. boolean immune_to_physical = false;
  316.  
  317. switch (foe) {
  318. case $monster[mouthless murmur]:
  319. immune_to_physical = true;
  320. break;
  321. default:
  322. immune_to_physical = foe.physical_resistance >= 90;
  323. }
  324.  
  325. release_the_boots(foe);
  326. if ( my_fury() > 1 && $slot[weapon].equipped_item() == $item[bindlestocking] ) {
  327. push_skill("furious wallop");
  328. }
  329.  
  330. push_turnless_macro("while !pastround 26"); // 28 aborts all
  331. if ( mm["untouchable"] || immune_to_physical ) {
  332. // rainbow damage. Or well, this because it's all I got
  333. push_action("skill saucestorm");
  334. }
  335. else {
  336. item equipped_weapon = $slot[weapon].equipped_item();
  337. string equipped_weapon_type = weapon_type(equipped_weapon);
  338. int expected_attack_damage = 0;
  339. if ( equipped_weapon_type == $stat[moxie] ) {
  340. expected_attack_damage = expected_ranged_damage(foe);
  341. }
  342. else if ( equipped_weapon_type == $stat[muscle] ) {
  343. expected_attack_damage = expected_weapon_damage(foe);
  344. }
  345.  
  346. if ( expected_attack_damage > 80 ) {
  347. push_action("attack");
  348. }
  349. else {
  350. push_action("skill saucestorm");
  351. }
  352. if ( $item[gauze garter].item_amount() > 1 ) {
  353. // TODO moar
  354. push_turnless_macro("if hppercentbelow 50 && pastround 10");
  355. push_item_multiuse_if_possible($item[gauze garter]);
  356. push_turnless_macro("endif");
  357. }
  358. }
  359. push_turnless_macro("endwhile");
  360.  
  361. if ( mm["untouchable"] ) {
  362. // Instakill anything that got this far.
  363. instakill_macro(foe);
  364. }
  365. }
  366.  
  367. boolean ticking_and_needs_instakill(monster foe) {
  368. if ( !mm["ticking"] )
  369. return false;
  370.  
  371. if ( mm["frozen"] )
  372. return false;
  373.  
  374. if ( mm["fragile"] && !mm["unlucky"] )
  375. return false;
  376.  
  377. if ( mm["untouchable"] ) {
  378. if ( mm["unlucky"] )
  379. return false; // we'll see.
  380. return true;
  381. }
  382.  
  383. if ( monster_modifiers_may_stop_actions() && foe.raw_hp > 90 )
  384. return true;
  385.  
  386. return false;
  387. }
  388.  
  389. boolean generic_should_olfact (monster foe) {
  390. switch (foe) {
  391. case $monster[drunk pygmy]: return true;
  392. case $monster[pygmy witch surgeon]: return true;
  393. case $monster[pygmy shaman]: return true;
  394. case $monster[gaudy pirate]: return true;
  395. case $monster[dirty old lihc]: return true;
  396. case $monster[tomb rat]: return true;
  397. case $monster[pygmy witch accountant]:
  398. if (my_location() == $location[The Hidden Office Building])
  399. return true;
  400. return false;
  401. }
  402. return false;
  403. }
  404.  
  405. boolean foe_should_be_olfacted (monster foe) {
  406. if ( generic_should_olfact(foe) )
  407. return true;
  408. return false;
  409. }
  410.  
  411. boolean foe_should_be_nosy_nose_olfacted (monster foe) {
  412. if ( generic_should_olfact(foe) )
  413. return true;
  414. return false;
  415. }
  416.  
  417. boolean foe_should_be_gallagaposed (monster foe) {
  418. if ( generic_should_olfact(foe) )
  419. return true;
  420. return false;
  421. }
  422.  
  423. boolean will_survive_n_rounds(monster foe, int rounds) {
  424. int damage_in_one_turn = 0;
  425.  
  426. if ( mm["cowardly"] )
  427. return true;
  428.  
  429. foreach monster_modifier, has_modifier in mm {
  430. if ( has_modifier == true ) {
  431. switch ( monster_modifier ) {
  432. case "electrified":
  433. damage_in_one_turn += my_maxhp() * 0.2;
  434. break;
  435. case "filthy":
  436. case "foul-mouthed":
  437. case "haunted":
  438. case "hot":
  439. case "wet":
  440. damage_in_one_turn += 30; // eh
  441. break;
  442. }
  443. }
  444. }
  445.  
  446. int plain_attack_damage = expected_damage(foe);
  447.  
  448. if ( plain_attack_damage < 0 ) // unspaded monster
  449. plain_attack_damage = 10;
  450.  
  451. if ( mm["shaky"] ) {
  452. plain_attack_damage = plain_attack_damage * 3;
  453. }
  454. else if ( mm["cloned"] ) {
  455. plain_attack_damage = plain_attack_damage * 2;
  456. }
  457.  
  458. print_html("plain dmg: " + plain_attack_damage + " | from mods: " + damage_in_one_turn);
  459. damage_in_one_turn += plain_attack_damage;
  460.  
  461. int total_damage = damage_in_one_turn * rounds;
  462.  
  463. return total_damage < my_hp();
  464. }
  465. boolean will_survive_round(monster foe) { // shortcut
  466. return will_survive_n_rounds(foe, 1);
  467. }
  468.  
  469. string gremlin_stasis_macro(monster foe) {
  470. // TODO
  471. return "abort \"Do gremlins on your own, you lazy fuck!\"";
  472. }
  473.  
  474. void rave_macro_generic(string which_combo) {
  475. string rave_combo = get_property("raveCombo1");
  476. if ( rave_combo == "" )
  477. return;
  478.  
  479. string [int] skill_order = rave_combo.split_string(",");
  480. foreach rave_skill in skill_order {
  481. push_skill(skill_order[rave_skill]);
  482. }
  483. }
  484.  
  485. void rave_plus_item_macro() {
  486. rave_macro_generic("raveCombo1");
  487. }
  488.  
  489. void rave_plus_meat_macro() {
  490. rave_macro_generic("raveCombo2");
  491. }
  492.  
  493. void rave_stun_macro() {
  494. rave_macro_generic("raveCombo3");
  495. }
  496.  
  497. boolean rave_steal_macro() {
  498. string rave_steal = get_property("raveCombo5");
  499. if ( rave_steal == "" )
  500. return false;
  501.  
  502. int steals_count = get_property("_raveStealCount").to_int();
  503. int steals_left = 30 - steals_count;
  504. if ( steals_left <= 0 )
  505. return false;
  506.  
  507. string [int] skill_order = rave_steal.split_string(",");
  508. foreach rave_skill in skill_order {
  509. push_skill(skill_order[rave_skill]);
  510. }
  511. return true;
  512. }
  513.  
  514. void pickpocket_macro(int num_items_dropped) {
  515. if ( num_items_dropped < 1 )
  516. return;
  517.  
  518. // no PP
  519. if ( !($classes[disco bandit,accordion thief] contains my_class()) )
  520. return;
  521.  
  522. // pp if we got the jump
  523. push_turnless_macro("if gotjump");
  524. push_action("pickpocket");
  525. push_turnless_macro("endif");
  526.  
  527. boolean have_second_pp = have_equipped($item[Bling of the New Wave]);
  528. if ( !have_second_pp )
  529. return;
  530.  
  531. // Second PP; only do it if the first attempt failed, OR
  532. // if the monster drops more than one item
  533. if ( num_items_dropped > 1 ) {
  534. push_action("pickpocket");
  535. }
  536. else {
  537. // Only drops one item. So only do the second PP
  538. // if the first one failed. This will also trigger if
  539. // we did not get the jump.
  540. push_turnless_macro("if !match \"You deftly slip your fingers\"");
  541. push_action("pickpocket");
  542. push_turnless_macro("endif");
  543. }
  544.  
  545. // match at this point will show whether we final pickpocket
  546. // succeeded
  547.  
  548. return;
  549. }
  550.  
  551. void disco_dance_macro() {
  552. push_skill("disco dance of doom");
  553. push_skill("disco dance ii");
  554. push_skill("disco dance 3");
  555. }
  556.  
  557. void add_goto_runaway_function(monster foe) {
  558. push_turnless_macro("sub try_goto_runaway");
  559. if ( mm["ticking"] ) {
  560. push_turnless_macro("if pastround 2");
  561. instakill_macro(foe);
  562. push_turnless_macro("endif");
  563. }
  564.  
  565. push_turnless_macro("while hascombatitem 4948");
  566. push_action("use 4948"); // hurmph.
  567. push_turnless_macro("endwhile");
  568.  
  569. // Stole the goto, tried to do a free runaway, but failed.
  570. // So just kill it.
  571. default_fight_macro(foe);
  572. push_turnless_macro("endsub");
  573. }
  574.  
  575. static
  576. {
  577. // Stolen from Ezandora, presumably originally taken from BanishManager.java
  578. int [string] __banish_source_length;
  579. __banish_source_length["banishing shout"] = -1;
  580. __banish_source_length["batter up!"] = -1;
  581. //__banish_source_length["chatterboxing"] = 20;
  582. __banish_source_length["classy monkey"] = 20;
  583. //__banish_source_length["cocktail napkin"] = 20;
  584. __banish_source_length["crystal skull"] = 20;
  585. __banish_source_length["deathchucks"] = -1;
  586. __banish_source_length["dirty stinkbomb"] = -1;
  587. __banish_source_length["divine champagne popper"] = 5;
  588. __banish_source_length["harold's bell"] = 20;
  589. __banish_source_length["howl of the alpha"] = -1;
  590. //__banish_source_length["ice house"] = -1;
  591. __banish_source_length["louder than bomb"] = 20;
  592. __banish_source_length["nanorhino"] = -1;
  593. __banish_source_length["pantsgiving"] = 30;
  594. __banish_source_length["peel out"] = -1;
  595. __banish_source_length["pulled indigo taffy"] = 20;
  596. __banish_source_length["smoke grenade"] = 20;
  597. //__banish_source_length["spooky music box mechanism"] = -1;
  598. __banish_source_length["staff of the standalone cheese"] = -1;
  599. __banish_source_length["stinky cheese eye"] = 10;
  600. __banish_source_length["thunder clap"] = 40;
  601. __banish_source_length["v for vivala mask"] = 10;
  602. __banish_source_length["walk away from explosion"] = 30;
  603. __banish_source_length["tennis ball"] = 30;
  604. __banish_source_length["curse of vacation"] = -1;
  605. __banish_source_length["ice hotel bell"] = -1;
  606. __banish_source_length["bundle of &quot;fragrant&quot; herbs"] = -1;
  607. __banish_source_length["snokebomb"] = 30;
  608. __banish_source_length["beancannon"] = -1;
  609. __banish_source_length["kgb tranquilizer dart"] = 20;
  610. __banish_source_length["spring-loaded front bumper"] = 30;
  611. __banish_source_length["mafia middle finger ring"] = 60;
  612. }
  613.  
  614.  
  615. string [monster] banishes_active() {
  616. string banished_monsters_string = get_property("banishedMonsters");
  617. string [monster] result;
  618.  
  619. // Stolen from Ezandora:
  620. string [int] banished_monsters_string_split = banished_monsters_string.split_string(":");
  621. foreach key, s in banished_monsters_string_split {
  622. if (s.length() == 0)
  623. continue;
  624. if (key % 3 != 0)
  625. continue;
  626.  
  627. if (!(banished_monsters_string_split contains (key + 1)) || !(banished_monsters_string_split contains (key + 2)))
  628. continue;
  629.  
  630. // Robbery ended here
  631. monster banished_foe = banished_monsters_string_split[key + 0].to_monster();
  632. string banish_source = banished_monsters_string_split[key + 1];
  633. result[banished_foe] = banish_source;
  634. }
  635.  
  636. return result;
  637. }
  638.  
  639. string [monster] foes_banished_in_location(location where) {
  640. string [monster] banishes_active = banishes_active();
  641. boolean [monster] location_monsters;
  642. foreach key, m in where.get_monsters() {
  643. location_monsters[m] = true;
  644. }
  645. string [monster] result;
  646. foreach banished_monster, banish_source in banishes_active {
  647. if (location_monsters contains banished_monster)
  648. result[banished_monster] = banish_source;
  649. }
  650. return result;
  651. }
  652.  
  653. boolean banish_not_active_and_can_use(boolean [string] banish_methods_active, string wanted_banish) {
  654. if ( banish_methods_active contains wanted_banish ) {
  655. return false;
  656. }
  657.  
  658. skill banish_skill = wanted_banish.to_skill();
  659. if ( banish_skill != $skill[none] ) {
  660. if ( !can_use_skill(banish_skill) )
  661. return false;
  662. push_skill(banish_skill);
  663. return true;
  664. }
  665.  
  666. item banish_item = wanted_banish.to_item();
  667. if ( banish_item != $item[none] ) {
  668. if ( banish_item.item_amount() > 0 ) {
  669. push_blockable_action("use " + banish_item.to_int());
  670. return true;
  671. }
  672. return false;
  673. }
  674.  
  675. print("No clue what to do with " + wanted_banish);
  676. return false;
  677. }
  678.  
  679. void do_any_banish(location where, monster foe) {
  680. boolean [string] banish_methods_active;
  681. foreach banished_foe, banish_method in foes_banished_in_location(where) {
  682. banish_methods_active[banish_method] = true;
  683. }
  684.  
  685. // Time to do the work!
  686. foreach banish_source, length in __banish_source_length {
  687. if ( banish_not_active_and_can_use(banish_methods_active, banish_source) ) {
  688. print("Will banish with " + banish_source);
  689. }
  690. }
  691. }
  692.  
  693. boolean delevel_is_useful(monster foe) {
  694. int monster_attack = foe.base_attack + 20; // to be on the safe side
  695.  
  696. if ( my_buffedstat($stat[moxie]) > monster_attack )
  697. return false;
  698.  
  699. return true;
  700. }
  701.  
  702. boolean in_aftercore() {
  703. return !in_hardcore() && can_interact();
  704. }
  705.  
  706. void tomb_rat_into_rat_king (monster foe) {
  707. if ( foe == $monster[tomb rat] && $item[tangle of rat tails].item_amount() > 0 ) {
  708. push_blockable_action("use tangle of rat tails");
  709. }
  710. }
  711.  
  712. void must_attempt_instakill_or_we_die(monster foe) {
  713. if ( ticking_and_needs_instakill(foe) ) {
  714. instakill_macro(foe);
  715. return;
  716. }
  717.  
  718. if ( !mm["unstoppable"] )
  719. return;
  720.  
  721. if ( !mm["electrified"] )
  722. return;
  723.  
  724. if ( !monster_modifiers_may_stop_actions() )
  725. return;
  726.  
  727. // TODO check if we can survive long enough, otherwise
  728. // instakill
  729. if ( foe.raw_hp > 100 ) {
  730. // eh, no chance. Just instakill it.
  731. instakill_macro(foe);
  732. }
  733. }
  734.  
  735. boolean stagger_immune (monster foe) {
  736. if ( foe == $monster[Eldritch Tentacle] )
  737. return true;
  738.  
  739. if ( mm["unstoppable"] )
  740. return true;
  741.  
  742. return false;
  743. }
  744.  
  745.  
  746. void megasniff() {
  747.  
  748. }
  749.  
  750. void resolve_aftercore_combat (monster foe, location where, int pickpocketable_items) {
  751. boolean do_weaksauce = false;
  752.  
  753.  
  754. switch ( where ) {
  755. case $location[Hobopolis Town Square]:
  756. do_weaksauce = true;
  757. pickpocket_macro(pickpocketable_items);
  758. break;
  759. case $location[The Dungeons of Doom]:
  760. switch (foe) {
  761. case $monster[Quantum Mechanic]:
  762. megasniff();
  763. break;
  764. case $monster[mind flayer]:
  765. break;
  766. default:
  767. do_any_banish(where, foe);
  768. }
  769. break;
  770. case $location[Cobb's Knob Menagerie\, Level 1]:
  771. // aftercore UR farming
  772. if ( mm["solid gold"] ) { // just kill solid gold monsters
  773. pickpocket_macro(pickpocketable_items);
  774. }
  775. else {
  776. switch (foe) {
  777. case $monster[Fruit Golem]:
  778. pickpocket_macro(pickpocketable_items);
  779. do_any_banish(where, foe);
  780. break;
  781. case $monster[BASIC Elemental]:
  782. add_goto_runaway_function(foe);
  783. pickpocket_macro(pickpocketable_items);
  784. push_turnless_macro("if match \"You deftly slip your fingers\"; call try_goto_runaway; endif;");
  785.  
  786. // Rave real
  787. if ( !mm["ticking"] && rave_steal_macro() ) {
  788. push_turnless_macro("if match \"Your savage beatdown seems to have knocked loose some treasure\"");
  789. push_turnless_macro("call try_goto_runaway");
  790. push_turnless_macro("endif");
  791. }
  792. break;
  793. default:
  794. push_turnless_macro("abort \"what\"");
  795. break;
  796. }
  797. }
  798. break;
  799. case $location[the red zeppelin]:
  800. if ( $item[glark cable].item_amount() > 0 && get_property("_glarkCableUses").to_int() < 5 )
  801. push_item_multiuse_if_possible($item[glark cable]);
  802. break;
  803. case $location[the hidden bowling alley]:
  804. if ( foe != $monster[drunk pygmy] && $item[short writ of habeas corpus].item_amount() > 0) {
  805. pickpocket_macro(pickpocketable_items);
  806. push_item_multiuse_if_possible($item[short writ of habeas corpus]);
  807. }
  808. default:
  809. if ( pickpocketable_items > 0 )
  810. pickpocket_macro(pickpocketable_items);
  811. break;
  812. }
  813.  
  814. boolean should_delevel = delevel_is_useful(foe);
  815. if ( !stagger_immune(foe) ) {
  816. if ( should_delevel )
  817. micrometeorite_macro();
  818. get_stun_macro();
  819. }
  820.  
  821.  
  822. if ( do_weaksauce && should_delevel && !mm["ticking"] )
  823. push_skill("curse of weaksauce");
  824.  
  825. boolean disco_bandit = my_class() == $class[disco bandit];
  826. if ( disco_bandit && !mm["ticking"] ) { // can deal with ticking if we keep up a stun.
  827. int rounds_spent = 0;
  828.  
  829. if ( mm["solid gold"] ) {
  830. // +50% meat from rave
  831. if ( will_survive_n_rounds(foe, 2 + rounds_spent) ) {
  832. rounds_spent += 2;
  833. rave_plus_meat_macro();
  834. }
  835. }
  836.  
  837. if ( pickpocketable_items > 0 ) {
  838. // +30% item from discosity
  839. if ( will_survive_n_rounds(foe, 1 + rounds_spent) ) {
  840. disco_dance_macro();
  841. rounds_spent += 1;
  842. }
  843.  
  844. // +30% item from rave
  845. if ( will_survive_n_rounds(foe, 2 + rounds_spent) ) {
  846. rave_plus_item_macro();
  847. rounds_spent += 2;
  848. }
  849. }
  850.  
  851. if ( !mm["solid gold"] && foe.min_meat > 80 ) {
  852. // eh, sure.
  853. if ( will_survive_n_rounds(foe, 2 + rounds_spent) ) {
  854. rave_plus_meat_macro();
  855. rounds_spent += 2;
  856. }
  857. }
  858. }
  859. }
  860.  
  861. int number_of_pickpocketable_items (monster foe) {
  862. int pickpocketable_items = 0;
  863.  
  864. foreach item_id, record_value in foe.item_drops_array() {
  865. if ( record_value.type == "c" ) { // conditional
  866. if ( item_type( record_value.drop ) != "shirt" )
  867. continue;
  868. }
  869. if ( record_value.rate == 0 ) // < 1% conditional
  870. continue;
  871.  
  872. pickpocketable_items += 1;
  873. }
  874.  
  875. return pickpocketable_items;
  876. }
  877.  
  878. void olfact_if_needed (monster foe) {
  879. if ( foe_should_be_olfacted(foe) )
  880. push_olfaction();
  881.  
  882. if ( foe_should_be_nosy_nose_olfacted(foe) )
  883. nosy_nose_olfact_macro();
  884.  
  885. if ( foe_should_be_gallagaposed(foe) )
  886. gallappagos_macro();
  887. }
  888.  
  889. void shattering_punch_to_preserve_buffs (monster foe) {
  890. if ( $effect[Steely-Eyed Squint].have_effect() == 0 )
  891. return;
  892.  
  893. if ( !can_use_skill($skill[Shattering Punch]) )
  894. return;
  895.  
  896. push_turnless_macro("if hasskill Shattering Punch");
  897. push_skill($skill[Shattering Punch]);
  898. push_turnless_macro("endif");
  899. }
  900.  
  901. void do_flyers_if_needed (monster foe) {
  902. if (
  903. $item[rock band flyers].item_amount() > 0
  904. &&
  905. get_property("flyeredML").to_int() < 10000
  906. &&
  907. will_survive_round(foe)
  908. ) {
  909. // TODO heal in case we pickpocketed
  910. if ( $item[beehive].item_amount() > 0 ) {
  911. push_blockable_action("use rock band flyers, beehive");
  912. }
  913. else {
  914. push_blockable_action("use rock band flyers");
  915. }
  916. }
  917. }
  918.  
  919. boolean location_with_desirable_monster(location where) {
  920. switch (where) {
  921. case $location[The Haunted Bedroom]:
  922. case $location[The Defiled Niche]:
  923. case $location[The Middle Chamber]:
  924. return true;
  925. default:
  926. return false;
  927. }
  928. }
  929.  
  930. void do_banish(location where, monster foe) {
  931. push_turnless_macro("abort \"Banish this sucker manually!\"");
  932. }
  933.  
  934. void banish_when_needed(monster foe, location where) {
  935. switch (where) {
  936. case $location[The Haunted Bedroom]:
  937. if (
  938. foe == $monster[animated ornate nightstand]
  939. ||
  940. foe == $monster[elegant animated nightstand]
  941. )
  942. return; # We want this one!
  943. do_banish(where, foe);
  944. // TODO
  945. default:
  946. return;
  947. }
  948. }
  949.  
  950. // TODO
  951. void macrometeorite_when_needed(monster foe, location where) {
  952. return;
  953. }
  954.  
  955. // TODO
  956. void free_runaway_when_possible(monster foe, location where) {
  957. return;
  958. }
  959.  
  960. void location_specific_actions(monster foe, location where) {
  961. banish_when_needed(foe, where);
  962. macrometeorite_when_needed(foe, where);
  963.  
  964. // Turn tomb rats into kings
  965. tomb_rat_into_rat_king(foe);
  966. // in-run
  967. if (
  968. where == $location[Barrrney's Barrr]
  969. &&
  970. foe.phylum == $phylum[pirate]
  971. ) {
  972. push_blockable_action("use big book of pirate insults");
  973. }
  974.  
  975. if ( contains_text(foe.manuel_name, "gremlin") ) {
  976. //string gremlin_stasis_macro = gremlin_stasis_macro(foe);
  977. //combat_macro = combat_macro + gremlin_stasis_macro;
  978. }
  979. }
  980.  
  981. void resolve_in_run_combat (monster foe, location where, int pickpocketable) {
  982. // TODO: pickpocket?
  983.  
  984. if ( can_use_skill($skill[Micrometeorite]) ) // Picky, Class Act, G-Lover, etc
  985. micrometeorite_macro();
  986.  
  987. olfact_if_needed(foe);
  988.  
  989. // Flyer, must happen before any instakilling or yellow raying
  990. do_flyers_if_needed(foe);
  991. shattering_punch_to_preserve_buffs(foe);
  992. if (yellow_ray_target(foe)) {
  993. yellow_ray(foe);
  994. }
  995.  
  996. location_specific_actions(foe, where);
  997. }
  998.  
  999. void after_fight_meddling(location where, monster foe) {
  1000. if ( in_aftercore() ) {
  1001. if (
  1002. where == $location[Hobopolis Town Square]
  1003. &&
  1004. my_familiar() == $familiar[slimeling]
  1005. ) {
  1006. int max_mp = my_maxmp();
  1007. int threshold = max_mp * 0.4;
  1008. if ( my_mp() < threshold ) {
  1009. float slimeling_fullness = get_property("slimelingFullness").to_float();
  1010. if ( slimeling_fullness < 5.0 ) {
  1011. cli_execute("slimeling 1 ring of aggravate");
  1012. }
  1013. }
  1014. }
  1015.  
  1016. if ( my_hp() < ( my_maxhp() * 0.6 ) ) {
  1017. cli_execute("cast cannelloni cocoon");
  1018. }
  1019. }
  1020. }
  1021.  
  1022. void main(int initround, monster foe, string pg) {
  1023. mm = foe.random_modifiers;
  1024.  
  1025. // Step up the base macro:
  1026. push_turnless_macro("scrollwhendone");
  1027. push_turnless_macro("abort hppercentbelow 25 || hpbelow 20 || pastround 28");
  1028.  
  1029. must_attempt_instakill_or_we_die(foe);
  1030.  
  1031. int pickpocketable_items = number_of_pickpocketable_items(foe);
  1032.  
  1033. location where = my_location();
  1034. if ( in_aftercore() ) {
  1035. resolve_aftercore_combat(foe, where, pickpocketable_items);
  1036. }
  1037. else { // in-run
  1038. resolve_in_run_combat(foe, where, pickpocketable_items);
  1039. }
  1040.  
  1041. default_fight_macro(foe);
  1042.  
  1043. // Show the macro, just in case...
  1044. string full_combat_macro = compose_combat_macro();
  1045. print_html(full_combat_macro);
  1046. run_combat(full_combat_macro);
  1047.  
  1048. after_fight_meddling(where, foe);
  1049.  
  1050.  
  1051. return;
  1052. }
Advertisement
Add Comment
Please, Sign In to add comment