Advertisement
Guest User

Untitled

a guest
Jun 21st, 2018
254
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 112.13 KB | None | 0 0
  1. =begin
  2. Documentation: https://elanthipedia.play.net/Lich_script_repository#combat-trainer
  3. =end
  4. custom_require.call(%w[common common-arcana common-healing common-items common-summoning common-travel drinfomon equipmanager events spellmonitor])
  5.  
  6. class SetupProcess
  7. include DRC
  8. include DRCS
  9. include DRCT
  10.  
  11. def initialize(settings, equipment_manager)
  12. @equipment_manager = equipment_manager
  13. echo('New SetupProcess') if $debug_mode_ct
  14.  
  15. @stance_override = settings.stance_override
  16. echo(" @stance_override: #{@stance_override}") if $debug_mode_ct
  17. @priority_defense = settings.priority_defense
  18. echo(" @priority_defense: #{@priority_defense}") if $debug_mode_ct
  19. @priority_weapons = settings.priority_weapons
  20. echo(" @priority_weapons: #{@priority_weapons}") if $debug_mode_ct
  21. @cycle_armors = settings.cycle_armors
  22. echo(" @cycle_armors: #{@cycle_armors}") if $debug_mode_ct
  23. @cycle_armors_time = settings.cycle_armors_time
  24. echo(" @cycle_armors_time: #{@cycle_armors_time}") if $debug_mode_ct
  25. @last_cycle_time = Time.now - @cycle_armors_time
  26.  
  27. @warhorn = settings.warhorn
  28. echo(" @warhorn: #{@warhorn}") if $debug_mode_ct
  29. @last_warhorn = Time.now - 305
  30.  
  31. return unless @warhorn
  32.  
  33. if DRCI.wearing?(@warhorn)
  34. @warhorn_get_verb = 'remove'
  35. @warhorn_store_verb = 'wear'
  36. else
  37. @warhorn_get_verb = 'get'
  38. @warhorn_store_verb = 'stow'
  39. end
  40. end
  41.  
  42. def execute(game_state)
  43. return true if game_state.done_cleaning_up?
  44. if game_state.stowing?
  45. echo('SetupProcess::clean_up') if $debug_mode_ct
  46. retreat
  47. if game_state.summoned_info(game_state.weapon_skill)
  48. if DRStats.moon_mage?
  49. bput('wear moon', 'telekinetic')
  50. else
  51. break_summoned_weapon(game_state.weapon_name)
  52. end
  53. else
  54. @equipment_manager.stow_weapon(game_state.weapon_name)
  55. game_state.sheath_whirlwind_offhand
  56. end
  57. game_state.next_clean_up_step
  58. return true
  59. end
  60.  
  61. was_retreating = game_state.retreating?
  62. game_state.update_room_npcs
  63. if game_state.dancing?
  64. blow_warhorn(game_state)
  65. game_state.dance
  66. elsif game_state.retreating?
  67. determine_next_to_train(game_state, game_state.retreat_weapons, false)
  68. else
  69. determine_next_to_train(game_state, game_state.weapon_training, was_retreating)
  70. end
  71.  
  72. if game_state.parrying
  73. check_stance(game_state)
  74. check_weapon(game_state)
  75. else
  76. check_weapon(game_state)
  77. check_stance(game_state)
  78. end
  79.  
  80. check_armor_swap(game_state)
  81. false
  82. end
  83.  
  84. private
  85.  
  86. def blow_warhorn(game_state)
  87. return unless @warhorn
  88. return if Time.now - @last_warhorn < 300
  89.  
  90. game_state.sheath_whirlwind_offhand
  91.  
  92. case bput("#{@warhorn_get_verb} my #{@warhorn}", 'You get', 'You remove', 'You take', 'What were you referring to', 'You need a free hand', 'Remove what')
  93. when 'You get', 'You remove', 'You take'
  94. bput('exhale warhorn lure', 'You sound a series of bursts from the warhorn', 'Your lungs are tired from having sounded a warhorn so recently.')
  95. @last_warhorn = Time.now
  96. waitrt?
  97. bput("#{@warhorn_store_verb} my #{@warhorn}", 'You put', 'You attach')
  98. when 'What were you referring to'
  99. echo "#{warhorn} NOT FOUND! Removing from hunt."
  100. @warhorn = nil
  101. end
  102.  
  103. game_state.wield_whirlwind_offhand
  104. end
  105.  
  106. def check_armor_swap(game_state)
  107. return if Time.now - @last_cycle_time < @cycle_armors_time
  108. return if game_state.loaded
  109. armor_types = @cycle_armors.map { |skill, _| skill }
  110. next_armor_type = armor_types.min_by { |skill| [DRSkill.getxp(skill), DRSkill.getrank(skill)] }
  111. return if next_armor_type == @last_worn_type
  112.  
  113. @last_cycle_time = Time.now
  114.  
  115. game_state.sheath_whirlwind_offhand
  116.  
  117. if @last_worn_type
  118. @equipment_manager.desc_to_items(@cycle_armors[@last_worn_type]).each { |item| @equipment_manager.remove_item(item) }
  119. else
  120. all_swap_pieces = @cycle_armors.map { |_, pieces| pieces }.flatten
  121. @equipment_manager.worn_items(all_swap_pieces).each { |item| @equipment_manager.remove_item(item) }
  122. end
  123.  
  124. @equipment_manager.wear_items(@equipment_manager.desc_to_items(@cycle_armors[next_armor_type]))
  125.  
  126. @last_worn_type = next_armor_type
  127.  
  128. game_state.wield_whirlwind_offhand
  129. end
  130.  
  131. def determine_next_to_train(game_state, weapon_training, ending_ranged)
  132. return unless game_state.skill_done? || !weapon_training[game_state.weapon_skill] || ending_ranged
  133.  
  134. echo('new skill needed for training') if $debug_mode_ct
  135.  
  136. game_state.reset_action_count
  137.  
  138. if DRStats.moon_mage? && moon_used_to_summon_weapon.nil?
  139. echo('skipping summoned weapons because no moonblade available') if $debug_mode_ct
  140. weapon_training = weapon_training.reject { |skill, _| game_state.summoned_info(skill) }
  141. end
  142. new_weapon_skill = weapon_training.min_by { |skill, _| [DRSkill.getxp(skill), @priority_weapons.include?(skill) ? -1 : 0, DRSkill.getrank(skill)] }.first
  143. game_state.update_weapon_info(new_weapon_skill)
  144.  
  145. game_state.update_target_weapon_skill
  146. end
  147.  
  148. def last_stance
  149. Flags['last-stance'][0] =~ /(\d+)%.* (\d+)%.* (\d+)%.* (\d+)/
  150. { 'EVASION' => Regexp.last_match(1).to_i, 'PARRY' => Regexp.last_match(2).to_i, 'SHIELD' => Regexp.last_match(3).to_i, 'SPARE' => Regexp.last_match(4).to_i }
  151. end
  152.  
  153. def build_stance_string(vals)
  154. "stance set #{vals['EVASION']} #{vals['PARRY']} #{vals['SHIELD']}"
  155. end
  156.  
  157. def check_stance(game_state, override = nil)
  158. return if @override_done && !game_state.reset_stance
  159. if @stance_override
  160. game_state.reset_stance = false
  161. pause
  162. waitrt?
  163. bput("stance set #{@stance_override}", 'Setting your')
  164. @override_done = true
  165. return
  166. end
  167. vals = { 'EVASION' => 0, 'PARRY' => 0, 'SHIELD' => 0, 'SPARE' => 0 }
  168. skill_map = { 'Parry Ability' => 'Parry', 'Shield Usage' => 'Shield' }
  169. previous = last_stance
  170. points = override || previous.values.inject(&:+)
  171.  
  172. priority = if game_state.current_weapon_stance
  173. game_state.current_weapon_stance[0..1].sort_by { |skill| [DRSkill.getxp(skill), skill] } + [game_state.current_weapon_stance.last]
  174. elsif @priority_defense
  175. rest = ['Evasion', 'Parry Ability', 'Shield Usage'] - [@priority_defense]
  176. rest.sort_by! { |skill| [DRSkill.getxp(skill), skill] }
  177. [@priority_defense] + rest
  178. else
  179. ['Evasion', 'Parry Ability', 'Shield Usage'].sort_by { |skill| [DRSkill.getxp(skill), skill] }
  180. end
  181.  
  182. game_state.parrying = priority.index('Parry Ability') < 2
  183.  
  184. priority.each do |skill|
  185. skill = skill_map[skill] if skill_map[skill]
  186. vals[skill.upcase] = points >= 100 ? 100 : points
  187. points -= vals[skill.upcase]
  188. end
  189.  
  190. return if vals == previous
  191. return unless /maximum number of points \((\d+)/ =~ bput(build_stance_string(vals), 'Setting your Evasion stance to', 'is above your maximum number of points \(\d+')
  192. check_stance(game_state, Regexp.last_match(1).to_i)
  193. end
  194.  
  195. def check_weapon(game_state)
  196. return if @last_seen_weapon_skill == game_state.weapon_skill
  197. @last_seen_weapon_skill = game_state.weapon_skill
  198.  
  199. echo("checking weapons as #{game_state.last_weapon_skill.inspect}!=#{game_state.weapon_skill}") if $debug_mode_ct
  200.  
  201. last_summoned = game_state.summoned_info(game_state.last_weapon_skill)
  202. next_summoned = game_state.summoned_info(game_state.weapon_skill)
  203.  
  204. # Clean up the previous weapon
  205. if !last_summoned
  206. @equipment_manager.stow_weapon(game_state.last_weapon_name)
  207. game_state.sheath_whirlwind_offhand
  208. elsif !next_summoned && !DRStats.moon_mage?
  209. break_summoned_weapon(game_state.last_weapon_name)
  210. elsif !next_summoned && DRStats.moon_mage?
  211. if right_hand =~ /moon/ || left_hand =~ /moon/
  212. bput('wear moon', 'telekinetic')
  213. end
  214. end
  215.  
  216. # Prepare the next weapon
  217. if next_summoned
  218. game_state.prepare_summoned_weapon(last_summoned)
  219. else
  220. bput('aim stop', "But you're not aiming", 'You stop concentrating', 'You are already') if game_state.aimed_skill?
  221. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  222. if game_state.whirlwind_trainable?
  223. game_state.currently_whirlwinding = true
  224. determine_whirlwind_weapon(game_state)
  225. echo("Combat-Trainer:: Whirlwinding with -=== MAIN: #{game_state.weapon_skill} OFF: #{game_state.whirlwind_offhand_skill} ===-") if $debug_mode_ct
  226. else
  227. game_state.currently_whirlwinding = false
  228. end
  229. end
  230.  
  231. # Invoke Focus
  232. return unless game_state.weapon_skill == 'Targeted Magic' && game_state.weapon_name
  233. bput("invoke #{game_state.weapon_name}", 'You')
  234. waitrt?
  235. end
  236.  
  237. def determine_whirlwind_weapon(game_state)
  238. temp_array = (game_state.whirlwind_trainables - [game_state.weapon_skill])
  239. offhand_skill = temp_array.min_by { |skill| [DRSkill.getxp(skill), DRSkill.getrank(skill)] }
  240. game_state.update_whirlwind_weapon_info(offhand_skill)
  241. game_state.wield_whirlwind_offhand
  242. end
  243. end
  244.  
  245. class LootProcess
  246. include DRC
  247. include DRCI
  248. include DRCS
  249. include DRCH
  250.  
  251. def initialize(settings, equipment_manager)
  252. @equipment_manager = equipment_manager
  253. echo('New LootProcess') if $debug_mode_ct
  254. skinning = settings.skinning
  255.  
  256. @skin = skinning['skin'] || false
  257. echo(" @skin: #{@skin}") if $debug_mode_ct
  258.  
  259. @arrange_all = skinning['arrange_all'] || false
  260. echo(" @arrange_all: #{@arrange_all}") if $debug_mode_ct
  261.  
  262. @arrange_count = skinning['arrange_count'] || 0
  263. echo(" @arrange_count: #{@arrange_count}") if $debug_mode_ct
  264.  
  265. @tie_bundle = skinning['tie_bundle'] || false
  266. echo(" @tie_bundle: #{@tie_bundle}") if $debug_mode_ct
  267.  
  268. @arrange_types = skinning['arrange_types'] || {}
  269. echo(" @arrange_types: #{@arrange_types}") if $debug_mode_ct
  270.  
  271. @lootables = settings.lootables
  272. echo(" @lootables: #{@lootables}") if $debug_mode_ct
  273.  
  274. thanatology = settings.thanatology
  275. @ritual_type = thanatology['ritual_type'].downcase
  276. echo(" @ritual_type: #{@ritual_type}") if $debug_mode_ct
  277.  
  278. @cycle_rituals = @ritual_type == 'cycle'
  279. echo(" @cycle_rituals: #{@cycle_rituals}") if $debug_mode_ct
  280.  
  281. @dissect_and_butcher = settings.dissect_and_butcher
  282. echo(" @dissect_and_butcher: #{@dissect_and_butcher}") if $debug_mode_ct
  283.  
  284. @rituals = get_data('spells').rituals
  285. echo(" @rituals: #{@rituals}") if $debug_mode_ct
  286.  
  287. @last_ritual = nil
  288. echo(" @last_ritual: #{@last_ritual}") if $debug_mode_ct
  289.  
  290. @necro_heal = thanatology['heal'] || false
  291. echo(" @necro_heal: #{@necro_heal}") if $debug_mode_ct
  292.  
  293. @necro_store = thanatology['store'] || false
  294. echo(" @necro_store: #{@necro_store}") if $debug_mode_ct
  295.  
  296. @necro_container = thanatology['harvest_container']
  297. echo(" @necro_container: #{@necro_container}") if $debug_mode_ct
  298.  
  299. @current_harvest_count = rummage('C material', @necro_container).size if DRStats.necromancer?
  300. echo(" @current_harvest_count: #{@current_harvest_count}") if $debug_mode_ct
  301.  
  302. @necro_count = thanatology['harvest_count']
  303. echo(" @necro_count: #{@necro_count}") if $debug_mode_ct
  304.  
  305. @make_zombie = settings.zombie['make']
  306. echo(" @make_zombie: #{@make_zombie}") if $debug_mode_ct
  307.  
  308. @wound_level_threshold = settings.necromancer_healing['wound_level_threshold'] || 1
  309. echo(" @wound_level_threshold: #{@wound_level_threshold}") if $debug_mode_ct
  310.  
  311. @gem_nouns = get_data('items').gem_nouns
  312. echo(" @gem_nouns: #{@gem_nouns}") if $debug_mode_ct
  313.  
  314. @tie_pouch = settings.tie_gem_pouches
  315. echo(" @tie_pouch: #{@tie_pouch}") if $debug_mode_ct
  316.  
  317. @spare_gem_pouch_container = settings.spare_gem_pouch_container
  318. echo(" @spare_gem_pouch_container: #{@spare_gem_pouch_container}") if $debug_mode_ct
  319.  
  320. @full_pouch_container = settings.full_pouch_container
  321. echo(" @full_pouch_container: #{@full_pouch_container}") if $debug_mode_ct
  322.  
  323. @gem_pouch_adjective = settings.gem_pouch_adjective
  324. echo(" @gem_pouch_adjective: #{@gem_pouch_adjective}") if $debug_mode_ct
  325.  
  326. @loot_delay = 5 # in seconds
  327. @loot_timer = Time.now - @loot_delay
  328. echo(" @loot_timer: #{@loot_timer}") if $debug_mode_ct
  329.  
  330. @loot_bodies = settings.loot_bodies
  331. echo(" @loot_bodies: #{@loot_bodies}") if $debug_mode_ct
  332.  
  333. @loot_specials = settings.loot_specials
  334. echo(" @loot_specials: #{@loot_specials}") if $debug_mode_ct
  335.  
  336. @custom_loot_type = settings.custom_loot_type
  337. echo(" @custom_loot_type: #{@custom_loot_type}") if $debug_mode_ct
  338.  
  339. @dump_junk = settings.dump_junk
  340. echo(" @dump_junk: #{@dump_junk}") if $debug_mode_ct
  341. @dump_timer = Time.now - 300
  342. @dump_item_count = settings.dump_item_count
  343.  
  344. @last_rites = settings.last_rites
  345. echo(" @last_rites: #{@last_rites}") if $debug_mode_ct
  346. @last_rites_timer = Time.now - 600
  347.  
  348. if settings.box_loot_limit
  349. @box_nouns = get_data('items').box_nouns
  350. @box_loot_limit = settings.box_loot_limit
  351. @current_box_count = count_boxes(settings)
  352. echo(" @current_box_count: #{@current_box_count}")
  353. echo(" @box_loot_limit: #{@box_loot_limit}")
  354. end
  355.  
  356. Flags.add('using-corpse', 'begins arranging', 'completes arranging', 'kneels down briefly and draws a knife', 'cruelly into the body and carving out a chunk', 'makes additional cuts, purposeful but seemingly at random')
  357. Flags.add('pouch-full', 'You think the .* pouch is too full to fit another gem into', 'You\'d better tie it up before putting')
  358. Flags.add('container-full', 'There isn\'t any more room')
  359. end
  360.  
  361. def execute(game_state)
  362. if (Time.now - @dump_timer > 300) && @dump_junk && DRRoom.room_objs.count >= @dump_item_count
  363. fput 'DUMP JUNK'
  364. @dump_timer = Time.now
  365. end
  366. game_state.mob_died = false
  367. dispose_body(game_state)
  368. stow_lootables(game_state)
  369. if (game_state.mob_died || game_state.npcs.empty?) && game_state.finish_killing?
  370. 15.times do
  371. break unless Flags['using-corpse']
  372. break if DRRoom.dead_npcs.empty?
  373. pause
  374. end
  375. stow_lootables(game_state)
  376. echo('LootProcess::clean_up') if $debug_mode_ct
  377. game_state.next_clean_up_step
  378. end
  379. return true if game_state.finish_spell_casting? || game_state.stowing?
  380. false
  381. end
  382.  
  383. def stow_loot(item, game_state)
  384. Flags.reset('pouch-full')
  385. Flags.reset('container-full')
  386.  
  387. special = @loot_specials.find { |x| x['name'] == item }
  388. if special
  389. if bput("get #{item}", 'You pick up', 'There isn\'t any more room', 'You get', 'You need a free hand', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory') == 'already in your inventory'
  390. bput("get other #{item}", 'You pick up', 'You get', 'You need a free hand', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory')
  391. end
  392. pause 0.25
  393. bput("put #{item} in my #{special['bag']}", 'you put')
  394. return
  395. end
  396.  
  397. case bput("stow #{item}", 'You pick up', 'You get', 'You need a free hand', 'There isn\'t any more room', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory', 'The .* is not designed to carry anything')
  398. when 'already in your inventory'
  399. if @gem_nouns.include?(item)
  400. bput('stow gem', 'You pick up', 'You get', 'You need a free hand', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory')
  401. else
  402. bput("stow other #{item}", 'You pick up', 'You get', 'You need a free hand', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory')
  403. end
  404. when 'You pick up', 'You get'
  405. @current_box_count += 1 if @box_loot_limit && @box_nouns.include?(item)
  406. end
  407. pause 0.25
  408. if Flags['container-full']
  409. bput("drop #{item}", 'You drop')
  410. game_state.unlootable(item)
  411. end
  412.  
  413. return unless Flags['pouch-full']
  414. bput("drop my #{item}", 'You drop', 'What were')
  415. unless @spare_gem_pouch_container
  416. game_state.unlootable(item)
  417. return
  418. end
  419. bput("remove my #{@gem_pouch_adjective} pouch", 'You remove')
  420. if @full_pouch_container
  421. bput("put my #{@gem_pouch_adjective} pouch in my #{@full_pouch_container}", 'You put')
  422. else
  423. bput("stow my #{@gem_pouch_adjective} pouch", 'You put')
  424. end
  425. bput("get #{@gem_pouch_adjective} pouch from my #{@spare_gem_pouch_container}", 'You get a')
  426. bput('wear my pouch', 'You attach')
  427. bput('stow gem', 'You pick up', 'You get', 'You need a free hand', 'You just can\'t', 'push you over the item limit', 'You stop as you realize the .* is not yours', 'Stow what', 'already in your inventory')
  428. if @tie_pouch
  429. bput('tie my pouch', 'You tie')
  430. else
  431. fput('close my pouch')
  432. end
  433. end
  434.  
  435. def stow_lootables(game_state)
  436. return unless @loot_bodies
  437.  
  438. pair = [left_hand, right_hand]
  439. tried_loot = false
  440. items_to_loot = []
  441. @lootables
  442. .select { |item| game_state.lootable?(item) }
  443. .reject { |item| @box_nouns.include?(item) && @box_loot_limit && at_box_limit? }
  444. .each do |item|
  445. item_reg = item.split.join('.*')
  446. matches = DRRoom.room_objs.grep(/\b#{item_reg}$/)
  447. tried_loot ||= !matches.empty?
  448. matches.each { |_| items_to_loot.push(item); }
  449. end
  450. if items_to_loot.any?
  451. game_state.sheath_whirlwind_offhand
  452. items_to_loot.each { |item| stow_loot(item, game_state) }
  453. game_state.wield_whirlwind_offhand
  454. end
  455. return unless tried_loot
  456. pause 1
  457. if left_hand != pair.first && !@equipment_manager.is_listed_item?(left_hand)
  458. echo("out of room, failed to store #{left_hand}")
  459. game_state.unlootable(GameObj.left_hand.noun.downcase)
  460. dispose_trash(left_hand)
  461. end
  462. if right_hand != pair.last && !@equipment_manager.is_listed_item?(right_hand)
  463. echo("out of room, failed to store #{right_hand}")
  464. game_state.unlootable(GameObj.right_hand.noun.downcase)
  465. dispose_trash(right_hand)
  466. end
  467. end
  468.  
  469. def at_box_limit?
  470. return false unless @box_loot_limit
  471. @current_box_count >= @box_loot_limit
  472. end
  473.  
  474. def should_perform_ritual?(game_state)
  475. return false unless DRStats.necromancer?
  476. return false unless @ritual_type
  477. return false if game_state.necro_casting?
  478. return true if @ritual_type == 'cycle'
  479. return true if @ritual_type == 'butcher'
  480. return true if @ritual_type == 'dissect' && DRSkill.getxp('First Aid') < 32
  481. return true if @ritual_type == 'harvest' && DRSkill.getxp('Skinning') < 32
  482. return true if DRSkill.getxp('Thanatology') < 32
  483. false
  484. end
  485.  
  486. def determine_next_ritual
  487. return unless @cycle_rituals
  488.  
  489. next_ritual = if DRSkill.getxp('Skinning') > 31 && DRSkill.getxp('First Aid') > 31 && DRSkill.getxp('Thanatology') > 31
  490. if @dissect_and_butcher
  491. 'butcher'
  492. else
  493. 'dissect'
  494. end
  495. elsif DRSkill.getxp('Skinning') < DRSkill.getxp('First Aid')
  496. 'harvest'
  497. elsif @dissect_and_butcher
  498. 'butcher'
  499. else
  500. 'dissect'
  501. end
  502. next_ritual
  503. end
  504.  
  505. def check_rituals?(game_state)
  506. return true unless DRStats.necromancer?
  507. mob_noun = DRRoom.dead_npcs.first
  508. return true if game_state.construct?(mob_noun)
  509.  
  510. echo " should_perform_ritual? #{should_perform_ritual?(game_state)}" if $debug_mode_ct
  511. if @last_ritual.nil?
  512. if @necro_heal && !game_state.necro_casting?
  513. game_state.wounds = check_health['wounds']
  514. echo "Severity to Wounds: #{game_state.wounds}" if $debug_mode_ct
  515. echo "wound_level_threshold: #{@wound_level_threshold}" if $debug_mode_ct
  516. unless game_state.wounds.empty?
  517. if @wound_level_threshold <= game_state.wounds.keys.max
  518. do_necro_ritual(mob_noun, 'consume', game_state)
  519. return false
  520. end
  521. end
  522. end
  523. if @make_zombie && !game_state.necro_casting? && !game_state.cfb_active?
  524. echo 'Making zombie' if $debug_mode_ct
  525. do_necro_ritual(mob_noun, 'arise', game_state)
  526. return false
  527. end
  528. ritual = if @cycle_rituals
  529. determine_next_ritual
  530. elsif @ritual_type.eql?('dissect') && @dissect_and_butcher
  531. 'butcher'
  532. else
  533. @ritual_type
  534. end
  535. do_necro_ritual(mob_noun, ritual, game_state) if should_perform_ritual?(game_state)
  536. end
  537. return false if %w[consume harvest dissect].include?(@last_ritual)
  538. true
  539. end
  540.  
  541. def do_necro_ritual(mob_noun, ritual, game_state)
  542. return unless DRStats.necromancer?
  543. return unless ritual
  544. return if game_state.construct?(mob_noun)
  545.  
  546. echo "Attempting necromancer ritual #{ritual} on #{mob_noun}" if $debug_mode_ct
  547.  
  548. if ritual.eql?('butcher')
  549. butcher_corpse(mob_noun, ritual, game_state)
  550.  
  551. @last_ritual = ritual
  552. echo "Last ritual performed: #{@last_ritual}" if $debug_mode_ct
  553. return
  554. end
  555.  
  556. do_necro_ritual(mob_noun, 'preserve', game_state) if %w[consume harvest arise].include?(ritual)
  557. perform_message = "perform #{ritual} on #{mob_noun}"
  558. result = bput(perform_message, @rituals['arise'], @rituals['preserve'], @rituals['dissect'], @rituals['harvest'], @rituals['consume'], @rituals['construct'], @rituals['failures'])
  559. echo result if $debug_mode_ct
  560. case result
  561. when @rituals['arise']
  562. echo 'Detected arise messaging' if $debug_mode_ct
  563. game_state.prepare_cfb = true if @make_zombie
  564. @last_ritual = ritual
  565. when @rituals['preserve'], @rituals['dissect']
  566. echo 'Detected preserve or dissect messaging' if $debug_mode_ct
  567. @last_ritual = ritual
  568. when @rituals['consume']
  569. echo 'Detected consume messaging' if $debug_mode_ct
  570. @last_ritual = ritual
  571. game_state.prepare_consume = true if @necro_heal
  572. when @rituals['harvest']
  573. echo 'Detected harvest messaging' if $debug_mode_ct
  574. @last_ritual = ritual
  575. waitrt?
  576. necro_harvest_check
  577. when @rituals['construct']
  578. echo 'Detected an attempt to do ritual on a construct' if $debug_mode_ct
  579. game_state.construct(mob_noun)
  580. when *@rituals['failures']
  581. echo 'Failure detected' if $debug_mode_ct
  582. end
  583. echo "Last ritual performed: #{@last_ritual}" if $debug_mode_ct
  584. end
  585.  
  586. def butcher_corpse(mob_noun, ritual, game_state)
  587. return unless ritual.eql?('butcher')
  588. echo "Butchering the #{mob_noun}'s corpse!" if $debug_mode_ct
  589. echo ' Only butchering it once!' if $debug_mode_ct && @dissect_and_butcher && !@ritual_type.eql?('butcher')
  590.  
  591. do_necro_ritual(mob_noun, 'preserve', game_state)
  592. @equipment_manager.stow_weapon(game_state.weapon_name)
  593.  
  594. loop do
  595. result = bput("perform #{ritual} on #{mob_noun}", @rituals['butcher'], @rituals['failures'])
  596. break if result.empty? || @rituals['failures'].any? { |msg| result.include?(msg) }
  597. bput("drop my #{right_hand}", 'You drop', 'You discard', 'Please rephrase')
  598. break if @dissect_and_butcher && !@ritual_type.eql?('butcher')
  599. end
  600.  
  601. do_necro_ritual(mob_noun, 'dissect', game_state) if @dissect_and_butcher && !@ritual_type.eql?('butcher')
  602. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  603. end
  604.  
  605. def necro_harvest_check
  606. unless @necro_store
  607. echo 'Store material: false, dropping harvested material' if $debug_mode_ct
  608. bput('drop material', 'you discard it')
  609. return
  610. end
  611.  
  612. quality = fput('glance left')
  613. if quality['great'] || quality['excellent'] || quality['perfect'] || quality['flawless']
  614. echo 'Harvested high quality material.' if $debug_mode_ct
  615. else
  616. bput('drop material', 'you discard it')
  617. echo 'Dropped low quality material.' if $debug_mode_ct
  618. return
  619. end
  620.  
  621. echo 'Store material: true, checking count of stored material' if $debug_mode_ct
  622. if @current_harvest_count >= @necro_count
  623. bput('drop material', 'you discard it')
  624. echo 'Already full on stored material, dropping harvested material.' if $debug_mode_ct
  625. return
  626. end
  627.  
  628. result = bput("put material in my #{@necro_container}", 'You put')
  629. @current_harvest_count += 1 if result =~ /^You put/
  630. end
  631.  
  632. def dispose_body(game_state)
  633. return unless @loot_bodies
  634. if DRRoom.dead_npcs.empty?
  635. Flags.reset('using-corpse')
  636. @last_ritual = nil
  637. return
  638. end
  639. return if Time.now - @loot_timer < @loot_delay
  640.  
  641. game_state.mob_died = true
  642. waitrt?
  643. return if Flags['using-corpse']
  644. if (Time.now - @last_rites_timer > 600) && @last_rites && game_state.blessed_room
  645. bput("pray #{DRRoom.dead_npcs.first}", 'You beseech your god for mercy', 'You pray fervently', 'You continue praying for guidance', 'Quietly touching your lips with the tips of your fingers', 'murmur a brief prayer for')
  646. waitrt?
  647. fput "recite Meraud, power the holy fires that unleash my righteous vengeance;Chadatru, guide my sword to swing in justice;Everild, give me the power to conquer my enemies;Truffenyi, let me not lose sight of compassion and mercy;Else, I will become like those I despise;Urrem'tier, receive into your fetid grasp these wicked souls;May the Tamsine's realms never know their evil ways again;May all the Immortals guide your faithful soldier #{checkname}."
  648. waitrt?
  649. @last_rites_timer = Time.now
  650. return
  651. end
  652.  
  653. game_state.sheath_whirlwind_offhand
  654.  
  655. arrange_mob(DRRoom.dead_npcs.first, game_state)
  656. check_skinning(DRRoom.dead_npcs.first, game_state) if check_rituals?(game_state)
  657.  
  658. game_state.wield_whirlwind_offhand
  659.  
  660. unless game_state.necro_casting?
  661. while bput("loot #{@custom_loot_type}".strip, 'You search', 'I could not find what you were referring to', 'and get ready to search it') == 'and get ready to search it'
  662. pause
  663. waitrt?
  664. end
  665. @last_ritual = nil
  666. end
  667. @loot_timer = Time.now
  668. end
  669.  
  670. def arrange_mob(mob_noun, game_state)
  671. return unless @skin
  672. return unless @arrange_count > 0
  673. return unless game_state.skinnable?(mob_noun)
  674. return if game_state.necro_casting?
  675.  
  676. arranges = 0
  677. type = @arrange_types[mob_noun] || 'skin'
  678. arrange_message = @arrange_all ? "arrange all for #{type}" : "arrange for #{type}"
  679. while arranges < @arrange_count
  680. arranges += 1
  681. case bput(arrange_message, 'You begin to arrange', 'You continue arranging', 'You make a mistake', 'You complete arranging', 'That creature cannot', 'That has already been arranged', 'Arrange what', 'cannot be skinned', 'You make a serious mistake in the arranging process', 'The .* is currently being arranged to produce')
  682. when 'You complete arranging', 'That has already been arranged', 'You make a serious mistake in the arranging process', 'Arrange what'
  683. break
  684. when 'cannot be skinned'
  685. game_state.unskinnable(mob_noun)
  686. break
  687. when 'That creature cannot'
  688. arranges = 0
  689. arrange_message = @arrange_all ? 'arrange all' : 'arrange'
  690. end
  691. waitrt?
  692. end
  693. end
  694.  
  695. def check_skinning(mob_noun, game_state)
  696. return unless @skin
  697. return unless game_state.skinnable?(mob_noun)
  698.  
  699. pause 0.25
  700. waitrt?
  701. if game_state.need_bundle
  702. case bput('tap my bundle', 'You tap a \w+ bundle that you are wearing', 'I could not find what you were referring to')
  703. when /lumpy/
  704. if @tie_bundle
  705. bput('tie my bundle', 'TIE the bundle again')
  706. bput('tie my bundle', 'you tie the bundle')
  707. bput('adjust my bundle', 'You adjust')
  708. end
  709. game_state.need_bundle = false
  710. when /tight/
  711. game_state.need_bundle = false
  712. end
  713. end
  714.  
  715. snap = [left_hand, right_hand]
  716. case bput('skin', 'roundtime', 'skin what', 'cannot be skinned', 'carrying far too many items', 'need a more appropriate weapon')
  717. when 'carrying far too many items'
  718. waitrt?
  719. fput 'get skin from my bundle'
  720. fput 'drop skin'
  721. fput 'skin'
  722. when 'need a more appropriate weapon'
  723. echo('BUY A SKINNING KNIFE')
  724. @skin = false
  725. return
  726. when 'cannot be skinned'
  727. game_state.unskinnable(mob_noun)
  728. return
  729. end
  730. pause 1
  731. waitrt?
  732. if game_state.need_bundle && snap != [left_hand, right_hand]
  733. stored_moon = false
  734. if DRStats.moon_mage? && bput('wear moon', 'suspend', 'already telekinetic', 'wear what') == 'suspend'
  735. stored_moon = true
  736. elsif summoned = game_state.summoned_info(game_state.weapon_skill)
  737. break_summoned_weapon(game_state.weapon_name)
  738. else
  739. @equipment_manager.stow_weapon(game_state.weapon_name)
  740. end
  741. if bput('get bundling rope', 'You get', 'What were you referring to', 'You need a free hand') == 'You get'
  742. fput('bundle')
  743. fput('wear my bundle')
  744. if @tie_bundle
  745. bput('tie my bundle', 'TIE the bundle again')
  746. bput('tie my bundle', 'you tie the bundle')
  747. bput('adjust my bundle', 'You adjust')
  748. end
  749. else
  750. dispose_trash(left_hand) if snap.first != left_hand && !@equipment_manager.is_listed_item?(left_hand)
  751. dispose_trash(right_hand) if snap.last != right_hand && !@equipment_manager.is_listed_item?(right_hand)
  752. end
  753. game_state.need_bundle = false
  754. unless stored_moon && bput('get moon', 'you grab', 'What were') == 'you grab'
  755. if summoned
  756. game_state.prepare_summoned_weapon(false)
  757. else
  758. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  759. end
  760. end
  761. end
  762. dispose_trash(left_hand) if snap.first != left_hand && !@equipment_manager.is_listed_item?(left_hand)
  763. dispose_trash(right_hand) if snap.last != right_hand && !@equipment_manager.is_listed_item?(right_hand)
  764. end
  765. end
  766.  
  767. class SafetyProcess
  768. include DRC
  769. include DRCH
  770. include DRCT
  771.  
  772. def initialize(settings)
  773. echo('New SafetyProcess') if $debug_mode_ct
  774. Flags.add('ct-engaged', 'closes to pole weapon range on you', 'closes to melee range on you')
  775. Flags.add('ct-lodged', 'from the .* lodged in your (.*)\.')
  776.  
  777. @health_threshold = settings.health_threshold
  778. echo(" @health_threshold: #{@health_threshold}") if $debug_mode_ct
  779. end
  780.  
  781. def execute(game_state)
  782. custom_require.call('tendme') if bleeding? && !Script.running?('tendme')
  783. fput 'exit' if health < @health_threshold
  784. fix_standing
  785. tend_lodged
  786. game_state.danger = in_danger?(game_state.danger)
  787. keep_away if !game_state.danger && game_state.retreating?
  788. end
  789.  
  790. private
  791.  
  792. def tend_lodged
  793. return unless Flags['ct-lodged']
  794. bind_wound(Flags['ct-lodged'].last)
  795. Flags.reset('ct-lodged')
  796. end
  797.  
  798. def keep_away
  799. return unless Flags['ct-engaged']
  800. Flags.reset('ct-engaged')
  801. retreat
  802. end
  803.  
  804. def in_danger?(danger)
  805. return false if health >= 75
  806.  
  807. unless danger
  808. Flags.reset('ct-engaged')
  809. retreat
  810. end
  811.  
  812. keep_away
  813. true
  814. end
  815. end
  816.  
  817. class SpellProcess
  818. include DRC
  819. include DRCA
  820. include DRCS
  821. include DRCH
  822. include DRCT
  823.  
  824. $weapon_buffs = ['Ignite', 'Rutilor\'s Edge', 'Resonance']
  825.  
  826. def initialize(settings, equipment_manager)
  827. @equipment_manager = equipment_manager
  828. echo('New SpellProcess') if $debug_mode_ct
  829.  
  830. @settings = settings
  831.  
  832. @buff_spells = settings.buff_spells
  833. echo(" @buff_spells: #{@buff_spells}") if $debug_mode_ct
  834.  
  835. @offensive_spells = settings.offensive_spells
  836. echo(" @offensive_spells: #{@offensive_spells}") if $debug_mode_ct
  837.  
  838. @training_spells = settings.combat_spell_training
  839. echo(" @training_spells: #{@training_spells}") if $debug_mode_ct
  840.  
  841. @training_spells_max_threshold = settings.combat_spell_training_max_threshold
  842. echo(" @training_spells_max_threshold: #{@training_spells_max_threshold}") if $debug_mode_ct
  843.  
  844. @offensive_spell_cycle = settings.offensive_spell_cycle
  845. echo(" @offensive_spell_cycle: #{@offensive_spell_cycle}") if $debug_mode_ct
  846.  
  847. @necromancer_healing = settings.necromancer_healing
  848. echo(" @necromancer_healing: #{@necromancer_healing}") if $debug_mode_ct
  849.  
  850. @necromancer_zombie = settings.waggle_sets['zombie']
  851. echo(" @necromancer_zombie: #{@necromancer_zombie}") if $debug_mode_ct
  852.  
  853. @empath_spells = settings.empath_healing
  854. echo(" @empath_spells: #{@empath_spells}") if $debug_mode_ct
  855.  
  856. @osrel_timer = Time.now - 1000
  857. echo(" @osrel_timer: #{@osrel_timer}") if $debug_mode_ct
  858.  
  859. @osrel_amount = settings.osrel_amount
  860. echo(" @osrel_amount: #{@osrel_amount}") if $debug_mode_ct
  861.  
  862. @osrel_no_harness = settings.osrel_no_harness
  863. echo(" @osrel_no_harness: #{@osrel_no_harness}") if $debug_mode_ct
  864.  
  865. @cast_only_to_train = settings.cast_only_to_train
  866. echo(" @cast_only_to_train: #{@cast_only_to_train}") if $debug_mode_ct
  867.  
  868. @offensive_spell_mana_threshold = settings.offensive_spell_mana_threshold
  869. echo(" @offensive_spell_mana_threshold: #{@offensive_spell_mana_threshold}") if $debug_mode_ct
  870.  
  871. @training_spell_mana_threshold = settings.training_spell_mana_threshold
  872. echo(" @training_spell_mana_threshold: #{@training_spell_mana_threshold}") if $debug_mode_ct
  873.  
  874. @buff_spell_mana_threshold = settings.buff_spell_mana_threshold
  875. echo(" @buff_spell_mana_threshold: #{@buff_spell_mana_threshold}") if $debug_mode_ct
  876.  
  877. @cambrinth = settings.cambrinth
  878. echo(" @cambrinth: #{@cambrinth}") if $debug_mode_ct
  879.  
  880. @cambrinth_cap = settings.cambrinth_cap
  881. echo(" @cambrinth_cap: #{@cambrinth_cap}") if $debug_mode_ct
  882.  
  883. @dedicated_camb_use = settings.dedicated_camb_use
  884. echo(" @dedicated_camb_use: #{@dedicated_camb_use}") if $debug_mode_ct
  885.  
  886. @stored_cambrinth = settings.stored_cambrinth
  887. echo(" @stored_cambrinth: #{@stored_cambrinth}") if $debug_mode_ct
  888.  
  889. @cambrinth_invoke_exact_amount = settings.cambrinth_invoke_exact_amount
  890. echo(" @cambrinth_invoke_exact_amount: #{@cambrinth_invoke_exact_amount}") if $debug_mode_ct
  891.  
  892. @harness_for_attunement = settings.use_harness_when_arcana_locked
  893. echo(" @harness_for_attunement: #{@harness_for_attunement}") if $debug_mode_ct
  894.  
  895. @siphon_vit_threshold = settings.necro_siphon_vit_threshold
  896. echo(" @siphon_vit_threshold: #{@siphon_vit_threshold}") if $debug_mode_ct
  897.  
  898. @ignored_npcs = settings.ignored_npcs
  899. echo(" @ignored_npcs: #{@ignored_npcs}") if $debug_mode_ct
  900.  
  901. @hide_type = settings.hide_type
  902. echo(" @hide_type: #{@hide_type}") if $debug_mode_ct
  903.  
  904. @buff_force_cambrinth = settings.combat_trainer_buffs_force_cambrinth
  905. echo(" @buff_force_cambrinth: #{@buff_force_cambrinth}") if $debug_mode_ct
  906.  
  907. @perc_health_timer = Time.now
  908.  
  909. @symbiosis_learning_threshold = settings.symbiosis_learning_threshold
  910. echo(" @symbiosis_learning_threshold: #{@symbiosis_learning_threshold}") if $debug_mode_ct
  911.  
  912. Flags.add('ct-spelllost', 'Your pattern dissipates with the loss of your target')
  913. Flags.add('ct-need-bless', ' passes through the .* with no effect')
  914.  
  915. @offensive_spells
  916. .select { |spell| spell['expire'] }
  917. .each { |spell| add_spell_flag(spell['abbrev'], spell['expire']) }
  918. @buff_spells
  919. .values
  920. .select { |data| data['expire'] }
  921. .each { |data| add_spell_flag(data['abbrev'], data['expire']) }
  922.  
  923. @training_cast_timer = Time.now + 45
  924. @training_cyclic_timer = Time.now + 45
  925.  
  926. @spell_timers = {}
  927. @wounds = {}
  928.  
  929. @tk_ammo = settings.tk_ammo
  930. @tk_spell = @offensive_spells.find { |spell| spell['abbrev'] =~ /tkt|tks/i }
  931. drop_tkt_ammo
  932. Flags.add('need-tkt-ammo', 'There is nothing here that can be thrown')
  933. end
  934.  
  935. def drop_tkt_ammo
  936. return unless @tk_ammo
  937. fput("get my #{@tk_ammo}")
  938. fput("drop #{@tk_ammo}")
  939. end
  940.  
  941. def add_spell_flag(name, expire)
  942. Flags.add("ct-#{name}", expire)
  943. Flags["ct-#{name}"] = true
  944. end
  945.  
  946. def execute(game_state)
  947. return true if game_state.stowing?
  948. return false if game_state.dismiss_pet?
  949.  
  950. check_timer(game_state)
  951. if Flags['ct-spelllost']
  952. game_state.casting = false
  953. Flags.reset('ct-spelllost')
  954. end
  955. check_osrel(game_state)
  956. if game_state.mob_died
  957. @offensive_spells
  958. .select { |spell| spell['expire'] }
  959. .reject { |spell| spell['cyclic'] }
  960. .reject { |spell| spell['heavy'] }
  961. .each { |spell| Flags["ct-#{spell['abbrev']}"] = true }
  962. end
  963. if Flags['need-tkt-ammo']
  964. Flags.reset('need-tkt-ammo')
  965. drop_tkt_ammo
  966. end
  967. check_slivers(game_state)
  968. check_consume(game_state)
  969. check_cfb(game_state)
  970. check_bless(game_state)
  971. check_ignite(game_state)
  972. check_rutilors_edge(game_state)
  973. check_health(game_state)
  974. check_buffs(game_state)
  975. check_training(game_state)
  976. check_offensive(game_state)
  977. check_current(game_state)
  978. if game_state.finish_spell_casting? && !game_state.casting
  979. echo('SpellProcess::clean_up') if $debug_mode_ct
  980. game_state.next_clean_up_step
  981. release_cyclics
  982. if checkprep != 'None'
  983. bput('release spell', 'You let your concentration lapse', "You aren't preparing a spell")
  984. bput('release mana', 'You release all', "You aren't harnessing any mana")
  985. end
  986. if @tk_ammo
  987. waitrt?
  988. pause
  989. fput("stow #{@tk_ammo}")
  990. end
  991. return true
  992. end
  993. false
  994. end
  995.  
  996. private
  997.  
  998. def check_slivers(game_state)
  999. return if game_state.casting
  1000. return if @tk_ammo
  1001. return unless @tk_spell
  1002. return if DRSpells.slivers
  1003. return if UserVars.moons['visible'].empty?
  1004.  
  1005. fput('prep moonblade')
  1006. if DRSkill.getrank('Lunar Magic') < 300
  1007. pause 3
  1008. elsif DRSkill.getrank('Lunar Magic') < 400
  1009. pause 2
  1010. else
  1011. pause
  1012. end
  1013. fput("cast #{UserVars.moons['visible'].first}")
  1014. fput('break moonblade')
  1015. end
  1016.  
  1017. def check_osrel(game_state)
  1018. return if game_state.casting
  1019. return unless @osrel_amount && DRSpells.active_spells['Osrel Meraud']
  1020. return unless Time.now - @osrel_timer > 300
  1021. @osrel_timer = Time.now
  1022. infuse_om(!@osrel_no_harness, @osrel_amount)
  1023. end
  1024.  
  1025. def check_timer(game_state)
  1026. return if game_state.cast_timer.nil? || (Time.now - game_state.cast_timer) <= 70
  1027.  
  1028. game_state.cast_timer = nil
  1029. if game_state.casting
  1030. bput('release spell', 'You let your concentration lapse', "You aren't preparing a spell")
  1031. bput('release mana', 'You release all', "You aren't harnessing any mana")
  1032. end
  1033. game_state.casting = false
  1034. end
  1035.  
  1036. def check_bless(game_state)
  1037. return if game_state.casting
  1038. return unless @buff_spells['Bless']
  1039. return unless Flags['ct-need-bless']
  1040. Flags.reset('ct-need-bless')
  1041.  
  1042. prepare?('Bless', 1)
  1043. cast?("cast #{right_hand || left_hand}")
  1044. end
  1045.  
  1046. def check_ignite(game_state)
  1047. # Ignite must be released before it can be recast
  1048. # Rutilor's Edge and Resonance do not have this problem
  1049. return if @last_seen_weapon_buff_name == game_state.weapon_name
  1050. return unless DRSpells.active_spells['Ignite']
  1051.  
  1052. # Release the spell on the character
  1053. bput('release ignite', 'The warm feeling in your hand goes away', 'Release what')
  1054. # Wait for the spell on the weapon to be released (it can take a second or two to pulse)
  1055. pause 1
  1056. end
  1057.  
  1058. def check_rutilors_edge(game_state)
  1059. # Rutilor's Edge does not need to be released before it can be recast
  1060. # But releasing allows the buff logic to detect it should be recast
  1061. return if @last_seen_weapon_buff_name == game_state.weapon_name
  1062. return unless DRSpells.active_spells['Rutilor\'s Edge']
  1063.  
  1064. # Release the spell on the character
  1065. bput('release rue', 'You sense the Rutilor\'s Edge spell fade away', 'Release what')
  1066. # Wait for the spell on the weapon to be released (it can take a second or two to pulse)
  1067. pause 1
  1068. end
  1069.  
  1070. def ready_to_cast?(game_state)
  1071. Flags['ct-spellcast'] || (@prep_time && Time.now - game_state.cast_timer >= @prep_time)
  1072. end
  1073.  
  1074. def check_current(game_state)
  1075. return unless game_state.casting
  1076.  
  1077. if @should_invoke
  1078. return if game_state.check_charging? && game_state.check_charging?
  1079. end
  1080.  
  1081. return unless ready_to_cast?(game_state)
  1082.  
  1083. game_state.check_harness if @should_harness
  1084. cast_spell(game_state)
  1085. end
  1086.  
  1087. def check_invoke(game_state)
  1088. return unless @should_invoke
  1089. find_cambrinth(@cambrinth, @stored_cambrinth, @cambrinth_cap)
  1090. @should_invoke = nil
  1091. invoke_amount = @cambrinth_invoke_exact_amount ? game_state.charges_total : nil
  1092. game_state.charges_total = nil
  1093. invoke(@cambrinth, @dedicated_camb_use, invoke_amount)
  1094. stow_cambrinth(@cambrinth, @stored_cambrinth, @cambrinth_cap)
  1095. end
  1096.  
  1097. def cast_spell(game_state)
  1098. check_invoke(game_state)
  1099. if game_state.casting_weapon_buff
  1100. @custom_cast = "cast my #{game_state.weapon_name}"
  1101. @last_seen_weapon_buff_name = game_state.weapon_name
  1102. end
  1103.  
  1104. if game_state.casting_consume
  1105. if @necromancer_healing.key?('Consume Flesh') && !@necromancer_healing.key?('Devour')
  1106. @custom_cast = "cast #{game_state.wounds[game_state.wounds.keys.max].first}"
  1107. end
  1108. end
  1109.  
  1110. hide?(@hide_type) if XMLData.prepared_spell == 'Vivisection' && game_state.use_stealth_attack?
  1111.  
  1112. if game_state.casting_sorcery
  1113. @equipment_manager.stow_weapon(game_state.weapon_name)
  1114. end
  1115.  
  1116. snapshot = DRSkill.getxp(@skill)
  1117. success = cast?(@custom_cast, @symbiosis, @before, @after)
  1118. if @symbiosis && @use_auto_mana
  1119. if !success
  1120. UserVars.discerns[@abbrev]['more'] = [UserVars.discerns[@abbrev]['more'] - 1, 0].max
  1121. elsif DRSkill.getxp(@skill) - snapshot < @symbiosis_learning_threshold
  1122. UserVars.discerns[@abbrev]['more'] = UserVars.discerns[@abbrev]['more'] + 1
  1123. end
  1124. end
  1125. @custom_cast = nil
  1126. @symbiosis = nil
  1127. @before = nil
  1128. @after = nil
  1129. @skill = nil
  1130. @abbrev = nil
  1131. @use_auto_mana = nil
  1132.  
  1133. game_state.casting = false
  1134. game_state.cast_timer = nil
  1135.  
  1136. game_state.casting_weapon_buff = false
  1137. game_state.casting_consume = false
  1138. game_state.casting_cfb = false
  1139. if game_state.casting_sorcery
  1140. game_state.casting_sorcery = false
  1141. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1142. end
  1143.  
  1144. if game_state.casting_moonblade
  1145. if left_hand =~ /moon/ || game_state.brawling? || game_state.offhand?
  1146. # The moonblade was summoned or refreshed while training something else
  1147. bput('wear moon', 'telekinetic')
  1148. end
  1149.  
  1150. game_state.casting_moonblade = false
  1151. end
  1152.  
  1153. Flags.reset("ct-#{@reset_expire}") if @reset_expire
  1154.  
  1155. return unless @command
  1156. pause 0.5 until DRRoom.npcs.include?('warrior')
  1157. fput("command #{@command}")
  1158. @command = nil
  1159. end
  1160.  
  1161. def check_spell_timer?(data)
  1162. Time.now - (@spell_timers[data['pet_type']] || @spell_timers[data['abbrev']] || Time.at(0)) >= data['recast_every']
  1163. end
  1164.  
  1165. def check_buff_conditions?(name, game_state)
  1166. return false if $weapon_buffs.include?(name) && (game_state.aimed_skill? || game_state.brawling?)
  1167. # Resonance does not show up in Active Spells, so we need to track the last weapon on which it was cast to avoid recasting it continuously
  1168. # Ignite and Rutilor's Edge do not have this problem
  1169. return false if name == 'Resonance' && @last_seen_weapon_buff_name == game_state.weapon_name
  1170.  
  1171. true
  1172. end
  1173.  
  1174. def check_training(game_state)
  1175. return if game_state.casting
  1176. return unless @training_spells
  1177. return if @training_spells_max_threshold && game_state.npcs.length > @training_spells_max_threshold
  1178. return if mana < @training_spell_mana_threshold
  1179.  
  1180. needs_training = %w[Warding Utility Augmentation Sorcery]
  1181. .select { |skill| @training_spells[skill] }
  1182. .select { |skill| DRSkill.getxp(skill) < 31 }
  1183. .select { |skill| Time.now > (@training_spells[skill]['cyclic'] ? @training_cyclic_timer : @training_cast_timer) }
  1184. .select { |skill| @training_spells[skill]['night'] ? UserVars.sun['night'] : true }
  1185. .select { |skill| @training_spells[skill]['day'] ? UserVars.sun['day'] : true }
  1186. .sort_by { |skill| DRSkill.getxp(skill) }.first
  1187. return unless needs_training
  1188.  
  1189. data = @training_spells[needs_training]
  1190. @training_cast_timer = Time.now + 45
  1191. if data['cyclic']
  1192. @training_cyclic_timer = Time.now + 325
  1193. elsif @training_cyclic_timer < @training_cast_timer
  1194. @training_cyclic_timer = @training_cast_timer
  1195. end
  1196.  
  1197. if needs_training == 'Sorcery'
  1198. echo 'Preparing a sorcery spell, held items will be stowed to prevent item loss' if $debug_mode_ct
  1199. game_state.casting_sorcery = true
  1200. end
  1201. prepare_spell(data, game_state)
  1202. end
  1203.  
  1204. def check_buffs(game_state)
  1205. return if game_state.casting
  1206. return if mana < @buff_spell_mana_threshold
  1207.  
  1208. recastable_buffs = @buff_spells
  1209. .select { |_name, data| data['recast'] || data['recast_every'] || data['expire'] }
  1210. .select { |_name, data| data['expire'] ? Flags["ct-#{data['abbrev']}"] : true }
  1211. .select { |name, _data| check_buff_conditions?(name, game_state) }
  1212.  
  1213. name, data = recastable_buffs.find do |name, data|
  1214. if data['pet_type']
  1215. check_spell_timer?(data) && DRRoom.npcs.include?(data['pet_type'])
  1216. elsif data['recast_every']
  1217. check_spell_timer?(data)
  1218. elsif data['expire']
  1219. true
  1220. else
  1221. !DRSpells.active_spells[name] || DRSpells.active_spells[name].to_i <= data['recast']
  1222. end
  1223. end
  1224. echo("found buff missing: #{name}") if $debug_mode_ct && name
  1225. game_state.casting_weapon_buff = $weapon_buffs.include?(name)
  1226. if data['ritual']
  1227. cast_ritual(data, game_state)
  1228. else
  1229. prepare_spell(data, game_state, @buff_force_cambrinth)
  1230. end
  1231. end
  1232.  
  1233. def check_health(game_state)
  1234. return if game_state.casting
  1235. return unless DRStats.empath?
  1236. return if health > 95 && @wounds.empty?
  1237.  
  1238. if DRSpells.active_spells['Regeneration']
  1239. if @empath_spells['VH'] && health <= 95
  1240. data = { 'abbrev' => 'vh', 'mana' => @empath_spells['VH'].first, 'cambrinth' => @empath_spells['VH'][1..-1] }
  1241. prepare_spell(data, game_state)
  1242. end
  1243. return
  1244. end
  1245.  
  1246. if Time.now - @perc_health_timer > 30 && @empath_spells['FOC'] || @empath_spells['HEAL']
  1247. @perc_health_timer = Time.now
  1248. @wounds = check_perc_health
  1249. end
  1250.  
  1251. echo('Healing') if $debug_mode_ct
  1252. if @wounds.any?
  1253. if @empath_spells['FOC']
  1254. data = { 'abbrev' => 'foc', 'mana' => @empath_spells['FOC'].first, 'cambrinth' => @empath_spells['FOC'][1..-1] }
  1255. elsif @empath_spells['HEAL']
  1256. data = { 'abbrev' => 'heal', 'mana' => @empath_spells['HEAL'].first, 'cambrinth' => @empath_spells['HEAL'][1..-1] }
  1257. end
  1258. @wounds = {}
  1259. prepare_spell(data, game_state, true) if data
  1260. elsif @empath_spells['VH']
  1261. data = { 'abbrev' => 'vh', 'mana' => @empath_spells['VH'].first, 'cambrinth' => @empath_spells['VH'][1..-1] }
  1262. prepare_spell(data, game_state, true)
  1263. end
  1264. end
  1265.  
  1266. def check_cfb(game_state)
  1267. return unless DRStats.necromancer?
  1268. return unless @necromancer_zombie['Call from Beyond']
  1269. return if game_state.casting
  1270. return unless game_state.prepare_cfb
  1271.  
  1272. game_state.casting_cfb = true
  1273. game_state.prepare_cfb = false
  1274. data = @necromancer_zombie['Call from Beyond']
  1275. prepare_spell(data, game_state, true)
  1276. end
  1277.  
  1278. def check_consume(game_state)
  1279. return unless DRStats.necromancer?
  1280. return unless @necromancer_healing
  1281. return if game_state.casting
  1282.  
  1283. if health <= @siphon_vit_threshold && @necromancer_healing['Siphon Vitality'] && !game_state.npcs.empty?
  1284. @necromancer_healing['Siphon Vitality']['prep'] = 'target'
  1285. prepare_spell(@necromancer_healing['Siphon Vitality'], game_state, true)
  1286. return
  1287. end
  1288.  
  1289. return unless game_state.prepare_consume
  1290. echo "@necromancer_healing.key?('Consume Flesh'): #{@necromancer_healing.key?('Consume Flesh')}" if $debug_mode_ct
  1291. echo "@necromancer_healing.key?('Devour'): #{@necromancer_healing.key?('Devour')}" if $debug_mode_ct
  1292. data = @necromancer_healing['Devour'] || @necromancer_healing['Consume Flesh']
  1293. game_state.casting_consume = true
  1294. game_state.prepare_consume = false
  1295. prepare_spell(data, game_state, true)
  1296. end
  1297.  
  1298. def check_offensive(game_state)
  1299. return if game_state.casting
  1300. return if game_state.npcs.empty?
  1301. return if mana < @offensive_spell_mana_threshold
  1302. ready_spells = @offensive_spells
  1303. .select { |spell| spell['target_enemy'] ? game_state.npcs.include?(spell['target_enemy']) : true }
  1304. .select { |spell| spell['min_threshold'] ? game_state.npcs.length >= spell['min_threshold'] : true }
  1305. .select { |spell| spell['max_threshold'] ? game_state.npcs.length <= spell['max_threshold'] : true }
  1306. .select { |spell| spell['expire'] ? Flags["ct-#{spell['abbrev']}"] : true }
  1307. .select { |spell| game_state.dancing? ? spell['harmless'] : true }
  1308. .select { |spell| spell['recast_every'] ? check_spell_timer?(spell) : true }
  1309. .select { |spell| @cast_only_to_train ? DRSkill.getxp(spell['skill']) <= 32 : true }
  1310. .select { |spell| spell['cast_only_to_train'] ? DRSkill.getxp(spell['skill']) <= 32 : true }
  1311. .select { |spell| spell['cyclic'] ? !DRSpells.active_spells[spell['name']] : true }
  1312. .select { |spell| spell['night'] ? UserVars.sun['night'] : true }
  1313. .select { |spell| spell['day'] ? UserVars.sun['day'] : true }
  1314. .select { |spell| spell['slivers'] ? DRSpells.slivers : true }
  1315. data = if @offensive_spell_cycle.empty?
  1316. ready_spells.min_by { |spell| DRSkill.getxp(spell['skill']) }
  1317. else
  1318. name = @offensive_spell_cycle.find { |spell_name| ready_spells.find { |spell| spell['name'] == spell_name } }
  1319. @offensive_spell_cycle.rotate!
  1320. ready_spells.find { |spell| spell['name'] == name }
  1321. end
  1322. prepare_spell(data, game_state)
  1323. Flags.reset('ct-spelllost')
  1324. end
  1325.  
  1326. def cast_ritual(data, game_state)
  1327. if summoned = game_state.summoned_info(game_state.weapon_skill)
  1328. break_summoned_weapon(game_state.weapon_name)
  1329. else
  1330. @equipment_manager.stow_weapon(game_state.weapon_name)
  1331. end
  1332.  
  1333. data = update_astral_data(data)
  1334. if data # update_astral_data returns nil on failure
  1335. check_invoke(game_state)
  1336. ritual(data, @ignored_npcs)
  1337. end
  1338.  
  1339. if summoned
  1340. game_state.prepare_summoned_weapon(false)
  1341. else
  1342. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1343. end
  1344. game_state.reset_stance = true
  1345. end
  1346.  
  1347. def prepare_spell(data, game_state, force_cambrinth = false)
  1348. return unless data
  1349. data = check_discern(data, @settings) if data['use_auto_mana']
  1350. game_state.cast_timer = Time.now
  1351. @prep_time = data['prep_time']
  1352. echo("prepare spell: #{data}") if $debug_mode_ct
  1353. if data['target_enemy']
  1354. echo(" Target found: #{data['target_enemy']}") if $debug_mode_ct
  1355. fput("face #{data['target_enemy']}")
  1356. end
  1357. release_cyclics if data['cyclic']
  1358. command = 'prep'
  1359. command = data['prep'] if data['prep']
  1360. command = data['prep_type'] if data['prep_type']
  1361.  
  1362. if data['recast_every']
  1363. if data['pet_type']
  1364. @spell_timers[data['pet_type']] = Time.now
  1365. else
  1366. @spell_timers[data['abbrev']] = Time.now
  1367. end
  1368. end
  1369.  
  1370. if data['moon']
  1371. check_moonwatch
  1372. moon = UserVars.moons['visible'].first
  1373. unless moon
  1374. echo "No moon available to cast #{data['abbrev']}" if $debug_mode_ct
  1375.  
  1376. @weather ||= bput('weather', 'inside', 'You glance up at the sky.')
  1377. if @weather =~ /inside/
  1378. echo "*** You're inside and there are no available moons. You're going to have a hard time casting #{data['abbrev']}"
  1379. end
  1380.  
  1381. unless moon = UserVars.moons['visible'].first
  1382. echo "Couldn't find any moons to cast #{data['abbrev']} with" if $debug_mode_ct
  1383. return
  1384. end
  1385. end
  1386. if data['abbrev'] == 'moonblade'
  1387. game_state.casting_moonblade = true
  1388. last_moon = moon_used_to_summon_weapon
  1389. data['before'] = [{ 'message' => 'get moon', 'matches' => ['already holding that', 'You grab', 'referring to'] }]
  1390. if UserVars.moons['visible'].include?(last_moon) && UserVars.moons[last_moon]['timer'] >= 4
  1391. moon = last_moon
  1392. data['cast'] = "cast #{moon} refresh"
  1393. else
  1394. data['before'] << { 'message' => 'drop moon', 'matches' => ['open your hand', 'referring to'] }
  1395. data['cast'] = "cast #{moon}"
  1396. end
  1397. else
  1398. data['cast'] = "cast #{moon}"
  1399. end
  1400. end
  1401. prepare?(data['abbrev'], data['mana'], data['symbiosis'], command)
  1402. game_state.casting = true
  1403. game_state.cambrinth_charges(data['cambrinth'])
  1404. if data['cambrinth']
  1405. @should_harness = check_to_harness(@harness_for_attunement) && !force_cambrinth
  1406. @should_invoke = data['cambrinth'] unless @should_harness
  1407. end
  1408. @custom_cast = data['cast']
  1409. @symbiosis = data['symbiosis']
  1410. @after = data['after']
  1411. @skill = data['skill']
  1412. @prep = data['prep']
  1413. @command = data['command']
  1414. @reset_expire = data['expire'] ? data['abbrev'] : nil
  1415. Flags.reset('ct-spellcast')
  1416. @before = data['before']
  1417. @abbrev = data['abbrev']
  1418. @use_auto_mana = data['use_auto_mana']
  1419. game_state.action_taken if (@skill == 'Targeted Magic' || @prep == 'target') && game_state.weapon_skill == 'Targeted Magic'
  1420. end
  1421. end
  1422.  
  1423. class PetProcess
  1424. include DRC
  1425.  
  1426. def initialize(settings)
  1427. echo('New Pet Process') if $debug_mode_ct
  1428.  
  1429. @zombie = settings.zombie
  1430. echo(" @zombie: #{@zombie}") if $debug_mode_ct
  1431.  
  1432. @is_present = false
  1433. @current_stance = nil
  1434. @current_behavior = nil
  1435. end
  1436.  
  1437. def execute(game_state)
  1438. check_zombie(game_state)
  1439. if game_state.dismiss_pet?
  1440. dismiss_zombie(game_state)
  1441. game_state.next_clean_up_step
  1442. return true
  1443. end
  1444. false
  1445. end
  1446.  
  1447. def summon_zombie(game_state)
  1448. return unless game_state.cfb_active?
  1449. return unless @zombie['summon']
  1450. return if @is_present
  1451.  
  1452. command_zombie('come', game_state)
  1453. end
  1454.  
  1455. def dismiss_zombie(game_state)
  1456. return unless @is_present
  1457. return unless game_state.cfb_active?
  1458.  
  1459. command_zombie('leave', game_state)
  1460. end
  1461.  
  1462. def update_behavior(game_state)
  1463. return unless game_state.cfb_active?
  1464. return unless @zombie['behavior']
  1465. return if @zombie['behavior'].eql?(@current_behavior)
  1466.  
  1467. command_zombie("behavior #{@zombie['behavior']}", game_state)
  1468. end
  1469.  
  1470. def update_stance(game_state)
  1471. return unless game_state.cfb_active?
  1472. return unless @zombie['stance']
  1473. return if @zombie['stance'].eql?(@current_stance)
  1474.  
  1475. command_zombie("stance #{@zombie['stance']}", game_state)
  1476. end
  1477.  
  1478. def check_zombie(game_state)
  1479. return unless DRStats.necromancer?
  1480. return unless game_state.cfb_active?
  1481.  
  1482. summon_zombie(game_state)
  1483. update_behavior(game_state)
  1484. update_stance(game_state)
  1485. end
  1486.  
  1487. def command_zombie(command, game_state)
  1488. return unless game_state.cfb_active?
  1489.  
  1490. case bput("command zombie #{command}", 'willing it to come back to you', 'You have already shifted', 'That is not a valid stance', 'is already right beside you', 'zombie shambles off with a groan', 'You sense a flicker of acknowledgement through the link', 'you sense your .+ shift into (a|an) \w+ stance', 'you sense your .+ behavior shift')
  1491. when 'is already right beside you'
  1492. echo(' Zombie is present') if $debug_mode_ct
  1493. @is_present = true
  1494. when 'zombie shambles off with a groan'
  1495. echo(' Zombie is no longer present') if $debug_mode_ct
  1496. @is_present = false
  1497. when /shift into a \w+ stance/
  1498. echo(" Zombie stance set to #{@zombie['stance']}") if $debug_mode_ct
  1499. @current_stance = @zombie['stance']
  1500. when /you sense your .+ behavior shift/
  1501. echo(" Zombie behavior set to #{@zombie['behavior']}") if $debug_mode_ct
  1502. @current_behavior = @zombie['behavior']
  1503. end
  1504. end
  1505. end
  1506.  
  1507. class AbilityProcess
  1508. include DRC
  1509. include DRCA
  1510. include DRCT
  1511.  
  1512. def initialize(settings)
  1513. echo('New AbilityProcess') if $debug_mode_ct
  1514.  
  1515. @buffs = settings.buff_nonspells
  1516. echo(" @buffs: #{@buffs}") if $debug_mode_ct
  1517.  
  1518. @khri = @buffs.delete('khri') || []
  1519. echo(" @khri: #{@khri}") if $debug_mode_ct
  1520.  
  1521. @kneel_khri = settings.kneel_khri
  1522. echo(" @kneel_khri: #{@kneel_khri}") if $debug_mode_ct
  1523.  
  1524. @barb_buffs = @buffs.delete('barb_buffs') || []
  1525. echo(" @barb_buffs: #{@barb_buffs}") if $debug_mode_ct
  1526.  
  1527. setup_barb_buff_flags
  1528.  
  1529. @paladin_use_badge = settings.paladin_use_badge
  1530. echo(" @paladin_use_badge: #{@paladin_use_badge}") if $debug_mode_ct
  1531.  
  1532. @use_mana_glyph = settings.paladin_use_mana_glyph
  1533. echo(" @paladin_glyphs: #{@paladin_glyphs}") if $debug_mode_ct
  1534.  
  1535. if @use_mana_glyph
  1536. Flags.add('glyph-mana-expired', 'You sense the holy power return to normal')
  1537. Flags['glyph-mana-expired'] = true
  1538. echo 'Added glyph of mana expiration flag.' if $debug_mode_ct
  1539. end
  1540.  
  1541. return unless @paladin_use_badge
  1542.  
  1543. if DRCI.wearing?('pilgrim badge')
  1544. @paladin_badge_get_verb = 'remove'
  1545. @paladin_badge_store_verb = 'wear'
  1546. else
  1547. @paladin_badge_get_verb = 'get'
  1548. @paladin_badge_store_verb = 'stow'
  1549. end
  1550.  
  1551. UserVars.paladin_last_badge_use ||= Time.now
  1552. @badge_reuse_cooldown = 1860 # 31 minutes
  1553. end
  1554.  
  1555. def execute(game_state)
  1556. check_paladin_skills
  1557. check_nonspell_buffs(game_state)
  1558. false
  1559. end
  1560.  
  1561. private
  1562.  
  1563. def check_paladin_skills
  1564. return unless DRStats.paladin?
  1565.  
  1566. pray_badge
  1567. check_mana_glyph
  1568. end
  1569.  
  1570. def pray_badge
  1571. return unless @paladin_use_badge
  1572. return unless Time.now - UserVars.paladin_last_badge_use > @badge_reuse_cooldown
  1573.  
  1574. case bput("#{@paladin_badge_get_verb} my pilgrim badge", 'You take off', 'You get', 'You remove', 'What were you referring to', 'You need a free hand', 'Remove what')
  1575. when 'You get', 'You remove', 'You take off'
  1576. retreat
  1577. bput('pray my pilgrim badge', 'You think upon the immortals')
  1578. UserVars.paladin_last_badge_use = Time.now
  1579. waitrt?
  1580. bput("#{@paladin_badge_store_verb} my pilgrim badge", 'You put', 'You attach')
  1581. when 'What were you referring to'
  1582. echo '***PILGRIM BADGE NOT FOUND! REMOVING FROM HUNT.***'
  1583. @paladin_use_badge = false
  1584. return
  1585. end
  1586. end
  1587.  
  1588. def check_mana_glyph
  1589. return unless @use_mana_glyph
  1590. return unless Flags['glyph-mana-expired']
  1591.  
  1592. bput('glyph mana', 'You trace a glyph', 'You begin to trace')
  1593. Flags.reset('glyph-mana-expired')
  1594. echo 'Used Glyph of Mana!' if $debug_mode_ct
  1595. end
  1596.  
  1597. def setup_barb_buff_flags
  1598. @barb_buffs.each do |name|
  1599. ability_data = get_data('spells').barb_abilities[name]
  1600. Flags.add("ap-#{name}-expired", ability_data['expired_message'])
  1601. Flags["ap-#{name}-expired"] = true unless DRSpells.active_spells[name]
  1602. echo "setup_barb_buff_flags:: adding #{Flags["ap-#{name}-expired"]} flag with an expiration message of: #{ability_data['expired_message']}" if $debug_mode_ct
  1603. end
  1604. end
  1605.  
  1606. def check_nonspell_buffs(game_state)
  1607. @buffs.each do |action, cooldown|
  1608. timer = game_state.cooldown_timers[action]
  1609. next unless !timer || (Time.now - timer).to_i > cooldown
  1610. game_state.cooldown_timers[action] = Time.now
  1611. fput action
  1612. waitrt?
  1613. end
  1614. return if game_state.danger && @kneel_khri
  1615. @khri
  1616. .map { |name| "Khri #{name}" }
  1617. .each do |name|
  1618. timer = game_state.cooldown_timers[name]
  1619. next unless !timer || (Time.now - timer).to_i > 30
  1620. game_state.cooldown_timers[name] = Time.now if activate_khri?(@kneel_khri, name)
  1621. end
  1622. @barb_buffs
  1623. .select { |name| Flags["ap-#{name}-expired"] }
  1624. .each do |name|
  1625. Flags.reset("ap-#{name}-expired")
  1626. activate_barb_buff(name)
  1627. echo "Activated barb_buff #{name}!" if $debug_mode_ct
  1628. waitrt?
  1629. pause 6 if get_data('spells').barb_abilities[name]['type'].eql? 'meditation'
  1630. end
  1631. end
  1632. end
  1633.  
  1634. class ManipulateProcess
  1635. include DRC
  1636. include DRCT
  1637.  
  1638. def initialize(settings)
  1639. echo('New ManipulateProcess') if $debug_mode_ct
  1640.  
  1641. @threshold = settings.manipulate_threshold
  1642. echo(" @threshold: #{@threshold}") if $debug_mode_ct
  1643.  
  1644. @manip_to_train = settings.manipulate_only_to_train
  1645. echo(" @manip_to_train: #{@manip_to_train}") if $debug_mode_ct
  1646.  
  1647. @last_manip = Time.now - 200
  1648. end
  1649.  
  1650. def execute(game_state)
  1651. return if game_state.danger || @threshold.nil? || game_state.construct_mode?
  1652. @filtered_npcs = game_state.npcs
  1653. manipulate(game_state) if should_manipulate?
  1654. end
  1655.  
  1656. private
  1657.  
  1658. def should_manipulate?
  1659. return false if @manip_to_train && DRSkill.getxp('Empathy') > 30
  1660.  
  1661. @filtered_npcs.length >= @threshold && Time.now - @last_manip > 120
  1662. end
  1663.  
  1664. def manipulate(game_state)
  1665. bput('manip stop all', 'You relax your will', 'But you aren')
  1666.  
  1667. manipulate_count = 0
  1668. npc_occurrences = Hash.new(0)
  1669.  
  1670. @filtered_npcs.each do |npc|
  1671. next if game_state.construct?(npc)
  1672. break if manipulate_count >= @threshold
  1673.  
  1674. index = npc_occurrences[npc]
  1675. ordinal_string = $ORDINALS[index]
  1676.  
  1677. case bput("manipulate friendship #{ordinal_string} #{npc}", 'You\'re already manipulating', 'beyond your ken', 'You attempt to empathically manipulate', 'You strain', 'does not seem to have a life essence')
  1678. when 'does not seem to have a life essence' then
  1679. game_state.construct(npc)
  1680. else
  1681. manipulate_count += 1
  1682. npc_occurrences[npc] += 1
  1683. end
  1684. end
  1685.  
  1686. @last_manip = Time.now
  1687. end
  1688. end
  1689.  
  1690. class TrainerProcess
  1691. include DRC
  1692. include DRCT
  1693.  
  1694. def initialize(settings, equipment_manager)
  1695. @equipment_manager = equipment_manager
  1696. echo('New TrainerProcess') if $debug_mode_ct
  1697. @training_abilities = settings.training_abilities
  1698. echo(" @training_abilities: #{@training_abilities}") if $debug_mode_ct
  1699.  
  1700. @skill_map = { 'Hunt' => 'Perception', 'Pray' => 'Theurgy', 'PercMana' => 'Attunement',
  1701. 'Perc' => 'Attunement', 'Astro' => 'Astrology', 'App' => 'Appraisal', 'PrayerMat' => 'Theurgy',
  1702. 'App Quick' => 'Appraisal', 'App Careful' => 'Appraisal', 'Tactics' => 'Tactics', 'Analyze' => 'Tactics',
  1703. 'Scream' => 'Bardic Lore', 'Perc Health' => 'Empathy', 'Khri Prowess' => 'Debilitation',
  1704. 'Stealth' => 'Stealth', 'Ambush Stun' => settings.stun_skill, 'Ambush Choke' => 'Debilitation',
  1705. 'Favor Orb' => 'Anything', 'Charged Maneuver' => 'Expertise', 'Meraud' => 'Theurgy', 'Recall' => 'Scholarship',
  1706. 'Barb Research Warding' => 'Warding', 'Barb Research Augmentation' => 'Augmentation',
  1707. 'Barb Research Debilitation' => 'Debilitation', 'Collect' => 'Outdoorsmanship', 'Smite' => 'Conviction' }
  1708.  
  1709. @skill_map['Hunt'] = %w[Perception Scouting] if DRStats.ranger?
  1710. @favor_god = settings.favor_god
  1711. if settings.favor_goal && @favor_god && /delicate/ =~ bput("tap #{@favor_god} orb", 'The orb is delicate', 'I could not find')
  1712. @training_abilities['Favor Orb'] = settings.favor_orb_rub_frequency
  1713. end
  1714.  
  1715. @no_app = []
  1716.  
  1717. @dont_stalk = settings.dont_stalk
  1718. echo(" @dont_stalk: #{@dont_stalk}") if $debug_mode_ct
  1719.  
  1720. @hide_type = settings.hide_type
  1721. echo(" @hide_type: #{@hide_type}") if $debug_mode_ct
  1722.  
  1723. @force_unhide = settings.force_unhide
  1724. echo(" @force_unhide: #{@force_unhide}") if $debug_mode_ct
  1725.  
  1726. @stun_weapon = settings.stun_weapon
  1727. echo(" @stun_weapon: #{@stun_weapon}") if $debug_mode_ct
  1728.  
  1729. @stun_weapon_skill = settings.stun_weapon_skill
  1730. echo(" @stun_weapon_skill: #{@stun_weapon_skill}") if $debug_mode_ct
  1731.  
  1732. @theurgy_supply_container = settings.theurgy_supply_container
  1733. echo(" @theurgy_supply_container: #{@theurgy_supply_container}") if $debug_mode_ct
  1734.  
  1735. @water_holder = settings.water_holder
  1736. echo(" @water_holder: #{@water_holder}") if $debug_mode_ct
  1737.  
  1738. @flint_lighter = settings.flint_lighter
  1739. echo(" @flint_lighter: #{@flint_lighter}") if $debug_mode_ct
  1740.  
  1741. @prayer_mat = settings.prayer_mat
  1742. echo(" @prayer_mat: #{@prayer_mat}") if $debug_mode_ct
  1743.  
  1744. @dirt_stacker = settings.dirt_stacker
  1745. echo(" @dirt_stacker: #{@dirt_stacker}") if $debug_mode_ct
  1746.  
  1747. @kneel_khri = settings.kneel_khri
  1748. echo(" @kneel_khri: #{@kneel_khri}") if $debug_mode_ct
  1749.  
  1750. @forage_item = settings.forage_item
  1751. echo(" @forage_item: #{@forage_item}") if $debug_mode_ct
  1752.  
  1753. @analyze_retry_count = settings.combat_analyze_retry_count
  1754. echo(" @analyze_retry_count: #{@analyze_retry_count}") if $debug_mode_ct
  1755.  
  1756. @combat_training_abilities_target = settings.combat_training_abilities_target
  1757. echo(" @combat_training_abilities_target: #{@combat_training_abilities_target}") if $debug_mode_ct
  1758. end
  1759.  
  1760. def execute(game_state)
  1761. return if game_state.danger
  1762.  
  1763. case select_ability(game_state)
  1764. when 'PercMana'
  1765. moon_mage_perc(game_state)
  1766. when 'Perc'
  1767. bput('perc', 'You reach out') unless game_state.retreating?
  1768. when 'Perc Health'
  1769. bput('perc heal', 'You close your eyes')
  1770. when 'Astro'
  1771. astrology(game_state)
  1772. when 'App'
  1773. appraise(game_state, '')
  1774. when 'App Quick'
  1775. appraise(game_state, 'quick')
  1776. when 'App Careful'
  1777. appraise(game_state, 'careful')
  1778. when 'Tactics'
  1779. bput(%w[weave bob circle].sample, 'roundtime', 'There is nothing else', 'Face what', 'You must be closer', 'You must be standing', 'Strangely, you don\'t feel like fighting right now', 'flying too high for you to attack') unless game_state.npcs.empty?
  1780. when 'Analyze'
  1781. analyze(game_state, 0)
  1782. when 'Hunt'
  1783. bput('hunt', 'You take note of ', 'You find yourself unable to hunt in this area') unless game_state.retreating?
  1784. when 'Pray'
  1785. bput('pray meraud', 'You glance')
  1786. when 'Scream'
  1787. bput('Scream conc', 'Inhaling deeply', 'There is nothing', 'You open your mouth, then close it suddenly, looking somewhat like a fish') unless game_state.npcs.empty?
  1788. when 'Khri Prowess'
  1789. if @kneel_khri
  1790. fput('retreat')
  1791. fput('kneel')
  1792. end
  1793. bput('khri prowess', 'Remembering the mantra of mind over matter', 'You\'re already using the Prowess meditation.', 'previous use of the Prowess', 'Your body is willing', 'Your mind and body are willing') unless game_state.npcs.empty?
  1794. if @kneel_khri
  1795. waitrt?
  1796. fput('stand')
  1797. end
  1798. when 'Stealth'
  1799. if hide?(@hide_type) && !@dont_stalk && !game_state.npcs.empty? && @hide_type == 'hide'
  1800. stalked = bput('stalk', 'Stalk what',
  1801. 'Try being out of sight',
  1802. 'You move into position',
  1803. 'already stalking',
  1804. 'discovers you, ruining your hiding place') == ('You move into position' || 'already stalking')
  1805. bput('stop stalk', "You're not stalking anything though", 'You stop stalking') if stalked
  1806. end
  1807. bput('unhide', 'You come out of hiding', 'You slip out of hiding', 'But you are not', 'You try to creep out of hiding but your injuries cause you to stumble and crash to the ground!') if (game_state.npcs.empty? || @force_unhide) && hidden
  1808. when 'Ambush Stun'
  1809. return ambush_stun(game_state)
  1810. when 'Ambush Choke'
  1811. ambush_choke(game_state)
  1812. when 'Favor Orb'
  1813. fput("rub my #{@favor_god} orb")
  1814. when 'Charged Maneuver'
  1815. game_state.use_charged_maneuvers = true
  1816. when 'Meraud'
  1817. meraud_commune(game_state)
  1818. when 'PrayerMat'
  1819. pray_mat(game_state)
  1820. when 'Recall'
  1821. bput("recall #{game_state.npcs.first}", 'Roundtime', 'You are far too occupied') unless game_state.npcs.empty?
  1822. when 'Barb Research Augmentation'
  1823. bput('meditate research monkey', 'You clear ')
  1824. when 'Barb Research Warding'
  1825. bput('meditate research turtle', 'You clear ')
  1826. when 'Barb Research Debilitation'
  1827. bput('meditate research earthquake', 'You clear ')
  1828. when 'Collect'
  1829. game_state.sheath_whirlwind_offhand
  1830. retreat
  1831. put('engage') unless game_state.npcs.empty? or game_state.retreating?
  1832. collect(@forage_item)
  1833. waitrt?
  1834. game_state.wield_whirlwind_offhand
  1835. kick_pile?
  1836. when 'Smite'
  1837. smite(game_state)
  1838. end
  1839. waitrt?
  1840. false
  1841. end
  1842.  
  1843. private
  1844.  
  1845. def smite(game_state)
  1846. return if game_state.npcs.empty?
  1847. return if game_state.brawling? || game_state.offhand? || game_state.aimed_skill?
  1848. return if right_hand.nil?
  1849.  
  1850. bput('smite', 'Drawing strength from your conviction', 'You aren\'t close enough')
  1851. end
  1852.  
  1853. def meraud_commune(game_state)
  1854. unless (DRSkill.getrank('Theurgy') >= 300 || game_state.npcs.empty?) && !game_state.aimed_skill?
  1855. reset_ability(game_state, 'Meraud')
  1856. return
  1857. end
  1858. if /meraud/i =~ bput('commune sense', 'roundtime', 'Meraud', 'Meraud\'s')
  1859. reset_ability(game_state, 'Meraud', 60)
  1860. game_state.blessed_room = true
  1861. return
  1862. end
  1863. waitrt?
  1864. @equipment_manager.stow_weapon(game_state.weapon_name)
  1865. fput "get #{@water_holder} from my #{@theurgy_supply_container}"
  1866. if /that/i =~ bput("sprinkle #{@water_holder} on #{checkname}", 'You sprinkle', 'Sprinkle what?', 'Sprinkle that')
  1867. fput "put #{@water_holder} in my #{@theurgy_supply_container}"
  1868. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1869. @training_abilities.delete('Meraud')
  1870. return
  1871. end
  1872. bput "put #{@water_holder} in my #{@theurgy_supply_container}", 'You put', 'What were you referring to'
  1873. fput "get #{@flint_lighter}", 'You get a', 'You are already'
  1874. if bput('get incense', 'You get', 'You are already', 'referring to') == 'referring to'
  1875. fput "stow #{@flint_lighter}", 'You put your', 'Stow what'
  1876. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1877. @training_abilities.delete('Meraud')
  1878. return
  1879. end
  1880. fput 'light my incense with flint' # get messaging
  1881. pause
  1882. waitrt?
  1883. fput "wave incense at #{checkname}"
  1884. fput 'snuff incense'
  1885. bput("put incense in my #{@theurgy_supply_container}", 'You put', 'What were you referring to')
  1886. fput "stow #{@flint_lighter}", 'You put your', 'Stow what'
  1887. pause 1
  1888. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1889. bput('commune meraud', 'Nothing happens.', 'you have attempted a commune too recently', 'You close your eyes and concentrate, letting your mind still and feeling your breathing grow shallow', 'the ground is already consecrated')
  1890. pause
  1891. waitrt?
  1892. fix_standing
  1893. game_state.blessed_room = true
  1894. end
  1895.  
  1896. def pray_mat(game_state)
  1897. unless @prayer_mat && @theurgy_supply_container
  1898. echo '*** Cannot run PrayerMat; need prayer_mat and theurgy_supply_container defined'
  1899. @training_abilities.delete('PrayerMat')
  1900. return
  1901. end
  1902. waitrt?
  1903. retreat
  1904. @equipment_manager.stow_weapon(game_state.weapon_name)
  1905.  
  1906. unless bput(
  1907. "get #{@prayer_mat} from my #{@theurgy_supply_container}",
  1908. 'You get', 'What were you referring to'
  1909. ) == 'You get'
  1910. echo '*** Cannot run PrayerMat; no prayer mat in theurgy_supply_container'
  1911. @training_abilities.delete('PrayerMat')
  1912. return
  1913. end
  1914. fix_standing
  1915. bput("unroll #{@prayer_mat}",
  1916. 'reverently lay your', 'need to be holding that first')
  1917.  
  1918. bput("kneel #{@prayer_mat}", 'You humbly kneel', 'You kneel in the water')
  1919. bput("kiss #{@prayer_mat}", 'You bend forward to kiss')
  1920.  
  1921. bput("get wine from my #{@theurgy_supply_container}",
  1922. 'You get', 'What were you referring to')
  1923. bput("pour wine on #{@prayer_mat}",
  1924. 'You quietly pour', 'Pour what')
  1925. bput("put wine in my #{@theurgy_supply_container}",
  1926. 'You put', 'What were you referring to')
  1927. fix_standing
  1928.  
  1929. bput("roll #{@prayer_mat}",
  1930. 'carefully gather up',
  1931. 'need to be holding that first', 'not on the ground')
  1932. bput("put #{@prayer_mat} in my #{@theurgy_supply_container}",
  1933. 'You put', 'What were you referring to')
  1934. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1935. end
  1936.  
  1937. def ambush_stun(game_state)
  1938. return false unless game_state.can_ambush_stun?
  1939.  
  1940. dead_count = DRRoom.dead_npcs.size
  1941. unless game_state.weapon_name == @stun_weapon && !game_state.offhand?
  1942. @equipment_manager.stow_weapon(game_state.weapon_name)
  1943. @equipment_manager.wield_weapon(@stun_weapon, @stun_weapon_skill)
  1944. end
  1945.  
  1946. if hide?
  1947. bput('ambush stun', 'Wouldn\'t it be better if you used a melee weapon?', 'You must be hidden or invisible to ambush', 'You aren\'t close enough to attack', 'You don\'t have enough focus', 'You don\'t think you have enough focus', 'Roundtime', 'is already out cold')
  1948. pause
  1949. waitrt?
  1950. end
  1951.  
  1952. unless game_state.weapon_name == @stun_weapon && !game_state.offhand?
  1953. @equipment_manager.stow_weapon(@stun_weapon)
  1954. @equipment_manager.wield_weapon(game_state.weapon_name, game_state.weapon_skill)
  1955. end
  1956. DRRoom.dead_npcs.size > dead_count
  1957. end
  1958.  
  1959. def ambush_choke(game_state)
  1960. return unless game_state.can_ambush_stun?
  1961. return unless @dirt_stacker
  1962. return if @dirt_empty
  1963.  
  1964. unless bput("push my #{@dirt_stacker}",
  1965. 'You push', 'have any dirt', "I don't think pushing") == 'You push'
  1966. @dirt_empty = true
  1967. return
  1968. end
  1969.  
  1970. dirt_in_hand = true
  1971. if hide?
  1972. dirt_in_hand = bput(
  1973. 'ambush choke',
  1974. 'Wouldn\'t it be better if you used a melee weapon?',
  1975. 'You must be hidden or invisible to ambush',
  1976. 'You aren\'t close enough to attack',
  1977. 'You don\'t have enough focus',
  1978. 'You don\'t think you have enough focus',
  1979. 'Snipe dirt at somebody',
  1980. 'Roundtime'
  1981. ) != 'Roundtime'
  1982. pause
  1983. waitrt?
  1984. end
  1985.  
  1986. return unless dirt_in_hand
  1987. bput("put my dirt in my #{@dirt_stacker}",
  1988. 'dumping some dirt', 'What were you referring')
  1989. end
  1990.  
  1991. def analyze(game_state, fail_count)
  1992. return if game_state.npcs.empty?
  1993. return if fail_count > @analyze_retry_count
  1994. return if DRSkill.getxp('Tactics') >= @combat_training_abilities_target
  1995. case bput('analyze', 'roundtime', 'Analyze what', 'Your analysis reveals a massive opening', /You reveal an? .* [weakness|opening]/, /Your analysis reveals an? .* [weakness|opening]/, 'You fail to find any holes', 'There is nothing else', 'Face what', 'You must be closer', 'You must be standing', 'Strangely, you don\'t feel like fighting right now', 'flying too high for you to attack') # unless
  1996. when 'Analyze what'
  1997. case bput('face next', 'There is nothing else', 'You turn', 'What are you trying')
  1998. when 'There is nothing else', 'What are you trying'
  1999. fput('engage')
  2000. pause 2
  2001. end
  2002. analyze(game_state, fail_count)
  2003. when 'You must be closer'
  2004. fput('engage')
  2005. when 'Your analysis reveals a massive opening'
  2006. return
  2007. when 'You fail to find any holes'
  2008. analyze(game_state, fail_count + 1)
  2009. when /You reveal an? .* [weakness|opening]/, /Your analysis reveals an? .* [weakness|opening]/
  2010. analyze(game_state, fail_count)
  2011. end
  2012. waitrt?
  2013. end
  2014.  
  2015. def appraise(game_state, modifier)
  2016. return if game_state.retreating?
  2017. return if game_state.npcs.empty?
  2018. target = (game_state.npcs - @no_app).first
  2019. return unless target
  2020. return if DRSkill.getrank('Appraisal') < 76
  2021. return if bput("app #{target} #{modifier}", 'Taking stock of', 'It\'s dead', 'You can\'t determine anything about this creature.', 'I could not find', 'You cannot appraise that', 'roundtime', '^Perhaps that', 'Appraise what') != 'Perhaps that'
  2022.  
  2023. @no_app << target
  2024. end
  2025.  
  2026. def moon_mage_perc(game_state)
  2027. return if game_state.retreating?
  2028.  
  2029. retreat unless DRSkill.getrank('Attunement') > 500
  2030. bput('perc mana', 'You reach out')
  2031. end
  2032.  
  2033. def astrology(game_state)
  2034. return if game_state.retreating?
  2035.  
  2036. retreat
  2037. bput('predict weather', 'You predict that', 'You are far too', 'you lack the skill to grasp them fully')
  2038. waitrt?
  2039. fput('engage')
  2040. end
  2041.  
  2042. def reset_ability(game_state, ability_name, offset = 0)
  2043. ability_info = @training_abilities.find { |name, _| name == ability_name }.last
  2044. cooldown = ability_info.is_a?(Hash) ? ability_info[:cooldown] : ability_info.to_i
  2045. game_state.cooldown_timers[ability_name] = Time.now - [(cooldown - offset), 0].min
  2046. end
  2047.  
  2048. def select_ability(game_state)
  2049. ability = @training_abilities.find { |name, ability_info| check_ability(name, ability_info, game_state) }.first
  2050. echo("Selected: #{ability}") if ability && $debug_mode_ct
  2051. game_state.cooldown_timers[ability] = Time.now
  2052. ability
  2053. end
  2054.  
  2055. def check_ability(name, ability_info, game_state)
  2056. return false if ['PercMana', 'App Careful'].include?(name) && game_state.casting
  2057.  
  2058. check = ability_info.is_a?(Hash) ? ability_info[:check] : @skill_map[name]
  2059. check = [check].flatten
  2060. cooldown = ability_info.is_a?(Hash) ? ability_info[:cooldown] : ability_info.to_i
  2061. expcheck = check.nil? || check.any? { |skill_to_check| DRSkill.getxp(skill_to_check) < @combat_training_abilities_target }
  2062. return expcheck unless game_state.cooldown_timers[name]
  2063.  
  2064. Time.now - game_state.cooldown_timers[name] >= cooldown ? expcheck : false
  2065. end
  2066. end
  2067.  
  2068. class AttackProcess
  2069. include DRC
  2070.  
  2071. def initialize(settings)
  2072. echo('New AttackProcess') if $debug_mode_ct
  2073.  
  2074. @fatigue_regen_action = settings.fatigue_regen_action
  2075. echo(" @fatigue_regen_action: #{@fatigue_regen_action}") if $debug_mode_ct
  2076.  
  2077. @is_empath = DRStats.empath?
  2078. echo(" @is_empath: #{@is_empath}") if $debug_mode_ct
  2079.  
  2080. @undead = DRStats.empath? && settings.undead
  2081. echo(" @undead: #{@undead}") if $debug_mode_ct
  2082.  
  2083. @stealth_attack_aimed_action = settings.stealth_attack_aimed_action
  2084. echo(" @stealth_attack_aimed_action: #{@stealth_attack_aimed_action}") if $debug_mode_ct
  2085.  
  2086. @hide_type = settings.hide_type
  2087. echo(" @hide_type: #{@hide_type}") if $debug_mode_ct
  2088.  
  2089. @offhand_thrown = settings.offhand_thrown
  2090. echo(" @offhand_thrown: #{@offhand_thrown}") if $debug_mode_ct
  2091.  
  2092. @ambush_location = settings.ambush_location
  2093. echo(" @ambush_location: #{@ambush_location}") if $debug_mode_ct
  2094.  
  2095. @get_actions = %w[get wield]
  2096. echo(" @get_actions: #{@get_actions}") if $debug_mode_ct
  2097.  
  2098. @rt_actions = %w[gouge attack jab feint draw lunge slice lob throw]
  2099. echo(" @rt_actions: #{@rt_actions}") if $debug_mode_ct
  2100.  
  2101. @stow_actions = %w[stow sheath put]
  2102. echo(" @stow_actions: #{@stow_actions}") if $debug_mode_ct
  2103.  
  2104. Flags.add('ct-ranged-ready', 'You think you have your best shot possible now')
  2105. Flags.add('ct-face-what', 'Face what')
  2106. end
  2107.  
  2108. def execute(game_state)
  2109. if @is_empath && game_state.construct_mode?
  2110. @is_empath = false
  2111. echo ' setting @is_empath to false due to construct_mode override' if $debug_mode_ct
  2112. end
  2113.  
  2114. check_face(game_state)
  2115. if game_state.npcs.uniq.length == 1 && !game_state.stabbable?(game_state.npcs.uniq.first)
  2116. game_state.no_stab_current_mob = true
  2117. elsif game_state.mob_died && game_state.no_stab_current_mob
  2118. game_state.no_stab_current_mob = false
  2119. end
  2120.  
  2121. if game_state.dancing? || game_state.weapon_skill == 'Targeted Magic' || (@is_empath && !(@undead && DRSpells.active_spells['Absolution']))
  2122. if game_state.finish_killing?
  2123. echo('AttackProcess::clean_up') if $debug_mode_ct
  2124. game_state.next_clean_up_step
  2125. else
  2126. dance(game_state)
  2127. end
  2128. return false
  2129. end
  2130.  
  2131. if game_state.fatigue_low?
  2132. fput(@fatigue_regen_action)
  2133. return false
  2134. end
  2135.  
  2136. charged_maneuver = check_charged_maneuver(game_state)
  2137.  
  2138. if game_state.thrown_skill?
  2139. game_state.loaded = false
  2140. attack_thrown(game_state)
  2141. elsif game_state.aimed_skill?
  2142. attack_aimed(charged_maneuver, game_state)
  2143. else
  2144. game_state.loaded = false
  2145. attack_melee(charged_maneuver, game_state)
  2146. end
  2147. false
  2148. end
  2149.  
  2150. private
  2151.  
  2152. def check_face(game_state)
  2153. return unless Flags['ct-face-what']
  2154.  
  2155. fput("eng #{game_state.npcs.first}")
  2156. Flags.reset('ct-face-what')
  2157. end
  2158.  
  2159. def attack_melee(charged_maneuver, game_state)
  2160. waitrt?
  2161. if charged_maneuver
  2162. use_charged_maneuver(charged_maneuver, game_state)
  2163. else
  2164. if game_state.backstab? || game_state.use_stealth_attack? || game_state.ambush?
  2165. hide?(@hide_type)
  2166. end
  2167.  
  2168. verb = game_state.melee_attack_verb
  2169.  
  2170. command = game_state.offhand? ? "#{verb} left" : verb
  2171.  
  2172. if (game_state.backstab? || game_state.ambush?) && hiding?
  2173. if (game_state.backstab? && game_state.no_stab_current_mob) || (game_state.ambush? && !game_state.backstab?)
  2174. command += " #{@ambush_location}"
  2175. else
  2176. command.sub!(verb, 'backstab')
  2177. end
  2178. end
  2179.  
  2180. fput(command)
  2181. end
  2182.  
  2183. pause
  2184. waitrt?
  2185.  
  2186. if reget(5, 'You can\'t backstab that')
  2187. if game_state.npcs.uniq.length == 1
  2188. game_state.unstabbable(game_state.npcs.first)
  2189. else
  2190. game_state.no_stab_current_mob = true
  2191. end
  2192. end
  2193.  
  2194. if reget(5, 'You aren\'t close enough to attack', 'It would help if you were closer')
  2195. fput('engage')
  2196. pause 6
  2197. else
  2198. game_state.action_taken
  2199. end
  2200. return unless reget(5, 'You need two hands')
  2201.  
  2202. fput('stow left') if left_hand && left_hand !~ /\b#{game_state.weapon_name}/i
  2203. fput('stow right') if right_hand && right_hand !~ /\b#{game_state.weapon_name}/i
  2204. end
  2205.  
  2206. def attack_thrown(game_state)
  2207. attack_action = game_state.thrown_attack_verb
  2208. attack_action += ' left' if game_state.offhand?
  2209. bput(attack_action, 'roundtime', 'What are you trying to')
  2210. waitrt?
  2211.  
  2212. if game_state.weapon_name == 'blades'
  2213. until /(Stow what|You put your)/ =~ bput('stow blade', 'Stow what', 'You pick up .*blade', 'You put your')
  2214. end
  2215. end
  2216.  
  2217. retrieve_action = game_state.thrown_retrieve_verb
  2218. case bput(retrieve_action, 'You are already holding', 'You pick up', 'You get', 'You catch', 'What were you', "You don't have any bonds to invoke")
  2219. when 'What were you'
  2220. # Workaround for a game bug when you lob an unblessed weapon at a noncorporeal mob
  2221. # The weapon lands on the ground, not in the 'at feet' slot, and 'my' will not work
  2222. bput("get #{game_state.weapon_name}", 'You pick up', 'You get')
  2223. when 'You catch'
  2224. bput('swap', 'You move', 'You have nothing') if game_state.offhand?
  2225. end
  2226.  
  2227. game_state.action_taken
  2228. end
  2229.  
  2230. def shoot_aimed(command, game_state)
  2231. case bput(command, 'isn\'t loaded', 'There is nothing', 'But your', 'you (fire|poach)', 'I could not find', 'with no effect and falls to the ground', 'Face what', 'How can you (poach|snipe)', 'your moving to fire went unobserved', 'notices your attempt to remain hidden', 'you don\'t feel like fighting right now', 'That weapon must be in your right hand to fire')
  2232. when /How can you (poach|snipe)/, 'notices your attempt to remain hidden'
  2233. shoot_aimed('shoot', game_state)
  2234. when /you (fire|poach)/, 'your moving to fire went unobserved'
  2235. game_state.action_taken
  2236. when 'you don\'t feel like fighting right now', 'That weapon must be in your right hand to fire'
  2237. pause 1
  2238. shoot_aimed(command, game_state)
  2239. end
  2240. end
  2241.  
  2242. def attack_aimed(charged_maneuver, game_state)
  2243. game_state.selected_maneuver = charged_maneuver unless game_state.loaded
  2244. game_state.loaded = false if game_state.mob_died && !(game_state.casting_consume || game_state.prepare_consume)
  2245. game_state.clear_aim_queue if Flags['ct-ranged-ready']
  2246.  
  2247. if game_state.loaded && game_state.done_aiming?
  2248. if game_state.selected_maneuver
  2249. use_charged_maneuver(game_state.selected_maneuver, game_state)
  2250. game_state.action_taken
  2251. else
  2252. command = if game_state.use_stealth_attack? && hide?(@hide_type)
  2253. @stealth_attack_aimed_action
  2254. else
  2255. 'shoot'
  2256. end
  2257. shoot_aimed(command, game_state)
  2258. end
  2259. game_state.loaded = false
  2260. waitrt?
  2261. elsif game_state.loaded
  2262. actions = game_state.next_aim_action.split(';')
  2263. actions.each do |action|
  2264. first_word = action.split(' ')[0].downcase
  2265. matches = [/^You /]
  2266. matches = ['You get', 'You draw out', 'You pick up', "You're already holding that"] if @get_actions.include?(first_word)
  2267. matches = ['Roundtime',"You aren't close enough to attack"] if @rt_actions.include?(first_word)
  2268. matches = ['You put', 'You sheathe'] if @stow_actions.include?(first_word)
  2269. bput(action.strip, matches)
  2270. pause 0.25
  2271. waitrt?
  2272. end
  2273. else
  2274. if game_state.dual_load?
  2275. pause 0.5 until load_return = bput('load arrows', 'You reach into', 'already loaded', 'Such a feat would be impossible without the winds to guide', 'but are unable to draw upon its majesty')
  2276. if load_return == 'but are unable to draw upon its majesty'
  2277. pause 0.5 until bput('load', 'You reach into', 'You carefully load', 'already loaded')
  2278. end
  2279. else
  2280. pause 0.5 until bput('load', 'You reach into', 'You carefully load', 'already loaded')
  2281. end
  2282.  
  2283. waitrt?
  2284. game_state.loaded = true
  2285. unless game_state.selected_maneuver
  2286. game_state.set_aim_queue
  2287. aim(game_state)
  2288. Flags.reset('ct-ranged-ready')
  2289. end
  2290. end
  2291. end
  2292.  
  2293. def aim(game_state)
  2294. case bput('aim', 'You begin to target', 'You are already', 'There is nothing else', 'Face what\?', 'You shift your target', 'Your repeating crossbow', 'Your assassin\'s crossbow', 'Your repeating arbalest', 'Strangely, you don\'t feel like fighting right now', 'Your riot crossbow')
  2295. when 'Your repeating crossbow', 'Your assassin\'s crossbow', 'Your riot crossbow'
  2296. case bput('push my cross', 'A rapid series of clicks', 'You attempt to ready your repeating crossbow', 'You attempt to ready your assassin\'s crossbow', 'You attempt to ready your riot crossbow')
  2297. when 'A rapid series of clicks'
  2298. aim(game_state)
  2299. when 'You attempt to ready your repeating crossbow', 'You attempt to ready your assassin\'s crossbow', 'You attempt to ready your riot crossbow'
  2300. game_state.loaded = false
  2301. end
  2302. when 'Your repeating arbalest'
  2303. case bput('push my arbalest', 'A rapid series of clicks', 'You attempt to ready your repeating arbalest')
  2304. when 'A rapid series of clicks'
  2305. aim(game_state)
  2306. when 'You attempt to ready your repeating arbalest'
  2307. game_state.loaded = false
  2308. end
  2309. when 'Face what?'
  2310. game_state.clear_aim_queue
  2311. when 'Strangely, you don\'t feel like fighting right now'
  2312. pause 1
  2313. aim(game_state)
  2314. end
  2315. end
  2316.  
  2317. def dance(game_state)
  2318. if game_state.npcs.empty?
  2319. pause 1
  2320. else
  2321. game_state.set_dance_queue
  2322. case bput(game_state.next_dance_action, 'You must be closer', 'There is nothing else', 'What are you trying', /.*/)
  2323. when 'You must be closer', 'There is nothing else', 'What are you trying'
  2324. fput('engage')
  2325. pause 2
  2326. end
  2327. pause 0.5
  2328. waitrt?
  2329. end
  2330. end
  2331.  
  2332. def check_charged_maneuver(game_state)
  2333. return nil unless game_state.use_charged_maneuvers
  2334. return nil unless game_state.charged_maneuver
  2335.  
  2336. timer = game_state.cooldown_timers[game_state.charged_maneuver]
  2337. return nil if timer && (Time.now - timer).to_i < 60
  2338.  
  2339. echo "***Ready to use charged maneuver: #{game_state.charged_maneuver}***" if $debug_mode_ct
  2340. game_state.charged_maneuver
  2341. end
  2342.  
  2343. def use_charged_maneuver(action, game_state)
  2344. game_state.cooldown_timers[action] = Time.now
  2345. attempt = bput("maneuver #{action}", 'You brace your', 'balanced and', 'Taking a full step back', 'You take a step back', 'You lower your shoulders', 'You angle to the side and ', 'rest a bit longer', 'You square up your feet', 'You crouch down', 'You step to the side')
  2346. return if attempt == 'rest a bit longer'
  2347.  
  2348. # Maneuvers have extra non-RT delays
  2349. pause 7
  2350. waitrt?
  2351. game_state.use_charged_maneuvers = false
  2352. end
  2353. end
  2354.  
  2355. class CombatTrainer
  2356. include DRC
  2357.  
  2358. attr_reader :running
  2359.  
  2360. def stop
  2361. echo 'Received stop signal' if $debug_mode_ct
  2362. @stop = true
  2363. end
  2364.  
  2365. def set_args
  2366. arg_definitions = [
  2367. [
  2368. { name: 'debug', regex: /debug/i, optional: true },
  2369. { name: 'construct', regex: /construct/i, optional: true, description: 'Construct setting to override empath no attack settings.' },
  2370. { name: 'undead', regex: /undead/i, optional: true, description: 'Allows hunting of undead by empaths when absolution is up.' },
  2371. { name: 'dance', display: 'd#', regex: /d\d+/i, optional: true, description: 'Dance threshold, d2 would keep two enemies alive.' },
  2372. { name: 'retreat', display: 'r#', regex: /r\d+/i, optional: true, description: 'Retreat threshold, r3 would stay at range with three or more enemies' }
  2373. ]
  2374. ]
  2375.  
  2376. args = parse_args(arg_definitions, true)
  2377.  
  2378. settings = get_settings(args.flex)
  2379.  
  2380. settings.construct = args.construct
  2381. settings.undead = args.undead
  2382.  
  2383. settings.debug_mode = args.debug
  2384. set_dance(args.dance, settings)
  2385. set_retreat(args.retreat, settings)
  2386.  
  2387. settings
  2388. end
  2389.  
  2390. def initialize
  2391. settings = set_args
  2392. @equipment_manager = EquipmentManager.new(settings)
  2393. setup(settings)
  2394. settings.storage_containers.each { |container| fput("open my #{container}") }
  2395. @equipment_manager.wear_equipment_set?('standard')
  2396. end
  2397.  
  2398. def set_dance(message, settings)
  2399. return unless message
  2400. message =~ /d(\d+)/
  2401. settings.dance_threshold = Regexp.last_match(1).to_i
  2402. end
  2403.  
  2404. def set_retreat(message, settings)
  2405. return unless message
  2406. message =~ /r(\d+)/
  2407. settings.retreat_threshold = Regexp.last_match(1).to_i
  2408. end
  2409.  
  2410. def setup(settings)
  2411. Flags.add('ct-spellcast', '^Your formation of a targeting pattern around .+ has completed\.', 'Your target pattern has finished forming around the area', '^You feel fully prepared to cast your spell\.')
  2412.  
  2413. Flags.add('last-stance', 'Setting your Evasion stance to \d+%, your Parry stance to \d+%, and your Shield stance to \d+%. You have \d+ stance points left')
  2414.  
  2415. bput("stance set #{settings.default_stance}", 'Setting your')
  2416.  
  2417. @stop = false
  2418. @running = true
  2419. $debug_mode_ct = UserVars.combat_trainer_debug || settings.debug_mode
  2420. @game_state = GameState.new(settings, @equipment_manager)
  2421. @safety_process = SafetyProcess.new(settings)
  2422. @combat_processes = make_processes(settings)
  2423. end
  2424.  
  2425. def make_processes(settings)
  2426. [
  2427. SetupProcess.new(settings, @equipment_manager),
  2428. SpellProcess.new(settings, @equipment_manager),
  2429. PetProcess.new(settings),
  2430. AbilityProcess.new(settings),
  2431. LootProcess.new(settings, @equipment_manager),
  2432. ManipulateProcess.new(settings),
  2433. TrainerProcess.new(settings, @equipment_manager),
  2434. AttackProcess.new(settings)
  2435. ]
  2436. end
  2437.  
  2438. def get_process(process)
  2439. case process
  2440. when 'setup' then @combat_processes[0]
  2441. when 'spell' then @combat_processes[1]
  2442. when 'pet' then @combat_processes[2]
  2443. when 'ability' then @combat_processes[3]
  2444. when 'loot' then @combat_processes[4]
  2445. when 'manipulate' then @combat_processes[5]
  2446. when 'trainer' then @combat_processes[6]
  2447. when 'attack' then @combat_processes[7]
  2448. end
  2449. end
  2450.  
  2451. def start_combat
  2452. @equipment_manager.empty_hands
  2453. loop do
  2454. @combat_processes.each do |process|
  2455. @safety_process.execute(@game_state)
  2456. break if process.execute(@game_state)
  2457. end
  2458. pause 0.1
  2459. if @game_state.done_cleaning_up?
  2460. echo('CombatTrainer::clean_up') if $debug_mode_ct
  2461. @running = false
  2462. stop_script('tendme') if Script.running?('tendme')
  2463. break
  2464. end
  2465. next unless @stop && !@game_state.cleaning_up?
  2466. @game_state.next_clean_up_step
  2467. @game_state.stop_weak_attacks
  2468. @game_state.stop_analyze_combo
  2469. end
  2470. end
  2471. end
  2472.  
  2473. class GameState
  2474. include DRCA
  2475. include DRCS
  2476. include DRC
  2477.  
  2478. $thrown_skills = ['Heavy Thrown', 'Light Thrown']
  2479. $aim_skills = %w[Bow Slings Crossbow]
  2480. $ranged_skills = $thrown_skills + $aim_skills
  2481. $non_dance_skills = $ranged_skills + ['Brawling', 'Offhand Weapon']
  2482.  
  2483. attr_accessor :mob_died, :last_weapon_skill, :danger, :parrying, :casting, :need_bundle, :cooldown_timers, :no_stab_current_mob, :loaded, :selected_maneuver, :cast_timer, :casting_moonblade, :casting_weapon_buff, :use_charged_maneuvers, :casting_consume, :prepare_consume, :casting_cfb, :prepare_cfb, :wounds, :blessed_room, :currently_whirlwinding, :whirlwind_trainables, :reset_stance, :charges_total, :casting_sorcery
  2484.  
  2485. def initialize(settings, equipment_manager)
  2486. @equipment_manager = equipment_manager
  2487. echo('New GameState') if $debug_mode_ct
  2488. # public
  2489. @mob_died = false
  2490. @last_weapon_skill = nil
  2491. @danger = false
  2492. @parrying = false
  2493. @casting = false
  2494. @need_bundle = true
  2495. @cooldown_timers = {}
  2496. @no_stab_current_mob = false
  2497. @loaded = false
  2498. @selected_maneuver = nil
  2499. @cast_timer = nil
  2500. @casting_moonblade = false
  2501. @casting_sorcery = false
  2502. @casting_weapon_buff = false
  2503. @casting_consume = false
  2504. @prepare_consume = false
  2505. @prepare_cfb = false
  2506. @casting_cfb = false
  2507. @use_charged_maneuvers = false
  2508. @wounds = {}
  2509. @blessed_room = false
  2510. @charges_total = nil
  2511.  
  2512. # private
  2513. @clean_up_step = nil
  2514. @target_weapon_skill = -1
  2515. @no_skins = []
  2516. @constructs = []
  2517. @no_stab_mobs = []
  2518. @no_loot = []
  2519. @dancing = false
  2520. @retreating = false
  2521. @action_count = 0
  2522. @charges = nil
  2523. @aim_queue = []
  2524. @dance_queue = []
  2525. @analyze_combo_array = []
  2526. @currently_whirlwinding = false
  2527.  
  2528. @dynamic_dance_skill = settings.dynamic_dance_skill
  2529. echo(" @dynamic_dance_skill: #{@dynamic_dance_skill}") if $debug_mode_ct
  2530.  
  2531. @dance_skill = settings.dance_skill
  2532. echo(" @dance_skill: #{@dance_skill}") if $debug_mode_ct
  2533.  
  2534. @target_action_count = settings.combat_trainer_action_count
  2535. echo(" @target_action_count: #{@target_action_count}") if $debug_mode_ct
  2536.  
  2537. @dance_threshold = settings.dance_threshold
  2538. echo(" @dance_threshold: #{@dance_threshold}") if $debug_mode_ct
  2539.  
  2540. @retreat_threshold = settings.retreat_threshold
  2541. echo(" @retreat_threshold: #{@retreat_threshold}") if $debug_mode_ct
  2542.  
  2543. @summoned_weapons = settings.summoned_weapons
  2544. echo(" @summoned_weapons: #{@summoned_weapons}") if $debug_mode_ct
  2545.  
  2546. @target_increment = settings.combat_trainer_target_increment
  2547. echo(" @target_increment: #{@target_increment}") if $debug_mode_ct
  2548.  
  2549. @stances = settings.stances
  2550. echo(" @stances: #{@stances}") if $debug_mode_ct
  2551.  
  2552. @stances.keys do |key|
  2553. settings = @stances[key]
  2554. unless (settings & %w[evasion parry shield]).empty?
  2555. echo 'Please update to the latest version of stance: settings!'
  2556. settings.map! { |x| { 'parry' => 'Parry Ability', 'shield' => 'Shield Usage', 'evasion' => 'Evasion' }[x] }
  2557. end
  2558. (['Evasion', 'Shield Usage', 'Parry Ability'] - settings).each { |x| settings << x }
  2559. unless settings.size == 3
  2560. echo "Error: stance settings #{settings} include invalid stance."
  2561. exit
  2562. end
  2563. end
  2564. echo("Modified stances: #{@stances}") if $debug_mode_ct
  2565.  
  2566. @weapons_to_train = settings.weapon_training
  2567. echo(" @weapons_to_train: #{@weapons_to_train}") if $debug_mode_ct
  2568. if is_brawling_ranged?
  2569. echo(' Augmenting ranged groups due to brawling with blowgun') if $debug_mode_ct
  2570. $aim_skills << 'Brawling'
  2571. $ranged_skills << 'Brawling'
  2572. end
  2573.  
  2574. @use_stealth_attacks = settings.use_stealth_attacks
  2575. echo(" @use_stealth_attacks: #{@use_stealth_attacks}") if $debug_mode_ct
  2576.  
  2577. @ambush = settings.ambush
  2578. echo(" @ambush: #{@ambush}") if $debug_mode_ct
  2579.  
  2580. @backstab = settings.backstab
  2581. echo(" @backstab: #{@backstab}") if $debug_mode_ct
  2582.  
  2583. @charged_maneuvers = settings.charged_maneuvers
  2584. echo(" @charged_maneuvers: #{@charged_maneuvers}") if $debug_mode_ct
  2585.  
  2586. @fatigue_regen_threshold = settings.fatigue_regen_threshold
  2587. echo(" @fatigue_regen_threshold: #{@fatigue_regen_threshold}") if $debug_mode_ct
  2588.  
  2589. @balance_regen_threshold = settings.balance_regen_threshold
  2590. echo(" @balance_regen_threshold: #{@balance_regen_threshold}") if $debug_mode_ct
  2591.  
  2592. @aim_fillers = settings.aim_fillers
  2593. echo(" @aim_fillers: #{@aim_fillers}") if $debug_mode_ct
  2594.  
  2595. @aim_fillers_stealth = settings.aim_fillers_stealth
  2596. echo(" @aim_fillers_stealth: #{@aim_fillers_stealth}") if $debug_mode_ct
  2597.  
  2598. @dance_actions = settings.dance_actions
  2599. echo(" @dance_actions: #{@dance_actions}") if $debug_mode_ct
  2600.  
  2601. @dance_actions_stealth = settings.dance_actions_stealth
  2602. echo(" @dance_actions_stealth: #{@dance_actions_stealth}") if $debug_mode_ct
  2603.  
  2604. @ignored_npcs = settings.ignored_npcs
  2605. echo(" @ignored_npcs: #{@ignored_npcs}") if $debug_mode_ct
  2606.  
  2607. @dual_load = settings.dual_load
  2608. echo(" @dual_load: #{@dual_load}") if $debug_mode_ct
  2609.  
  2610. @summoned_weapons_element = settings.summoned_weapons_element
  2611. echo(" @summoned_weapons_element: #{@summoned_weapons_element}") if $debug_mode_ct
  2612.  
  2613. @summoned_weapons_ingot = settings.summoned_weapons_ingot
  2614. echo(" @summoned_weapons_ingot: #{@summoned_weapons_ingot}") if $debug_mode_ct
  2615.  
  2616. @stop_on_bleeding = settings.stop_hunting_if_bleeding
  2617. echo(" @stop_on_bleeding: #{@stop_on_bleeding}") if $debug_mode_ct
  2618.  
  2619. @cambrinth = settings.cambrinth
  2620. echo(" @cambrinth: #{@cambrinth}") if $debug_mode_ct
  2621.  
  2622. @stored_cambrinth = settings.stored_cambrinth
  2623. echo(" @stored_cambrinth: #{@stored_cambrinth}") if $debug_mode_ct
  2624.  
  2625. @cambrinth_cap = settings.cambrinth_cap
  2626. echo(" @cambrinth_cap: #{@cambrinth_cap}") if $debug_mode_ct
  2627.  
  2628. @use_weak_attacks = settings.use_weak_attacks
  2629. echo(" @use_weak_attacks: #{@use_weak_attacks}") if $debug_mode_ct
  2630.  
  2631. @use_barb_combos = settings.use_barb_combos
  2632. echo(" @use_barb_combos: #{@use_barb_combos}") if $debug_mode_ct
  2633.  
  2634. @skip_last_kill = settings.skip_last_kill
  2635. echo(" @skip_last_kill: #{@skip_last_kill}") if $debug_mode_ct
  2636.  
  2637. @attack_overrides = settings.attack_overrides
  2638. echo(" @attack_overrides: #{@attack_overrides}") if $debug_mode_ct
  2639.  
  2640. @whirlwind_trainables = settings.whirlwind_trainables
  2641. echo(" @whirlwind_trainables: #{@whirlwind_trainables}") if $debug_mode_ct
  2642.  
  2643. if @use_barb_combos
  2644. Flags.add('ct-accuracy-ready', 'You sense your combat accuracy decrease')
  2645. Flags['ct-accuracy-ready'] = true
  2646. Flags.add('ct-damage-ready', 'You sense your ability to land deadly blows decrease')
  2647. Flags['ct-damage-ready'] = true
  2648. Flags.add('ct-balance-ready', 'Your enhanced balance escapes')
  2649. Flags['ct-balance-ready'] = true
  2650. end
  2651.  
  2652. @dedicated_camb_use = settings.dedicated_camb_use
  2653. echo(" @dedicated_camb_use: #{@dedicated_camb_use}") if $debug_mode_ct
  2654.  
  2655. $thrown_skills << 'Offhand Weapon' if settings.offhand_thrown
  2656.  
  2657. @construct_mode = settings.construct(false)
  2658. echo(" @construct_mode: #{@construct_mode}") if $debug_mode_ct
  2659. end
  2660.  
  2661. def next_clean_up_step
  2662. echo(" Changing from clean up step #{@clean_up_step}") if $debug_mode_ct
  2663. case @clean_up_step
  2664. when nil
  2665. @clean_up_step = if @stop_on_bleeding && bleeding?
  2666. 'clear_magic'
  2667. elsif @skip_last_kill
  2668. 'clear_magic'
  2669. else
  2670. 'kill'
  2671. end
  2672. when 'kill'
  2673. @clean_up_step = 'clear_magic'
  2674. when 'clear_magic'
  2675. @clean_up_step = 'dismiss_pet'
  2676. when 'dismiss_pet'
  2677. @clean_up_step = 'stow'
  2678. when 'stow'
  2679. @clean_up_step = 'done'
  2680. end
  2681. end
  2682.  
  2683. def cleaning_up?
  2684. !@clean_up_step.nil?
  2685. end
  2686.  
  2687. def finish_killing?
  2688. @clean_up_step == 'kill'
  2689. end
  2690.  
  2691. def finish_spell_casting?
  2692. @clean_up_step == 'clear_magic'
  2693. end
  2694.  
  2695. def dismiss_pet?
  2696. @clean_up_step == 'dismiss_pet'
  2697. end
  2698.  
  2699. def stowing?
  2700. @clean_up_step == 'stow'
  2701. end
  2702.  
  2703. def done_cleaning_up?
  2704. @clean_up_step == 'done'
  2705. end
  2706.  
  2707. def update_weapon_info(weapon_skill)
  2708. @last_weapon_skill = @current_weapon_skill
  2709. @current_weapon_skill = weapon_skill
  2710. end
  2711.  
  2712. def attack_override
  2713. @attack_overrides[weapon_skill]
  2714. end
  2715.  
  2716. def whirlwind_offhand_name
  2717. weapon_training[@current_whirlwind_offhand_skill]
  2718. end
  2719.  
  2720. def update_whirlwind_weapon_info(weapon_skill)
  2721. @last_whirlwind_offhand_skill = @current_whirlwind_offhand_skill
  2722. @current_whirlwind_offhand_skill = weapon_skill
  2723. end
  2724.  
  2725. def whirlwind_offhand_skill
  2726. @current_whirlwind_offhand_skill
  2727. end
  2728.  
  2729. def whirlwind_trainable?
  2730. return false if whirlwind_trainables.empty?
  2731. whirlwind_trainables.include?(weapon_skill)
  2732. end
  2733.  
  2734. def sheath_whirlwind_offhand
  2735. return unless currently_whirlwinding
  2736. @equipment_manager.stow_weapon(whirlwind_offhand_name)
  2737. end
  2738.  
  2739. def necro_casting?
  2740. return false unless DRStats.necromancer?
  2741. return true if @prepare_cfb
  2742. return true if @casting_cfb
  2743. return true if @prepare_consume
  2744. return true if @casting_consume
  2745. false
  2746. end
  2747.  
  2748. def wield_whirlwind_offhand
  2749. return unless currently_whirlwinding
  2750. @equipment_manager.wield_weapon_offhand(whirlwind_offhand_name)
  2751. end
  2752.  
  2753. def determine_whirlwind_action
  2754. if @use_weak_attacks && Flags['ct-accuracy-ready']
  2755. update_analyze_array(true) if @analyze_combo_array.empty?
  2756. @analyze_combo_array.shift
  2757. elsif (npcs.length > 2) && !balance_low?
  2758. 'whirlwind'
  2759. else
  2760. action_reduce if npcs.length > 2
  2761. %w[jab bob feint].sample
  2762. end
  2763. end
  2764.  
  2765. def weapon_skill
  2766. @current_weapon_skill
  2767. end
  2768.  
  2769. def dance
  2770. if @dynamic_dance_skill
  2771. filtered_skills = weapon_training.reject { |skill, _| $non_dance_skills.include?(skill) }
  2772. @dance_skill = filtered_skills.min_by { |skill, _| DRSkill.getrank(skill) }.first
  2773. end
  2774. update_weapon_info(@dance_skill)
  2775. end
  2776.  
  2777. def skill_done?
  2778. current_exp = DRSkill.getxp(weapon_skill)
  2779. echo("action count: #{@action_count} vs #{@target_action_count}") if $debug_mode_ct
  2780. echo("skill exp: #{current_exp} vs #{@target_weapon_skill}") if $debug_mode_ct
  2781.  
  2782. @action_count >= @target_action_count || current_exp >= @target_weapon_skill
  2783. end
  2784.  
  2785. def update_room_npcs
  2786. @dancing = npcs.length <= @dance_threshold || npcs.empty?
  2787. @retreating = @retreat_threshold && npcs.length >= @retreat_threshold
  2788. end
  2789.  
  2790. def retreat_weapons
  2791. weapon_training.select { |skill, _| $ranged_skills.include?(skill) }
  2792. end
  2793.  
  2794. def summoned_info(weapon_skill)
  2795. @summoned_weapons.find { |summoned_skill| summoned_skill['name'] == weapon_skill }
  2796. end
  2797.  
  2798. def update_target_weapon_skill
  2799. @target_weapon_skill = [34, DRSkill.getxp(current_weapon_skill) + @target_increment].min
  2800. end
  2801.  
  2802. def current_weapon_stance
  2803. @stances[weapon_skill]
  2804. end
  2805.  
  2806. def skinnable?(mob_noun)
  2807. !@no_skins.include?(mob_noun)
  2808. end
  2809.  
  2810. def unskinnable(mob_noun)
  2811. echo("adding #{mob_noun} to no skin list: #{@no_skins}") if $debug_mode_ct
  2812. @no_skins.push(mob_noun)
  2813. end
  2814.  
  2815. def construct?(mob_noun)
  2816. @constructs.include?(mob_noun)
  2817. end
  2818.  
  2819. def construct(mob_noun)
  2820. @constructs.push(mob_noun)
  2821. end
  2822.  
  2823. def stabbable?(mob_noun)
  2824. !@no_stab_mobs.include?(mob_noun)
  2825. end
  2826.  
  2827. def unstabbable(mob_noun)
  2828. @no_stab_mobs.push(mob_noun)
  2829. end
  2830.  
  2831. def lootable?(item)
  2832. !@no_loot.include?(item.downcase)
  2833. end
  2834.  
  2835. def unlootable(item)
  2836. @no_loot.push(item.downcase)
  2837. end
  2838.  
  2839. def weapon_training
  2840. @weapons_to_train
  2841. end
  2842.  
  2843. def weapon_name
  2844. weapon_training[weapon_skill]
  2845. end
  2846.  
  2847. def last_weapon_name
  2848. weapon_training[@last_weapon_skill]
  2849. end
  2850.  
  2851. def thrown_skill?
  2852. $thrown_skills.include?(weapon_skill)
  2853. end
  2854.  
  2855. def aimed_skill?
  2856. $aim_skills.include?(weapon_skill)
  2857. end
  2858.  
  2859. def offhand?
  2860. weapon_skill == 'Offhand Weapon'
  2861. end
  2862.  
  2863. def brawling?
  2864. weapon_skill == 'Brawling' && !is_brawling_ranged?
  2865. end
  2866.  
  2867. def is_brawling_ranged?
  2868. /(?:\b|^)blowgun(?:\b|$)/i.match(weapon_training['Brawling'])
  2869. end
  2870.  
  2871. def use_stealth_attack?
  2872. @use_stealth_attacks && use_stealth?
  2873. end
  2874.  
  2875. def ambush?
  2876. @ambush && DRSkill.getxp('Backstab') < 34 && !brawling?
  2877. end
  2878.  
  2879. def backstab?
  2880. @backstab.include?(weapon_skill) && DRSkill.getxp('Backstab') < 34
  2881. end
  2882.  
  2883. def dancing?
  2884. @dancing
  2885. end
  2886.  
  2887. def retreating?
  2888. @retreating
  2889. end
  2890.  
  2891. def charged_maneuver
  2892. return @charged_maneuvers['Dual Wield'] if currently_whirlwinding
  2893. @charged_maneuvers[weapon_skill]
  2894. end
  2895.  
  2896. def fatigue_low?
  2897. echo("***Fatigue: #{DRStats.fatigue}***") if $debug_mode_ct
  2898. echo("***Target: #{@fatigue_regen_threshold}***") if $debug_mode_ct
  2899. DRStats.fatigue < @fatigue_regen_threshold
  2900. end
  2901.  
  2902. def balance_low?
  2903. echo("***Balance: #{DRStats.balance}***") if $debug_mode_ct
  2904. echo("***Target: #{@balance_regen_threshold}***") if $debug_mode_ct
  2905. DRStats.balance < @balance_regen_threshold
  2906. end
  2907.  
  2908. def reset_action_count
  2909. @action_count = 0
  2910. end
  2911.  
  2912. def action_taken
  2913. @action_count += 1
  2914. end
  2915.  
  2916. def action_reduce
  2917. @action_count -= 1
  2918. end
  2919.  
  2920. def set_aim_queue
  2921. echo("set_aim_queue #{@aim_fillers}:#{@aim_fillers_stealth}") if $debug_mode_ct
  2922.  
  2923. @aim_queue = aim_stealth? ? @aim_fillers_stealth[weapon_skill].dup : @aim_fillers[weapon_skill].dup
  2924. end
  2925.  
  2926. def clear_aim_queue
  2927. @aim_queue = []
  2928. end
  2929.  
  2930. def done_aiming?
  2931. @aim_queue.empty?
  2932. end
  2933.  
  2934. def next_aim_action
  2935. @aim_queue.shift
  2936. end
  2937.  
  2938. def set_dance_queue
  2939. return unless @dance_queue.empty?
  2940.  
  2941. echo("set_dance_queue #{@dance_actions}:#{@dance_actions_stealth}") if $debug_mode_ct
  2942.  
  2943. @dance_queue = dance_stealth? ? @dance_actions_stealth.dup : @dance_actions.dup
  2944. end
  2945.  
  2946. def next_dance_action
  2947. @dance_queue.shift
  2948. end
  2949.  
  2950. def cambrinth_charges(charges)
  2951. cambrinth = case charges.first
  2952. when Array
  2953. charges.first
  2954. else
  2955. charges
  2956. end
  2957. @charges = nil
  2958.  
  2959. return if cambrinth.nil? || cambrinth.empty?
  2960. @charges_total = cambrinth.inject(:+)
  2961. @charges = cambrinth.dup
  2962. end
  2963.  
  2964. def check_charging?
  2965. return false if @charges.nil?
  2966.  
  2967. if @charges.empty?
  2968. echo('check_charging?: done') if $debug_mode_ct
  2969. cambrinth_charges(nil)
  2970. return false
  2971. end
  2972.  
  2973. find_cambrinth(@cambrinth, @stored_cambrinth, @cambrinth_cap)
  2974.  
  2975. next_charge = @charges.pop
  2976. echo("check_charging?: #{next_charge}") if $debug_mode_ct
  2977.  
  2978. @charges = [] unless charge?(@cambrinth, next_charge)
  2979.  
  2980. stow_cambrinth(@cambrinth, @stored_cambrinth, @cambrinth_cap)
  2981.  
  2982. true
  2983. end
  2984.  
  2985. def check_harness
  2986. return if @charges.nil?
  2987.  
  2988. if @charges.empty?
  2989. echo('check_harness?: done') if $debug_mode_ct
  2990. cambrinth_charges(nil)
  2991. return
  2992. end
  2993.  
  2994. harness_mana(@charges.flatten)
  2995.  
  2996. @charges = []
  2997. end
  2998.  
  2999. def npcs
  3000. DRRoom.npcs - @ignored_npcs
  3001. end
  3002.  
  3003. def dual_load?
  3004. @dual_load && weapon_skill == 'Bow' &&
  3005. DRSkill.getrank('Bow') >= 201 && DRStats.agility >= 30 && DRStats.reflex >= 30 &&
  3006. (DRSpells.active_spells['See the Wind'] || DRStats.barbarian?)
  3007. end
  3008.  
  3009. def prepare_summoned_weapon(weapon_already_summoned)
  3010. info = summoned_info(weapon_skill)
  3011.  
  3012. summon_weapon(UserVars.moons['visible'].first, @summoned_weapons_element, @summoned_weapons_ingot, weapon_skill) unless weapon_already_summoned
  3013. shape_summoned_weapon(weapon_skill, @summoned_weapons_ingot) if weapon_already_summoned || DRStats.moon_mage?
  3014. turn_summoned_weapon if info['turn']
  3015. push_summoned_weapon if info['push']
  3016. pull_summoned_weapon if info['pull']
  3017. end
  3018.  
  3019. def can_ambush_stun?
  3020. !npcs.empty? && !aimed_skill?
  3021. end
  3022.  
  3023. def stop_weak_attacks
  3024. @use_weak_attacks = false
  3025. end
  3026.  
  3027. def stop_analyze_combo
  3028. @use_barb_combos = false
  3029. end
  3030.  
  3031. def set_barb_accuracy_flag
  3032. Flags.reset('ct-accuracy-ready')
  3033. end
  3034.  
  3035. def set_barb_damage_flag
  3036. Flags.reset('ct-damage-ready')
  3037. end
  3038.  
  3039. def melee_attack_verb
  3040. if currently_whirlwinding
  3041. determine_whirlwind_action
  3042. elsif attack_override
  3043. attack_override
  3044. elsif @use_weak_attacks
  3045. brawling? ? 'gouge' : 'jab'
  3046. elsif @use_barb_combos && !offhand? && !brawling?
  3047. update_analyze_array(false) if @analyze_combo_array.empty?
  3048. @analyze_combo_array.shift
  3049. else
  3050. 'attack'
  3051. end
  3052. end
  3053.  
  3054. def thrown_attack_verb
  3055. if bound_weapon? && !@use_weak_attacks
  3056. 'hurl'
  3057. elsif @use_weak_attacks || lodging_weapon?
  3058. 'lob'
  3059. else
  3060. 'throw'
  3061. end
  3062. end
  3063.  
  3064. def thrown_retrieve_verb
  3065. if bound_weapon?
  3066. 'invoke'
  3067. else
  3068. "get my #{weapon_name}"
  3069. end
  3070. end
  3071.  
  3072. def cfb_active?
  3073. DRSpells.active_spells.include?('Call from Beyond')
  3074. end
  3075.  
  3076. def construct_mode?
  3077. @construct_mode
  3078. end
  3079.  
  3080. private
  3081.  
  3082. def lodging_weapon?
  3083. item = @equipment_manager.item_by_desc(weapon_name)
  3084. item.nil? || item.lodges
  3085. end
  3086.  
  3087. def bound_weapon?
  3088. item = @equipment_manager.item_by_desc(weapon_name)
  3089. item && item.bound
  3090. end
  3091.  
  3092. def perform_analyze?(combo_type, expertise_requirement)
  3093. return false if combo_type != 'flame' && !Flags["ct-#{combo_type}-ready"]
  3094. return false if DRSkill.getrank('Expertise') < expertise_requirement
  3095.  
  3096. result = bput("analyze #{combo_type}", 'cannot repeat', 'Analyze what\?', 'by landing an? .*', 'You need to hold')
  3097. waitrt?
  3098.  
  3099. case result
  3100. when 'cannot repeat'
  3101. Flags.reset("ct-#{combo_type}-ready")
  3102. return false
  3103. when 'Analyze what?'
  3104. fput('face next')
  3105. return true
  3106. end
  3107.  
  3108. text = result.match(/by landing an? (.*)\.$/).to_a[1]
  3109. @analyze_combo_array = list_to_nouns(text)
  3110.  
  3111. true
  3112. end
  3113.  
  3114. def update_analyze_array(only_accuracy)
  3115. return perform_analyze?('accuracy', 50) if only_accuracy
  3116. { 'accuracy' => 50, 'damage' => 125, 'balance' => 600, 'flame' => 0 }.each do |type, expertise|
  3117. break if perform_analyze?(type, expertise)
  3118. end
  3119. end
  3120.  
  3121. def dance_stealth?
  3122. @dance_actions_stealth && !@dance_actions_stealth.empty? && use_stealth?
  3123. end
  3124.  
  3125. def aim_stealth?
  3126. @aim_fillers_stealth && @aim_fillers_stealth[weapon_skill] && use_stealth?
  3127. end
  3128.  
  3129. def use_stealth?
  3130. DRSkill.getxp('Stealth') < 32
  3131. end
  3132.  
  3133. attr_accessor :clean_up_step, :current_weapon_skill, :target_weapon_skill, :no_skins, :constructs, :no_stab_mobs, :no_loot, :dancing, :retreating, :action_count, :charges, :aim_queue, :dance_queue, :analyze_combo_array
  3134. attr_reader :dance_skill, :target_action_count, :dance_threshold, :retreat_threshold, :summoned_weapons, :target_increment, :stances, :weapons_to_train, :use_stealth_attacks, :ambush, :backstab, :charged_maneuvers, :fatigue_regen_threshold, :aim_fillers, :aim_fillers_stealth, :dance_actions, :dance_actions_stealth, :ignored_npcs, :dual_load, :summoned_weapons_element, :summoned_weapons_ingot, :cambrinth, :stored_cambrinth, :cambrinth_cap, :use_weak_attacks, :dedicated_camb_use, :use_barb_combos, :balance_regen_threshold
  3135. end
  3136.  
  3137. before_dying do
  3138. DRCA.release_cyclics
  3139. end
  3140.  
  3141. $COMBAT_TRAINER = CombatTrainer.new
  3142. $COMBAT_TRAINER.start_combat
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement