diff --git a/bescort.lic b/bescort.lic index 70b8fb3105..2bac60a369 100644 --- a/bescort.lic +++ b/bescort.lic @@ -237,6 +237,7 @@ class Bescort @settings = get_settings @equipment_manager = EquipmentManager.new(@settings) + @flying_mount = @settings.flying_mount pause @@ -323,7 +324,7 @@ class Bescort mode = mode.downcase case mode when 'mount' - DRC.bput("get my #{type}", /You get/, /You pick up/, /You are already holding/, /What were you referring/) + DRCI.get_item?(type) case type when /broom|dirigible/i case DRC.bput("mount my #{type}", /You mount your/, /You are already mounted/, /What were you referring/) @@ -349,15 +350,14 @@ class Bescort case type when /broom|dirigible/i DRC.bput('dismount', /Your .* floats down to the ground/, /You climb off/) - @equipment_manager.empty_hands when /carpet|rug/i DRC.bput('dismount', /Your .* floats down to the ground/, /You climb off/) DRC.bput("roll #{type}", /You roll up/, /You can't roll/) - DRC.bput("stow my #{type}", /You put/, /You pick up/, /Stow what?/) else DRC.message("#{type} is not a valid type of flying mount.") exit end + DRCI.put_away_item?(type) end end @@ -468,18 +468,16 @@ class Bescort manual_go2(start_room) move('go stream bank') # Once in the stream then you're in a safe room, get mount or remove gear. - flying_mount = @settings.flying_mount @equipment_manager.empty_hands - have_changed_gear = flying_mount ? false : @equipment_manager.wear_equipment_set?('swimming') - if flying_mount - use_flying_mount(flying_mount, 'mount') + have_changed_gear = @flying_mount ? false : @equipment_manager.wear_equipment_set?('swimming') + if @flying_mount + use_flying_mount(@flying_mount, 'mount') move(moveset.first) # mount travels all three rooms at once else moveset.each { |dir| swim(dir) } end - use_flying_mount(flying_mount, 'dismount') if flying_mount + use_flying_mount(@flying_mount, 'dismount') if @flying_mount # While in the stream then you're in a safe room, dismount or wear gear. - @equipment_manager.empty_hands @equipment_manager.wear_equipment_set?('standard') if have_changed_gear move('go stream bank') # You're now among cave trolls! @@ -1076,13 +1074,12 @@ class Bescort end def faldesu(mode) - flying_mount = @settings.flying_mount unless mode =~ /haven|crossing/i echo 'You must specify haven or crossing for traversing the faldesu river' exit end - if flying_mount + if @flying_mount swim_faldesu(mode =~ /haven/i) return end @@ -1108,40 +1105,45 @@ class Bescort path = mode == 'shard' ? $ICE_PATH_SHARD : $ICE_PATH_HIB @equipment_manager.empty_hands - settings = get_settings - footwear = settings.footwear + footwear = @settings.footwear move_fast = false footwear_removed = false skates_worn = false - # If the footwear setting has been defined then respect that - # and only try to remove it. If you're not wearing this item - # then obviously nothing on your feet will be removed. - # You might: - # - have incorrect yaml - # - put something else on (or nothing on) - # - already wearing your skates - if footwear - if DRCI.remove_item?(footwear) - footwear_removed = true - DRCI.put_away_item?(footwear) + if @flying_mount + move_fast = true + use_flying_mount(@flying_mount, 'mount', 'glide') + path = mode == 'shard' ? %w[se se sw sw se] : %w[nw ne ne nw sw] + else + # If the footwear setting has been defined then respect that + # and only try to remove it. If you're not wearing this item + # then obviously nothing on your feet will be removed. + # You might: + # - have incorrect yaml + # - put something else on (or nothing on) + # - already wearing your skates + if footwear + if DRCI.remove_item?(footwear) + footwear_removed = true + DRCI.put_away_item?(footwear) + end end - end - # If you have some skates then try to get and wear them. - # Note, if you're already wearing the skates then we won't - # be able to "get" them, and that's why the attempt to wear - # is not conditional upon you getting them to your hands. - if DRCI.exists?('skates') - DRCI.get_item?('skates') - if DRCI.wear_item?('skates') - skates_worn = true - else - DRCI.put_away_item?('skates') + # If you have some skates then try to get and wear them. + # Note, if you're already wearing the skates then we won't + # be able to "get" them, and that's why the attempt to wear + # is not conditional upon you getting them to your hands. + if DRCI.exists?('skates') + DRCI.get_item?('skates') + if DRCI.wear_item?('skates') + skates_worn = true + else + DRCI.put_away_item?('skates') + end end - end - move_fast = skates_worn + move_fast = skates_worn + end # Despite our best efforts, if bescort starts moving you fast # and the game gives you warnings to slow down, SLOW DOWN! @@ -1174,6 +1176,10 @@ class Bescort DRCI.get_item?(footwear) DRCI.wear_item?(footwear) end + + if @flying_mount + use_flying_mount(@flying_mount, 'dismount') + end end def swim(dir) @@ -1183,13 +1189,12 @@ class Bescort end def swim_faldesu(north) - flying_mount = @settings.flying_mount start = north ? 1375 : 473 manual_go2(start) moveset = north ? %w[north northwest northeast] : %w[south southwest southeast] move 'dive river' - if flying_mount - use_flying_mount(flying_mount, 'mount') + if @flying_mount + use_flying_mount(@flying_mount, 'mount') if north move n move nw @@ -1198,8 +1203,7 @@ class Bescort move sw end move 'go bridge' - use_flying_mount(flying_mount, 'dismount') - @equipment_manager.empty_hands + use_flying_mount(@flying_mount, 'dismount') else swim(moveset[0]) while XMLData.room_exits.include?(moveset[0]) swim(moveset[1]) while XMLData.room_exits.include?('east') @@ -1477,9 +1481,8 @@ class Bescort end def segoltha(mode) - flying_mount = @settings.flying_mount @equipment_manager.empty_hands - have_changed_gear = flying_mount ? false : @equipment_manager.wear_equipment_set?('swimming') + have_changed_gear = @flying_mount ? false : @equipment_manager.wear_equipment_set?('swimming') move_count = 0 if mode =~ /^n/i dir_of_travel = 'north' @@ -1495,8 +1498,8 @@ class Bescort exit end - if flying_mount - use_flying_mount(flying_mount, 'mount', 'skim') + if @flying_mount + use_flying_mount(@flying_mount, 'mount', 'skim') if dir_of_travel == 'south' move 'go bank' move 'west' @@ -1511,7 +1514,7 @@ class Bescort move 'east' move 'go slope' end - use_flying_mount(flying_mount, 'dismount') + use_flying_mount(@flying_mount, 'dismount') return end @@ -1640,7 +1643,7 @@ class Bescort DRCA.release_cyclics unless DRCA.cast_spell({ 'abbrev' => 'rezz', 'mana' => 5, - 'cyclic' => true }, get_settings) + 'cyclic' => true }, @settings) echo('Failed to cast Resurrection! Try again or use the puzzle to enter.') exit end @@ -2014,7 +2017,6 @@ class Bescort def get_fare?(amount, town, room) return false unless @settings.bescort_fare_handling - settings = get_settings echo 'GETTING MONEY, YOU SLOB.' echo "Heading to #{town} for public transportation fare" pause 1 @@ -2025,7 +2027,7 @@ class Bescort echo 'You might be a necromancer! Get some money manually!' return false end - settings.hometown = town + @settings.hometown = town succeeded = false DRCM.minimize_coins(amount).each { |each_amount| succeeded = DRCM.get_money_from_bank(each_amount, settings) } echo "Put some fare money in the #{town} bank!" unless succeeded diff --git a/circlecheck.lic b/circlecheck.lic index abec25212c..ac22ea55e1 100644 --- a/circlecheck.lic +++ b/circlecheck.lic @@ -339,7 +339,7 @@ $GuildReqs = { }, hard_reqs: ['Evasion', 'Parry Ability', 'Expertise', 'Inner Fire', 'Tactics'], - restricted: ['Sorcery', 'Thievery', 'Utility', 'Targeted Magic', 'Offhand Weapon'] + restricted: ['Sorcery', 'Thievery', 'Targeted Magic', 'Offhand Weapon'] }, 'Necromancer' => { diff --git a/combat-trainer.lic b/combat-trainer.lic index 7accbfb68c..f824e1c39f 100644 --- a/combat-trainer.lic +++ b/combat-trainer.lic @@ -84,16 +84,18 @@ class SetupProcess private - def armor_hysteresis? + def armor_hysteresis?(game_state) return false unless @armor_hysteresis return false if @cycle_armors.keys.any? { |skill| DRSkill.getxp(skill) < 25 } all_swap_pieces = @cycle_armors.keys.map { |armortype| @cycle_armors[armortype] }.flatten if @cycle_armors.keys.all? { |skill| DRSkill.getxp(skill) > 32 } if @last_worn_type != @default_armor && @cycle_armors.keys.include?(@default_armor) + game_state.sheath_whirlwind_offhand @equipment_manager.worn_items(all_swap_pieces).each { |item| @equipment_manager.remove_item(item) } @equipment_manager.wear_items(@equipment_manager.desc_to_items(@cycle_armors[@default_armor])) @last_worn_type = @default_armor + game_state.wield_whirlwind_offhand end end true @@ -113,7 +115,7 @@ class SetupProcess end def check_armor_swap(game_state) - return if armor_hysteresis? + return if armor_hysteresis?(game_state) return if Time.now - @last_cycle_time < @cycle_armors_time return if game_state.loaded diff --git a/data/base-spells.yaml b/data/base-spells.yaml index 33d9d10ade..b7dd0db984 100644 --- a/data/base-spells.yaml +++ b/data/base-spells.yaml @@ -142,6 +142,8 @@ prep_messages: - Please don't do that here - You cannot use the tattoo while maintaining the effort to stay hidden - As you attempt to prepare the spell, a sense of overwhelming peace washes over you +# You tried to target a spell but there is nothing left to face +- There is nothing else to face cast_messages: - Converging in midair, angular ripples assemble a slender hexagonal rod whorled with faintly shifting fractals diff --git a/dependency.lic b/dependency.lic index fbbe2e33b4..4b17dea9c3 100644 --- a/dependency.lic +++ b/dependency.lic @@ -10,7 +10,7 @@ require 'ostruct' require 'digest/sha1' require 'monitor' -$DEPENDENCY_VERSION = '1.6.6' +$DEPENDENCY_VERSION = '1.7.1' $MIN_RUBY_VERSION = '3.2.2' no_pause_all @@ -20,6 +20,7 @@ while Script.running?('repository') echo("Repository is running, pausing for 10 seconds.") pause 10 end + class Object # IMPORT FUTURE LAWLZ def itself @@ -184,13 +185,21 @@ install = args.install class ScriptManager attr_reader :autostarts - attr_accessor :developer, :ignore_dependency def initialize(debug) unless XMLData.game =~ /^DR/ echo("This script is not intended for usage with games other than Dragonrealms. Exiting now") exit end + unless LICH_VERSION.match?(/^5/) + _respond("*****************************************************************************") + _respond("* Unsupported Lich versions detected. *") + _respond("* Please see https://github.com/rpherbig/dr-scripts/wiki/First-Time-Setup *") + _respond("* For an update path. *") + _respond("*****************************************************************************") + exit + end + @debug = debug @paste_bin_token = 'dca351a27a8af501a8d3123e29af7981' @paste_bin_url = 'https://pastebin.com/api/api_post.php' @@ -199,9 +208,7 @@ class ScriptManager @status_branch = Settings['status_branch'] || 'master' update_status_url # Gating setting lich_url on lich version - unless LICH_VERSION.match?(/^5/) - @lich_url = 'https://api.github.com/repos/dragon-realms/dr-lich/git/trees/master' - end + UserVars.autostart_scripts ||= [] UserVars.autostart_scripts.uniq! UserVars.autostart_scripts = UserVars.autostart_scripts - ['dependency'] @@ -210,15 +217,10 @@ class ScriptManager Settings['autostart'] = Settings['autostart'] - ['dependency'] # Setting Settings['lich_fork_sha'] to nil if using lich5. This setting isn't used anymore. - if LICH_VERSION.match?(/^5/) - Settings['lich_fork_sha'] = nil if Settings['lich_fork_sha'] - end Settings['base_versions'] ||= {} CharSettings['next_ruby_version_check_datetime'] = Time.now - @developer = Settings['dependency-developer'] || false - @ignore_dependency = Settings['ignore-dependency'] || false @add_autos = [] @remove_autos = [] update_autostarts @@ -228,11 +230,6 @@ class ScriptManager @request_authorization = manage_github_token @versions = nil - - # Gating lich fork code to non-lich5 - unless LICH_VERSION.match?(/^5/) - @enable_fork = LICH_VERSION =~ /f/ - end end def updated_dependency? @@ -307,8 +304,6 @@ class ScriptManager def run_queue validate_supported_ruby_version - Settings['dependency-developer'] = @developer - Settings['ignore-dependency'] = @ignore_dependency Settings['status_repo'] = @status_repo Settings['status_branch'] = @status_branch update = false @@ -323,16 +318,6 @@ class ScriptManager @remove_autos.each { |script| Settings['autostart'].delete(script) } @remove_autos = [] end - # No lich fork with lich5 - unless LICH_VERSION.match?(/^5/) - if @disable_fork - stop_download_lich - @disable_fork = nil - elsif @enable_fork - download_lich - @enable_fork = nil - end - end submit_thieving_update(*@thievery_queue.pop) unless @thievery_queue.empty? submit_shop_update(@shop_update_queue.pop) unless @shop_update_queue.empty? @@ -388,46 +373,12 @@ class ScriptManager end end - unless LICH_VERSION.match?(/^5/) - def queue_lich - @enable_fork = true - end - - def unqueue_lich - @disable_fork = true - end - - def download_lich - return if @developer - - lich_data = make_request(@lich_url)['tree'].find { |data| data['path'] == 'lich.rbw' } - if LICH_VERSION =~ /f/ && Settings['lich_fork_sha'] == lich_data['sha'] - echo('latest version of lich fork already downloaded.') - return - end - blob = make_request(lich_data['url']) - File.open('lich.rbw', 'w') { |file| file.print(Base64.decode64(blob['content'])) } - Settings['lich_fork_sha'] = lich_data['sha'] - echo('New version of lich installed, please restart Lich.') - end - - def stop_download_lich - Settings['lich_fork_sha'] = nil - end - end - def download_script(filename, force = false) return if filename.nil? || filename.empty? - if filename == 'dependency.lic' && @ignore_dependency - respond 'ignoring dependency download due to ignore_dependency setting' - respond "use '#{$clean_lich_char}e check_dependency' to check the value." - return - end echo("downloading:#{filename}") if @debug info = get_file_status(filename) return unless info - return if @developer return if get_versions[filename] == info['sha'] && !force echo("info:#{info}") if @debug @@ -480,8 +431,6 @@ class ScriptManager end def check_base_files - return if @developer - verify_or_make_dir File.join(SCRIPT_DIR, 'profiles') profile_tree_url = get_status['tree'].find { |element| element['path'] == 'profiles' }['url'] make_request(profile_tree_url)['tree'] @@ -496,8 +445,6 @@ class ScriptManager end def check_data_files - return if @developer - verify_or_make_dir File.join(SCRIPT_DIR, 'data') profile_tree_url = get_status['tree'].find { |element| element['path'] == 'data' }['url'] make_request(profile_tree_url)['tree'] @@ -873,9 +820,10 @@ class SlackbotManager private def register_slackbot - return if @slackbot return unless @username + return unless @slackbot.nil? + echo("Registering Slackbot") custom_require.call('slackbot') @slackbot = SlackBot.new end @@ -1622,7 +1570,7 @@ def verify_script(script_names) .each do |name| echo "Failed to find a script named '#{name}'" echo "Please report this to " - echo "or to Discord " + echo "or to Discord " state = false end state @@ -1665,11 +1613,6 @@ end def replace_all managed_scripts .each do |script| - if script == 'dependency.lic' && $manager.ignore_dependency - respond 'ignoring replace dependency due to ignore_dependency setting' - respond "use '#{$clean_lich_char}e check_dependency' to check the value." - next - end new_name = "#{script}.#{Time.now.to_i}.bak" respond "Renaming existing script #{script} to #{new_name}" File.rename(File.join(SCRIPT_DIR, "#{script}"), File.join(SCRIPT_DIR, "#{new_name}")) @@ -1711,73 +1654,6 @@ def stop_autostart(script_names) end end -def set_dev_mode - echo "Now turning dev mode on" - $manager.developer = true - echo "Developer mode now set to: #{$manager.developer}" -end - -def unset_dev_mode - echo "Now turning dev mode off" - $manager.developer = false - echo "Developer mode now set to: #{$manager.developer}" -end - -def check_dev_mode - echo "Developer mode set to: #{$manager.developer}" -end - -def toggle_developer_mode - echo "THIS METHOD IS NO LONGER USED. USE '#{$clean_lich_char}e set_dev_mode' and '#{$clean_lich_char}e unset_dev_mode'." -end - -def ignore_dependency - echo "Now ignoring dependency updates" - $manager.ignore_dependency = true - echo "ignore_dependency now set to: #{$manager.ignore_dependency}" -end - -def unignore_dependency - echo "Now processing dependency updates" - $manager.ignore_dependency = false - echo "ignore_dependency now set to: #{$manager.ignore_dependency}" -end - -def check_dependency - echo "ignore_dependency is set to: #{$manager.ignore_dependency}" - echo "Use '#{$clean_lich_char}e ignore_dependency' and '#{$clean_lich_char}e unignore_dependency' to change." -end - -unless LICH_VERSION.match?(/^5/) - def use_lich_fork - echo 'Now switching onto the DR lich fork...' - start_script('repository', ['unset-lich-updatable']) - pause 1 while Script.running?('repository') - echo 'Turning off updates from main lich branch on go2...' - start_script('repository', ['unset-updatable', 'go2']) - $manager.queue_lich - end - - def use_lich_main - echo 'Now switching onto the lich mainline...' - start_script('repository', ['set-lich-updatable']) - pause 1 while Script.running?('repository') - - echo 'Turning updates from main lich branch on go2 back on...' - start_script('repository', ['set-updatable', 'go2']) - pause 1 while Script.running?('repository') - - start_script('repository', ['download-lich']) - pause - pause 1 while Script.running?('repository') - echo('New version of lich installed, please restart Lich.') - end - - def toggle_lich_fork - echo "THIS METHOD IS NO LONGER USED. USE #{$clean_lich_char}e use_lich_fork and #{$clean_lich_char}e use_lich_main" - end -end - def set_custom_status_repo(repo, branch = 'master') $manager.set_custom_status_repo(repo, branch) end @@ -1912,14 +1788,6 @@ $manager.check_data_files $manager.start_scripts $manager.make_map_edits -if LICH_VERSION.match?(/^4/) - _respond("*****************************************************************************") - _respond("* Lich version 4 detected. This version of lich was deprecated in mid-2022. *") - _respond("* Please see https://github.com/rpherbig/dr-scripts/wiki/First-Time-Setup *") - _respond("* For an update path. *") - _respond("*****************************************************************************") -end - if $manager.updated_dependency? echo('Update found for dependency.lic') update_d diff --git a/help-me.lic b/help-me.lic index 7ef59b4fa2..7d672e5eb8 100644 --- a/help-me.lic +++ b/help-me.lic @@ -39,8 +39,6 @@ class HelpMe message_body += "\n" message_body += "Game Client: #{$frontend}" message_body += "\n" - message_body += "Dev Mode: #{$manager.developer}" - message_body += "\n" Dir[File.join(SCRIPT_DIR, 'profiles/*.yaml')].map { |item| File.path(item) }.select { |path| path.include?("#{checkname}-") }.each do |path| message_body += "\n****" * 3 diff --git a/inventory-manager.lic b/inventory-manager.lic index b299de26e8..ea65722643 100644 --- a/inventory-manager.lic +++ b/inventory-manager.lic @@ -2,7 +2,7 @@ Documentation: https://elanthipedia.play.net/Lich_script_repository#inventory-manager =end -custom_require.call(%w[common]) +custom_require.call(%w[common common-items]) class InventoryManager def initialize @@ -15,14 +15,17 @@ class InventoryManager { name: 'desc', regex: /\w+/i, optional: true, description: "Optional specific count by description. Use quotes for multiple word strings, i.e., \"purple pouch\"." } ], [ - { name: 'save', regex: /save/i, description: "Save new or update current character's items to the database." }, { name: 'vault_book', regex: /vault_book/i, optional: true, description: "Retrieves, reads, and save from vault book." }, { name: 'vault_regular', regex: /vault_regular/i, optional: true, description: "Rummages your vault to save items NOTE: must be standing by your open vault." }, { name: 'storage_box', regex: /storage_box/i, optional: true, description: "Rummages caravan storage box for items." }, { name: 'family_vault', regex: /family_vault/i, optional: true, description: "Rummages your family vault to save items NOTE: must be standing by your open vault." }, { name: 'register', regex: /register/i, optional: true, description: "Reads contents of deed register." }, - { name: 'eddy', regex: /eddy/i, optional: true, description: "Save the contents of an eddy (HE 436 Gift)." } + { name: 'eddy', regex: /eddy/i, optional: true, description: "Save the contents of an eddy (HE 436 Gift)." }, + { name: 'scrolls', regex: /scrolls/i, optional: true, description: "Save spell scrolls tracked with sort-scrolls or stack-scrolls." }, + { name: 'home', regex: /home/i, optional: true, description: "Save home inventory." }, + { name: 'servant', regex: /servant/i, optional: true, description: "Save shadow servant inventory." }, + { name: 'shop', regex: /shop/i, optional: true, description: "Save your Trader shop inventory." } ], [ { name: 'search', regex: /search/i, description: 'Start a search across all characters for specified item.' }, @@ -39,6 +42,8 @@ class InventoryManager ] args = parse_args(arg_definitions) + @settings = get_settings + @inventory_ignores = @settings.inventory_manager_ignores setup @@ -51,9 +56,18 @@ class InventoryManager elsif args.register add_register_inv elsif args.eddy + DRC.message('*WARNING: Character inventory includes items found within Eddy. Using both will duplicate Eddy items.') add_eddy_inv elsif args.storage_box add_storage_box_inv + elsif args.scrolls + add_scrolls + elsif args.home + add_home + elsif args.servant + add_shadow_servant + elsif args.shop + add_trader_shop elsif args.save add_current_inv elsif args.count @@ -65,7 +79,7 @@ class InventoryManager elsif args.list list_character_inv(args.name) else - DRC.message 'Type ;inventory-manager help for a usage guide' + DRC.message('Type ;inventory-manager help for a usage guide') end end @@ -78,300 +92,361 @@ class InventoryManager end if !File.exist?(@item_db_path) - DRC.message "Something very wrong is occuring. You don't have a file to open and I can't create one!" - DRC.message "item-db saves the file to: /lich/scripts/itemDB/inventory.yaml" + DRC.message("Something very wrong is occuring. You don't have a file to open and I can't create one!") + DRC.message("item-db saves the file to: /lich/scripts/itemDB/inventory.yaml") exit end @item_data = OpenStruct.new(YAML.load_file(@item_db_path)).to_h + + # The legacy version of this script posted character inventory without an identifier. + # Adding a version check and 'upgrade' mechanism to fix these entries, otherwise they would exist + # forever unless the entire character was deleted. + @version_string = 'version'.to_sym + + version = @item_data[@version_string][0] + + if version != '2.00' + @item_data.each do |_k, v| + v.each { |item| + next if valid_data_row(item) + + item.concat(" (character)") + } + end + @item_data[@version_string] = ['2.00'] + File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml(line_width: -1)) } + end + end + + def valid_data_row(item) + if item.include?('(vault)') || item.include?('(register)') || item.include?('(eddy)') || item.include?('(caravan_box)') || item.include?('(Family)') + true + else + false + end + end + + def get_item_data(inventory_type) + if @item_data[@active_character] + @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? "(#{inventory_type})" } + else + @item_data[@active_character] = [] + end + end + + def save_item_data(inventory_type) + DRC.message("Saving #{inventory_type} data for #{@active_character}!") + # .to_yaml limits to 80 chars by default, line_width: -1 bypasses this limit + File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml(line_width: -1)) } end def get_inv_count(desc) count, closed = 0, 0 - # Counting all items in inventory if desc.nil? - DRC.bput('inv list', 'You have:') - while (line = get) - break if line =~ /INVENTORY HELP/i - + # Counting all items in inventory + capture = Lich::Util.issue_command('inv list', /^You have:/) + capture.each do |line| item = line.lstrip + + next if item.empty? + next if item.start_with?(*@inventory_ignores) + count += 1 closed += 1 if item.match?(/(closed)/) end - DRC.message "You have #{count} items, #{closed} of which are (closed) containers." + DRC.message("You have #{count} items, #{closed} of which are (closed) containers.") else # Counting items matching the description, i.e., inv count pouch - DRC.bput("inv search #{desc}", 'You rummage') - while (line = get) - break if line =~ /INVENTORY HELP/i + capture = Lich::Util.issue_command("inv search #{desc}", /rummage about your person/) + capture.each do |line| + item = line.lstrip + + next if item.empty? + next if item.start_with?(*@inventory_ignores) count += 1 end - DRC.message "You have #{count} items matching \"#{desc}\"." + DRC.message("You have #{count} items matching \"#{desc}\".") end end - def add_vault_book_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? 'vault' } - else - @item_data[@active_character] = [] + def check_inventory(command, end_pattern, inventory_type, rummage_length = 0) + using_sorter = false + if Script.running?('sorter') + stop_script('sorter') + using_sorter = true end - unless DRCI.get_item_if_not_held?("vault book") - DRC.message "Unable to find your vault book, exiting!" - exit - end + get_item_data(inventory_type) - DRC.bput('read my vault book', 'Vault Inventory:') - while (line = get) - break if line =~ /The last note/i + capture = Lich::Util.issue_command(command, end_pattern) - item = line.lstrip.concat(' (vault)') - @item_data[@active_character] << item - end + lines = capture + # when rummaging, this block splits the items, including the last two that are split by and instead of a comma + if command.start_with?("rummage") + container = capture[0] + lines = container[rummage_length, container.length - (rummage_length + 1)].split(",") - DRCI.stow_item?("vault book") + last_item = lines.length - 1 - DRC.message("Saving vault data for #{@active_character}!") - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - end + last_two_items = lines[last_item].split(" and ") - def add_current_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| (line.include?('vault') || line.include?('eddy')) } - else - @item_data[@active_character] = [] + lines[last_item] = last_two_items[0] + lines[last_item + 1] = last_two_items[1] end - DRC.bput('inv list', 'You have:') - while (line = get) - break if line =~ /Roundtime/i - + container = "" + lines.each do |line| item = line.lstrip + + next if item.empty? + next if item.start_with?(*@inventory_ignores) + + # if the item starts with a -, it's in a container if item[0].eql? '-' item[0] = '' - item.concat(' (in container)') - else + item.concat(" (in container - #{container})") + elsif inventory_type == 'character' + # We don't want the inventory_type here as it's extra noise, so we do a .to_s so container doesn't get updated by changing item later + container = (item.include?("eddy") ? "eddy" : item).to_s item.concat(' (worn)') + elsif (command == 'read my vault book' || inventory_type == 'shadow_servant') + # When reading the vault book, items in a container are prefixed by 6 spaces + if line =~ /\s{6}(?:a|an|some) / + item.concat(" (in container - #{container})") + else + container = item.to_s + end + elsif inventory_type == 'home' + if !item.start_with?("Attached:") + item = clean_home_string(item) + container = item.to_s + else + item = clean_home_string(item) + item.concat(" (attached to #{container})") + end end + + item.concat(" (#{inventory_type})") + @item_data[@active_character] << item end - DRC.message "Saving inventory data for #{@active_character}!" - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - end + save_item_data(inventory_type) - def add_register_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? 'register' } - else - @item_data[@active_character] = [] + if using_sorter + start_script('sorter') unless Script.running?('sorter') end + end + + def clean_home_string(string) + # We remove the category by finding the : in the string, plus drop the period at the end + colon = string.index(":") + 2 + string[colon..-2] + end - case DRC.bput("get my register", 'You get', 'What were', 'You are already holding that') - when 'What were' - DRC.message "Unable to find your register, exiting!" + def add_vault_book_inv + unless DRCI.get_item_if_not_held?("vault book") + DRC.message("Unable to find your vault book, exiting!") exit end - DRC.bput("turn my register to contents", 'You flip your deed register', 'already at the table of contents') + check_inventory("read my vault book", /^Vault Inventory:/, 'vault') - case DRC.bput("read my register", 'Stored Deeds', 'stored any deeds in this register') - when 'stored any deeds in this register' - exit - when 'Stored Deeds' - while (line = get) - break if line =~ /Currently stored/i + DRCI.stow_item?("vault book") + end - item = line.lstrip.concat(' (register)') - @item_data[@active_character] << item - end + def add_current_inv + check_inventory("inv list", /^You have:/, 'character') + end + + def add_register_inv + unless DRCI.get_item_if_not_held?("register") + DRC.message("Unable to find your register, exiting!") + exit end - DRC.bput('stow my register', 'You put') + DRC.bput("turn my register to contents", 'You flip your deed register', 'already at the table of contents') + + check_inventory("read my register", /^Stored Deeds:/, 'register') - DRC.message "Saving register data for #{@active_character}!" - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } + DRCI.stow_item?("register") end def add_eddy_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? 'eddy' } - else - @item_data[@active_character] = [] - end + checkInventory("inv eddy", /^Inside a/, 'eddy') + end - using_sorter = false - if Script.running?('sorter') - stop_script('sorter') - using_sorter = true - end + def add_storage_box_inv + check_inventory("rummage storage boc", /^You rummage through a storage box/, 'caravan_box', 41) + end - item_list = DRC.bput('look in my watery portal', /In the swirling eddy .*/i, 'What were') - .slice!("In the swirling eddy you see") - .split(",") - item_list.each_with_index do |item, itr| - if itr < item_list.length - 1 - @item_data[@active_character] << item.lstrip.concat(' (eddy)') - else - item.split("and") - .each do |item2| - @item_data[@active_character] << item2.strip.concat(" (eddy)").tr('.', '') - end - end - end + def add_family_vault + check_inventory("rummage vault", /^You rummage through a secure vault/, 'Family', 42) + end - DRC.message "Saving eddy data for #{@active_character}!" - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - if using_sorter - start_script('sorter') unless Script.running?('sorter') - end + def add_vault_regular_inv + check_inventory("rummage vault", /^You rummage through a secure vault/, 'vault', 42) end - def add_storage_box_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? 'caravan_box' } - else - @item_data[@active_character] = [] + def add_scrolls + stacker_container = (@settings.scroll_sorter['stacker_container'] || @settings.stacker_container) + unless stacker_container + DRC.message("You have no stacker_container defined for sort-scrolls or stack-scrolls!") + exit end - using_sorter = false - if Script.running?('sorter') - stop_script('sorter') - using_sorter = true - end + get_item_data('spell_scroll') - item_list = DRC.bput('rummage storage box', /through a storage box and see .*/i, 'What were') - .slice!("You rummage through a storage box and see") - .split(",") - item_list.each_with_index do |item, itr| - if itr < item_list.length - 1 - @item_data[@active_character] << item.lstrip.concat(' (caravan_box)') - else - item.split("and") - .each do |item2| - @item_data[@active_character] << item2.strip.concat(" (caravan_box)").tr('.', '') - end + stacker = @settings.scroll_sorter['stacker'] + scroll_stackers = @settings.scroll_stackers + + DRCI.open_container?("my #{stacker_container}") + + spells = [] + + if stacker + # stacker is defined, so they're using sort-scrolls - get all ten books and parse them + 10.times do + DRCI.get_item_safe?("tenth #{stacker}", stacker_container) + spells.concat(check_scroll_stacker(stacker)) + DRCI.put_away_item?(stacker, stacker_container) + end + else + # no stacker variable, so they are using stack-scrolls. loop through their scroll stackers and parse them + scroll_stackers.each do |scroll_stacker| + DRCI.get_item_safe?(scroll_stacker, stacker_container) + spells.concat(check_scroll_stacker(scroll_stacker)) + DRCI.put_away_item?(scroll_stacker, stacker_container) end end - DRC.message("Saving caravan box data for #{@active_character}!") - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - if using_sorter - start_script('sorter') unless Script.running?('sorter') + spells.sort.each do |spell| + @item_data[@active_character] << spell end + + save_item_data('spell_scroll') + + DRCI.close_container?("my #{stacker_container}") if @settings.scroll_sorter['close_container'] end - def add_family_vault - if @item_data['Family'] - @item_data['Family'] = @item_data['Family'].select { |line| !line.include? 'Family' } - else - @item_data['Family'] = [] + def check_scroll_stacker(stacker) + spells = [] + capture = Lich::Util.issue_command("flip my #{stacker.split.last}", /^You flip through the #{stacker.split.last}, checking each section before closing it.$/) + capture.each do |line| + if line =~ /The (.+) section has (\d+)/ + spell = "#{Regexp.last_match(1)} (#{Regexp.last_match(2)})" + spell.concat(" (spell_scroll)") + spells << spell + end end + spells + end - using_sorter = false - if Script.running?('sorter') - stop_script('sorter') - using_sorter = true - end + def add_home + check_inventory("home recall", /^The home contains:/, 'home') + end - item_list = DRC.bput('rummage vault', /through a vault and see .*/i, 'What were') - .slice!("You rummage through a vault and see") - .split(",") - item_list.each_with_index do |item, itr| - if itr < item_list.length - 1 - @item_data['Family'] << item.lstrip.concat(' (Family)') - else - item.split("and") - .each do |item2| - @item_data['Family'] << item2.strip.concat(" (Family)").tr('.', '') - end - end + def add_shadow_servant + unless DRStats.moon_mage? + DRC.message("You're not a Moon Mage!") + exit end - DRC.message("Saving family vault data!") - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - if using_sorter - start_script('sorter') unless Script.running?('sorter') + unless DRRoom.npcs.include?('Servant') + DRC.message("Your Shadow Servant isn't present.") + exit end + + DRC.bput('prepare PG', 'You raise') + pause 3 + + check_inventory('cast servant', /^Within the belly/, 'shadow_servant') end - def add_vault_regular_inv - if @item_data[@active_character] - @item_data[@active_character] = @item_data[@active_character].select { |line| !line.include? 'vault' } - else - @item_data[@active_character] = [] + def add_trader_shop + unless DRStats.trader? + DRC.message("You're not a Trader!") + exit end - using_sorter = false - if Script.running?('sorter') - stop_script('sorter') - using_sorter = true + get_item_data('trader_shop') + + surfaces = Hash.new + capture = Lich::Util.issue_command("shop customer", /^The following items contain goods for sale:/) + capture.each do |line| + line = line.lstrip + + # this extracts the command from the shop surface and uses that to find what's on/in it + # because the surfaces aren't always just 'a glass table' (ex: a knotted flax cargo net) + # command looks like shop #123456789 + if line =~ /^(.*?)<\/d>/ + surfaces[Regexp.last_match(2)] = Regexp.last_match(1) + end end - item_list = DRC.bput('rummage vault', /through a secure vault and see .*/i, 'What were') - .slice!("You rummage through a secure vault and see") - .split(",") - item_list.each_with_index do |item, itr| - if itr < item_list.length - 1 - @item_data[@active_character] << item.lstrip.concat(' (vault)') - else - item.split("and") - .each do |item2| - @item_data[@active_character] << item2.strip.concat(" (vault)").tr('.', '') + surfaces.each do |surface| + capture = Lich::Util.issue_command(surface[1], /, you see:/) + capture.each do |line| + line = line.lstrip + + if line =~ /^(.*?)<\/d>/ + @item_data[@active_character] << "#{Regexp.last_match(2)} (#{surface[0]}) (trader_shop)" end end end - DRC.message("Saving vault data for #{@active_character}!") - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - if using_sorter - start_script('sorter') unless Script.running?('sorter') - end + save_item_data('trader_shop') end def list_character_inv(name) if name.nil? - DRC.message "There is inventory data for:" + DRC.message("There is inventory data for:") @item_data.each do |k, v| + next if k == @version_string + inv_count = 0 v.each do |_data| inv_count += 1 end - DRC.message "#{k} - #{inv_count}" + DRC.message("#{k} - #{inv_count}") end return end name_sym = name.capitalize.to_sym if @item_data.has_key?(name_sym) - DRC.message "Inventory for #{name.capitalize}" - @item_data[name_sym].each { |item| DRC.message " - #{item}" } + DRC.message("Inventory for #{name.capitalize}") + @item_data[name_sym].each { |item| DRC.message(" - #{item}") } else - DRC.message "No data found for the character #{name.capitalize}!" + DRC.message("No data found for the character #{name.capitalize}!") end end def search_for_item(item) total_found = 0 @item_data.each do |k, v| + next if k == @version_string + total_found = 0 - DRC.message "Checking #{k}:" + DRC.message("Checking #{k}:") v.each { |data| if data.downcase.include?(item) total_found += 1 - DRC.message "Match #{total_found}): #{data}" + DRC.message("Match #{total_found}): #{data}") end } - DRC.message "Found #{total_found} matches on #{k}\n" + DRC.message("Found #{total_found} match#{(total_found > 1 ? 'es' : '')} on #{k}\n") end end - def remove_character_data(name) - @item_data.delete(name.capitalize.to_sym) - File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml) } - DRC.message "Removed #{name.capitalize}'s data!" + def remove_character_data(name_to_remove) + return if name_to_remove == "version" + + @item_data.delete(name_to_remove.capitalize.to_sym) + File.open(@item_db_path, 'w') { |file| file.write(@item_data.to_yaml(line_width: -1)) } + DRC.message("Removed #{name_to_remove.capitalize}'s data!") end end diff --git a/pick.lic b/pick.lic index c7207e98ac..f6c1c13021 100644 --- a/pick.lic +++ b/pick.lic @@ -415,7 +415,11 @@ class Pick def try_unlock_box_with_key(box) return unless @settings.use_skeleton_key - return unless DRCI.get_item_if_not_held?(@settings.skeleton_key) + + unless DRCI.get_item_if_not_held?(@settings.skeleton_key) + echo("Couldn't get skeleton key. Exiting.") + exit + end result = DRC.bput("turn my #{@settings.skeleton_key} at my #{box['noun']}", "^You turn", "that doesn't seem to do much", "I could not find", "What were you referring") waitrt? diff --git a/profiles/base-empty.yaml b/profiles/base-empty.yaml index c1746a6385..2a4f750e55 100644 --- a/profiles/base-empty.yaml +++ b/profiles/base-empty.yaml @@ -62,6 +62,7 @@ empty_values: hunting_info: [] hunting_nemesis: [] ignored_npcs: [] + inventory_manager_ignores: [] lichbot_buffs: [] listen_skills: [] lockpick_buffs: {} diff --git a/profiles/base.yaml b/profiles/base.yaml index 16614e1b29..76ca006fcc 100644 --- a/profiles/base.yaml +++ b/profiles/base.yaml @@ -2178,6 +2178,31 @@ sorter: sort_look_items_command: true ignore_categories: lootables|trash +# https://elanthipedia.play.net/Lich_script_repository#inventory-manager +inventory_manager_ignores: + - '[' + - '<' + - 'Roundtime' + - 'You have' + - 'Vault Inventory' + - 'Done' + - 'The last note' + - 'a brass hook' + - 'a steel wire rack' + - 'a small shelf' + - 'a top drawer' + - 'a middle drawer' + - 'a bottom drawer' + - 'a large shelf' + - 'Inside a' + - 'Page' + - 'Stored Deeds' + - 'Currently store' + - 'Maximum:' + - 'The home contains' + - 'Within the belly' + - 'Your Servant is holding' + stabbity: # Settings for script card-collector, defines bag to draw cards from(fresh) and bag to store duplicates and your case (duplicates) diff --git a/remedy.lic b/remedy.lic index a51663e5bf..52620fec0a 100644 --- a/remedy.lic +++ b/remedy.lic @@ -15,6 +15,8 @@ class Remedy @belt = @settings.alchemy_belt @training_spells = @settings.crafting_training_spells @stock = get_data('crafting')['remedies'][@settings.hometown] + @stamp = @settings.mark_crafted_goods + @cube = @settings.cube_armor_piece arg_definitions = [ [ @@ -177,6 +179,8 @@ class Remedy DRCC.stow_crafting_item("remed book", @bag, @forging_belt) end + DRC.bput("touch my #{@cube}", /^Warm vapor swirls around your head in a misty halo/, /^A thin cloud of vapor manifests with no particular effect./, /^Touch what/) if @cube + if ('red flower').include?(@herb1) @herb1 = 'dried flower' unless DRCI.exists?('red flower') elsif ('blue flower').include?(@herb1) @@ -397,11 +401,18 @@ class Remedy DRC.bput('release symb', "But you haven't", 'You release', 'Repeat this command') end + def stamp_item(noun) + DRCC.get_crafting_item('stamp', @bag, @bag_items, @belt) + DRC.bput("mark my #{noun} with my stamp", 'carefully hammer the stamp', 'You cannot figure out how to do that', 'too badly damaged', /score the surface with the stamp/) + DRCC.stow_crafting_item('stamp', @bag, @belt) + end + def finish waitrt? stow_item(DRC.left_hand) fput("get my #{@noun} from my #{@container}") stow_item(DRC.right_hand) + stamp_item(@noun) if @stamp magic_cleanup exit end diff --git a/validate.lic b/validate.lic index 560ea4c0c0..08d99675bd 100644 --- a/validate.lic +++ b/validate.lic @@ -17,13 +17,6 @@ class DRYamlValidator setup_data - if $manager.developer - respond("") - echo "**WARNING**: You are on developer or dev mode. That suggests you are a developer." - echo "**WARNING**: If you are on dev mode, you should be capable of solving most issues yourself." - echo "**WARNING**: Support by Lich contributors will be limited or declined." - end - respond("") respond(" CHECKING: That #{checkname}-setup.yaml exists in the proper folder.") if profiles.grep(/#{checkname}-setup/).empty?