diff --git a/go2.lic b/go2.lic index 95277dd4ce..e1668b9687 100644 --- a/go2.lic +++ b/go2.lic @@ -7,25 +7,89 @@ author: Tillmen (tillmen@lichproject.org) original author: Shaelun + contributors: Deysh, Doug, Gildaren, Sarvatt, Tysong, Xanlin game: any tags: core, movement - version: 1.37 - required: Lich >= 4.6.14 + version: 2.1.8 + required: Lich >= 5.4.1 changelog: - 1.37 (2024-05-03) - Removing personal wayto overrides, as that functionality has moved to dependency.lic - 1.36 (2024-03-03) - Re-supporting the ability to use spaces in custom go2 locations. - 1.35 (2023-02-04) - Add support for custom named targets with an array of roomnumbers. Finds nearest. - 1.34 (2022-11-26) - Add support to "goback" to the room go2 last started in. - 1.33 (2022-04-20): + 2.1.8 (2024-11-03): + Ungate hide_room_descriptions and hide_room_titles for DR + 2.1.7 (2024-09-19): + Additional stand messaging + 2.1.6 (2024-09-11) + Bugfix for use_portal variable when using GUI Needed to be on/off instead of true/false + 2.1.5 (2024-07-18): + Additional stand messaging + 2.1.4 (2024-07-17): + Additional stand messaging + 2.1.3 (2024-07-13): + Additional stand messaging + 2.1.2 (2024-07-01): + Fix for urchin usage when mounted + Add output info if muckled? to know why go2 is paused + 2.1.1 (2024-06-23): + Bugfix to custom targets to respect non-arrays + 2.1.0 (2024-05-02): + Merge DR go2 code into EO + Add support for custom target arrays + UI changes to be game specific + 2.0.12 (2024-04-22): + Add initial basic support for usage while mounted + Change Char.prof to Stats.prof + 2.0.11 (2024-01-05): + Fix for version constant and showing properly via setup/help/list output + Rubocop cleanup + 2.0.10 (2023-09-21): + Bugfix for matching change in wealth output. + 2.0.9 (2023-07-05): Xanlin: + Fix for permanent urchin guide access. Rubocop cleanup. + 2.0.8 (2023-03-03): Tysong: + bugfix for integer comparison to string for Society + 2.0.7 (2023-03-03): Xanlin: + navigate out of a playershop even if it's not mapped (GS only) + 2.0.6 (2023-02-09): Rinualdo + Added targets list for portmaster, grocer, cobbling and treasuremaster + 2.0.5 (2022-11-29): Tysong + Fix for variable name syntax + 2.0.4 (2022-11-28): Gildaren: + Add support to "goback" to the room go2 last started in + 2.0.3 (2022-11-22): Mahtra: + adjusted DR/GS separattion of features Support for yaml-based map timeto and stringproc overrides - Only overrides `wayto` and/or `timeto` if that option specified in yaml - 1.32 (2022-03-22): + 2.0.2 (2022-10-20): Xanlin: + adjusted wait before exiting + 2.0.1 (2022-10-08) + bug fix for non-Gtk users + backward compatibility for Lich4 + 2.0 (2022-10-08): Deysh: + added setup gui + added color options to help output +=end +=begin + 1.37 (2022-10-07): Xanlin: + added option to hide room descriptions for travel + added option to hide room titles for travel + added option to echo input + added fallback for check_silvers that uses wealth quiet instead + wrap in module + travel time now calculated to a higher precision. + targets town name now based on location. + targets won't include towns tagged closed. + 1.36.0 (2022-06-16): + fix for urchins runners not recognized as command option + add sos caravan options. + 1.35 (2022-05-12): + exit if get-silvers fails to get enough silver from bank. + 1.34 (2022-03-31): For DR: add support for yaml-based map stringproc overrides + 1.33 (2022-03-31): + set UserVars.mapdb_urchins_expire to 0 when expired to fix comparison with nil + 1.32 (2022-03-31): + Added setting --use-portmasters for UserVars.mapdb_use_portmasters + Added setting --use-urchins for UserVars.mapdb_use_urchins + Added location and uid to output list for multiple matched destinations 1.31 (2022-03-10): Merged in DR changes from v1.22f by Sarvatt 1.30 (2022-03-03): @@ -43,8 +107,6 @@ Fix DragonRealms auto drag feature (Sarvatt) 1.24 (2019-03-03): Updated formatting for ";go2 list" in GSPlat and GSF -=end -=begin 1.23 (2019-03-03): add setting for using GSPlat old portal system 1.22 (2019-02-10): @@ -99,1228 +161,1940 @@ # fixme: don't do puzzles option -setting_value = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } -previous = shortest_distances = nil - -CharSettings['typeahead'] = 0 if CharSettings['typeahead'].nil? -CharSettings['vaalor shortcut'] = false if CharSettings['vaalor shortcut'].nil? -CharSettings['get silvers'] = false if CharSettings['get silvers'].nil? -CharSettings['delay'] = 0 if CharSettings['delay'].nil? -CharSettings['stop for dead'] = false if CharSettings['stop for dead'].nil? - -show_help = proc { - output = "\n" - output.concat " #{$clean_lich_char}#{script.name} Takes you where you want to go using your saved options.\n" - output.concat " #{$clean_lich_char}#{script.name} goback Takes you back to the room your last #{script.name} started in.\n" - output.concat " #{$clean_lich_char}#{script.name} Takes you where you want to go, using the given options\n" - output.concat " #{''.rjust($clean_lich_char.length + script.name.length)} instead of your saved options.\n" - output.concat " #{$clean_lich_char}#{script.name} Saves the given options.\n" - output.concat "\n" - output.concat " target:\n" - output.concat "\n" - output.concat " may be a room number, a custom target, a built-in target,\n" - output.concat " or part of a room title or room description.\n" - output.concat "\n" - output.concat " options:\n" - output.concat "\n" - output.concat " --typeahead=<#> Sets the number of typeahead lines to use.\n" - output.concat " --delay=<#> Sets the delay in seconds between movements\n" - output.concat " (disables typeahead).\n" - if XMLData.game =~ /^GS/ - output.concat " --get-silvers= Sets if #{script.name} has permission to access your bank\n" - output.concat " account.\n" - output.concat " --get-return-trip-silvers= Sets if #{script.name} should withdraw enough silvers to\n" - output.concat " return from your destination room to your starting room.\n" - output.concat " --ice-mode= Sets how #{script.name} should deal with rooms that make\n" - output.concat " you slip and fall.\n" - output.concat " --stop-for-dead= Pauses the script if you pass a dead person.\n" - output.concat " --shortcut= Sets if the shortcut to Ta'Vaalor should be used.\n" - output.concat " (climbing and/or simming needed)\n" - output.concat " --use-seeking= Sets if #{script.name} should use Voln symbol of seeking\n" - output.concat " when it will shorten your trip.\n" - output.concat " --use-day-pass= Use a Chronomage day pass to travel between towns in the\n" - output.concat " same zone if you have one.\n" - output.concat " --buy-day-pass= Buy a Chronomage day pass if you don't have an unexpired\n" - output.concat " one. get-silvers will also need to be turned on if you\n" - output.concat " want to buy one without gold ring credits. If you only\n" - output.concat " want to buy passes for certain locations, specify the\n" - output.concat " locations like so:\n" - output.concat " ;go2 --buy-day-pass=wl,imt;imt,wl;imt,sol;ill,val;ill,cys\n" - output.concat " --day-pass-container= Sets the container where you keep your day passes\n" - output.concat " --instability= Use the instability at the given room number to get into\n" - output.concat " the Elementla Confluence instead of finding an attuned one.\n" - output.concat " --fwi-trinket= Use a FWI trinket to get to/from FWI\n" - output.concat " --fwi-trinket=off Stop using a FWI trinket\n" - elsif XMLData.game =~ /^DR/ - output.concat " --drag= Attempt to automatically drag someone to your destination\n" - output.concat " (this probably won't work)\n" - end - if XMLData.game =~ /^GSPlat|^GSF/ - output.concat " --portals= Sets if portals should be used.\n" - end - if XMLData.game =~ /^GSPlat/ - output.concat " --old-portals= Sets if old (dangerous) portals should be used.\n" - output.concat " --portal-pass= Turn this on if you have a wearable portal pass and don't\n" - output.concat " need a portal ticket.\n" - end - output.concat "\n" - output.concat " other commands:\n" - output.concat "\n" - output.concat " #{$clean_lich_char}#{script.name} save = Saves a custom target. can be the same\n" - output.concat " #{$clean_lich_char}#{script.name} save =[123, 456, 789] as before, or \"current\" for your current room.\n" - output.concat " #{''.rjust($clean_lich_char.length + script.name.length)} Can also be an array of rooms, separated by commas.\n" - output.concat " #{''.rjust($clean_lich_char.length + script.name.length)} If the target exists, will append the room to array.\n" - output.concat " #{$clean_lich_char}#{script.name} delete Deletes a saved custom target.\n" - output.concat " #{$clean_lich_char}#{script.name} list Shows your settings and custom targets.\n" - output.concat " #{$clean_lich_char}#{script.name} targets Shows the built-in targets.\n" - output.concat "\n" - respond output -} - -change_map_vaalor_shortcut = proc { |use_shortcut| - unless Map.list.any? { |room| room.timeto.any? { |adj_id,time| time.class == Proc and time._dump =~ /$go2_use_vaalor_shortcut/ } } +module Go2 + @@data ||= nil + @@mounted = false + + def self.mounted + @@mounted + end + + def self.mounted=(value) + @@mounted = value + end + + def self.get_script_version + data = Script.list.find { |x| x.name == 'go2' }.inspect + return data[/version: (\d+\.\d+\.\d+)/i, 1] + end + + def self.data + @@data + end + + def self.color(color, msg) + if defined?(Lich::Messaging) + Lich::Messaging.msg_format(color, msg) + else + msg + end + end + + def self.wealth_quiet(); + wealth_pattern = /^You have (no|[,\d]+|but one) silver with you/; + wealth = dothistimeout 'wealth quiet', 3, wealth_pattern; + coins = 0; + if wealth.gsub('but one', '1') =~ wealth_pattern; + coins = $1.gsub(',', '').to_i; + end; + return coins; + end; + + def self.go2_check_silver; + if LICH_VERSION.split('.')[0].to_i < 5 or !defined?(Lich::Util.silver_count) + return self.wealth_quiet + else + return Lich::Util.silver_count + end + end + + def self.load_go2_settings() + if UserVars.mapdb_buy_day_pass == true + buy_pass = "on" + elsif UserVars.mapdb_buy_day_pass == false + buy_pass = "off" + else + buy_pass = UserVars.mapdb_buy_day_pass + end + + use_portals = UserVars.mapdb_use_portals == 'yes' ? true : false + + settings_hash = { + :mapdb_car_to_sos => UserVars.mapdb_car_to_sos, + :mapdb_car_from_sos => UserVars.mapdb_car_from_sos, + :mapdb_use_portals => use_portals, + :mapdb_use_old_portals => UserVars.mapdb_use_old_portals, + :mapdb_use_urchins => UserVars.mapdb_use_urchins, + :mapdb_use_portmasters => UserVars.mapdb_use_portmasters, + :mapdb_use_day_pass => UserVars.mapdb_use_day_pass, + :mapdb_buy_day_pass => buy_pass, + :mapdb_day_pass_sack => UserVars.day_pass_sack, + :mapdb_ice_mode => UserVars.mapdb_ice_mode, + :mapdb_fwi_trinket => UserVars.mapdb_fwi_trinket, + :rogue_password => UserVars.rogue_password, + :delay => CharSettings['delay'], + :typeahead => CharSettings['typeahead'], + :stop_for_dead => CharSettings['stop for dead'], + :get_silvers => CharSettings['get silvers'], + :get_return_silvers => CharSettings['get return trip silvers'], + :use_vaalor_shortcut => CharSettings['vaalor shortcut'], + :use_seeking => CharSettings['use seeking'], + :echo_input => CharSettings['echo_input'], + :hide_room_desc => CharSettings['hide_room_descriptions'], + :hide_room_titles => CharSettings['hide_room_titles'], + } + settings_hash + end + + def self.load(settings) + @@data = settings + end + + def self.save_go2_settings(settings) + UserVars.mapdb_car_to_sos = settings[:mapdb_car_to_sos] + UserVars.mapdb_car_from_sos = settings[:mapdb_car_from_sos] + UserVars.mapdb_use_old_portals = settings[:mapdb_use_old_portals] + UserVars.mapdb_use_urchins = settings[:mapdb_use_urchins] + UserVars.mapdb_use_portmasters = settings[:mapdb_use_portmasters] + UserVars.mapdb_use_day_pass = settings[:mapdb_use_day_pass] + UserVars.day_pass_sack = settings[:mapdb_day_pass_sack] + UserVars.mapdb_ice_mode = settings[:mapdb_ice_mode] + + UserVars.mapdb_use_portals = settings[:mapdb_use_portals] ? 'yes' : 'no' + + if settings[:mapdb_buy_day_pass].empty? || settings[:mapdb_buy_day_pass] =~ /off|no|false/ + UserVars.mapdb_buy_day_pass = nil + elsif settings[:mapdb_buy_day_pass] =~ /on|true|yes/ + UserVars.mapdb_buy_day_pass = true + else + settings[:mapdb_buy_day_pass].split(';').each { |location| + if location !~ /^\s*(?:wl,imt|imt,wl|wl,sol|sol,wl|imt,sol|ill,val|val,ill|ill,cys|cys,ill|val,cys|cys,val)\s*$/i + echo "warning: Location #{location} is invalid. Using it anyway." + end + } + + UserVars.mapdb_buy_day_pass = settings[:mapdb_buy_day_pass] + end + + if settings[:mapdb_fwi_trinket].empty? || UserVars.mapdb_fwi_trinket =~ /^off$/i + UserVars.mapdb_fwi_trinket = nil + else + UserVars.mapdb_fwi_trinket = settings[:mapdb_fwi_trinket] + end + + UserVars.rogue_password = settings[:rogue_password] + CharSettings['delay'] = settings[:delay] + CharSettings['typeahead'] = settings[:typeahead] + CharSettings['stop for dead'] = settings[:stop_for_dead] + CharSettings['get silvers'] = settings[:get_silvers] + CharSettings['get return trip silvers'] = settings[:get_return_silvers] + CharSettings['vaalor shortcut'] = settings[:use_vaalor_shortcut] + CharSettings['use seeking'] = settings[:use_seeking] + CharSettings['echo_input'] = settings[:echo_input] + CharSettings['hide_room_descriptions'] = settings[:hide_room_desc] + CharSettings['hide_room_titles'] = settings[:hide_room_titles] + end + + if defined?(Gtk) + # Setup is an extension of Gtk::Builder for Gtk setup + class Setup < Gtk::Builder + attr_accessor :settings + + @@categories = { + general: { + mapdb_car_to_sos: { default: false }, + mapdb_car_from_sos: { default: false }, + mapdb_ice_mode: { default: false }, + mapdb_use_urchins: { default: false }, + mapdb_use_portmasters: { default: false }, + mapdb_use_day_pass: { default: false }, + mapdb_buy_day_pass: { default: '' }, + mapdb_day_pass_sack: { default: '' }, + mapdb_fwi_trinket: { default: '' }, + mapdb_use_portals: { default: false }, + mapdb_use_old_portals: { default: false }, + typeahead: { default: 0 }, + delay: { default: 0 }, + use_vaalor_shortcut: { default: false }, + get_silvers: { default: false }, + get_return_silvers: { default: false }, + hide_room_desc: { default: false }, + hide_room_titles: { default: false }, + echo_input: { default: true }, + use_seeking: { default: false }, + stop_for_dead: { default: false }, + rogue_password: { default: '' }, + } + } + + def self.get_category(key) + @@categories.each { |category, data| return category unless data[key].nil? } + nil + end + + def self.get_setting(key) + cat = Setup.get_category(key) + return nil if cat.nil? + @@categories[cat].each { |setting, data| return data if setting == key } + nil + end + + def initialize(settings) + super() + @settings = settings + # set default values if they don't exist + @@categories.each do |_, data| + data.each { |key, value| @settings[key] = value[:default] if @settings[key].nil? } + end + # remove settings that doesn't exist + @settings.delete_if { |key, _| next Setup.get_category(key).nil? } + # use a GTK Builder to setup all the basics of the window then expand on that base + return unless defined?(Gtk) && Gtk::Version::MAJOR == 3 + Gtk.queue do + # add_from_file("#{$data_dir}go2.ui") + add_from_string(Setup.go2_ui) + load_settings + self['main'].keep_above = true + self['main'].set_title "Go2 Setup v#{Go2.get_script_version}" + # connect signals after settings are loaded to a bunch of handlers don't trigger + connect_signals { |handler| method(handler) } + end + end + + def self.go2_ui + '600110100110 + FalseGo2 SetupTrueFalsevertical5TrueTrueTrueTrueTrueTrueinTrueFalseTrueFalseverticalTrueFalse100TrueFalse5555Use SeekingTrueTrueFalsestart106True + 20TrueFalseendType Ahead 30TrueTruestarttype_ahead_adjustmentTrue-0.021999999999999999 + 40Use UrchinsTrueTrueFalsestart107True + 12TrueTruestart0delay_adjustmentTrue41 + TrueFalseendDelay31Use PortmastersTrueTrueFalsestart107True + 13Get SilversTrueTrueFalsestart107True + 00Get Return SilversTrueTrueFalsestart107True + 01Hide Room DescTrueTrueFalsestart107True + 02Hide Room TitlesTrueTrueFalsestart107True + 03Stop for DeadTrueTrueFalsestart106True + 21Use Vaalor ShortcutTrueTrueFalsestart106True + 22Echo InputTrueTrueFalsestart106True + 23TrueFalseendIce Mode32TrueFalsestart0TrueAutoOnOff + False42TrueFalseendRogue Password33 + TrueTruestart47pull, push,tap...whatever. There should be 7 actions43Caravan from SoSTrueTrueFalsestart107True + 11Caravan to SoSTrueTrueFalsestart107True + 10TrueFalseMiscFalseTrue0TrueFalse100TrueFalse5555TrueFalseend13FWI Trinket + 00TrueTruestart47name of FWI trinket or \'off\' to stop using it10 + Use Portals (Plat and Shattered Only)TrueTrueFalsestart107True012 + Use Old Portals (Plat Only)TrueTrueFalsestart107True022 + Use Day PassTrueTrueFalsestart157True202 + TrueFalseend19Day Pass Sack22TrueTruestart47 + 32TrueFalseend19Buy Day Pass21TrueTrueBuy a Chronomage day pass if you don\'t have an unexpired one. Get Silvers will also need to be turned on if you want to buy one without gold ring credits. If you only want to buy passes for certain locations, specify the locations like so: wl,imt;imt,wl;imt,sol;ill,val;ill,cysstart47<on|off|locations> + 31TrueFalsePortals and PassesFalseTrue1TrueFalse100TrueFalse55105TrueFalsestart105Custom Targets cannot be done from the UI. Please use the command line + 00TrueFalsestart105Command line still functions for all options. See help for details.01 + TrueFalseNotesFalseTrue2TrueFalseGeneral + FalseFalseTrue0TrueFalseTrueFalse1055Changes are only saved if you use the Close button --> + FalseTrue0Close80TrueTrueTrueend1055True + FalseTrue1FalseTrueend1' + end + + # This is connected to automatically during load_settings and syncs data back to CharSettings. + def on_update(obj) + Gtk.queue do + key = obj.builder_name.to_sym + setting = Setup.get_setting(key) + return if setting.nil? + + if obj.class == Gtk::CheckButton + @settings[key] = obj.active? + elsif obj.class == Gtk::Entry + @settings[key] = obj.text.strip + elsif obj.class == Gtk::SpinButton + # update from text entry + obj.update + # force int, we don't use floats anywhere + @settings[key] = obj.adjustment.value.to_i + elsif obj.class == Gtk::ComboBoxText + @settings[key] = obj.active_text + end + end + end + + def on_close_clicked + Go2.load(@settings) + self['main'].destroy + end + + def on_destroy + Gtk.queue { + Go2.load(@settings) + @running = false + } + end + + # iterate all objects and for any that match a setting name directly we set the default + def load_settings + Gtk.queue do + # load up the generic settings which are just matching by name of the widget + objects.each do |obj| + next unless obj.methods.include?(:builder_name) + + key = obj.builder_name.to_sym + next if (setting = Setup.get_setting(key)).nil? + + # set the default value + obj.set_sensitive(false) if (obj.builder_name.to_s.eql?("mapdb_use_portals")) && XMLData.game !~ /^GSPlat|^GSF/ + obj.set_sensitive(false) if (obj.builder_name.to_s.eql?("mapdb_use_old_portals")) && XMLData.game !~ /^GSPlat/ + obj.set_sensitive(false) if (obj.builder_name.to_s.eql?("rogue_password")) && Stats.prof != "Rogue" + obj.set_sensitive(false) if (obj.builder_name.to_s.eql?("use_seeking")) && Society.member !~ /Order of Voln/ && Society.rank.eql?(26) + + if obj.class == Gtk::CheckButton + obj.active = @settings[key] + obj.signal_connect('toggled') { on_update(obj) } + elsif obj.class == Gtk::Entry + obj.text = @settings[key].strip + obj.signal_connect('changed') { on_update(obj) } + elsif obj.class == Gtk::SpinButton + obj.value = @settings[key] + obj.adjustment.value = @settings[key] + obj.signal_connect('changed') { on_update(obj) } + elsif obj.class == Gtk::ComboBoxText + # Fixme: change to builder_name + if @settings[key] == "Auto" + item = 0 + elsif @settings[key] == "On" + item = 1 + elsif @settings[key] == "Off" + item = 2 + elsif @settings[key] == "1" + item = 0 + elsif @settings[key] == "2" + item = 1 + end + + obj.set_active(item) if item + obj.signal_connect('changed') { on_update(obj) } + elsif obj.class == Gtk::TreeView + if (store = self["#{key}_store"]).nil? + respond "** failed to find store for treeview #{key}" + next + elsif setting[:load].nil? + respond "** no :load defined #{key}" + next + end + + setting[:load].call(store, @settings[key]) + + # setup the signals + if (add = self["#{key}_add"]).nil? + respond "** failed to find add for treeview #{key}" + next + elsif (delete = self["#{key}_delete"]).nil? + respond "** failed to find delete for treeview #{key}" + next + elsif (entry = self["#{key}_entry"]).nil? + respond "** failed to find entry for treeview #{key}" + next + end + + add.signal_connect('clicked') do + if setting[:set].nil? + respond "** no :set defined for #{key}" + next + elsif entry.text.empty? + next + end + setting[:set].call(store, entry.text, @settings[key]) + setting[:load].call(store, @settings[key]) + end + + delete.signal_connect('clicked') do + if setting[:delete].nil? + respond "** no :delete defined for #{key}" + next + elsif (selected = obj.selection.selected).nil? + next + end + setting[:delete].call(store, selected, @settings[key]) + setting[:load].call(store, @settings[key]) + end + end + end + + # checkboxes for array storage with id's : + # this is primarily used by the loot types + objects.each do |obj| + next unless obj.methods.include?(:builder_name) + next unless obj.builder_name =~ /^([^:]+):(.*)$/i + next unless obj.class == Gtk::CheckButton + + key = Regexp.last_match(1).to_sym + value = Regexp.last_match(2).to_s + # echo "key: #{key} value: #{value}" + next if Setup.get_setting(key).nil? + # echo @settings[key].include?(value) + obj.active = @settings[key].include?(value) + + # add in hook + obj.signal_connect('toggled') do + @settings[key].delete(value) + if obj.active? + @settings[key].push(value) + @settings[key].uniq!.sort! + end + end + end + end + end + + def start + @running = true + Gtk.queue { + main_width = XMLData.game =~ /^GS/ ? 840 : 450 + main_height = XMLData.game =~ /^GS/ ? 550 : 350 + self['main'].set_default_size(main_width, main_height) + + self['main'].show_all + + if XMLData.game =~ /^DR/ + # Hide non-DR elements if needed + hide_elements = [ + 'portals_passes_frame', + 'get_silvers', + 'get_return_silvers', + 'mapdb_car_to_sos', + 'mapdb_car_from_sos', + 'mapdb_use_urchins', + 'mapdb_use_portmasters', + 'use_seeking', + 'stop_for_dead', + 'use_vaalor_shortcut', + 'ice_mode_label', + 'mapdb_ice_mode', + 'rogue_password_label', + 'rogue_password' + ] + + hide_elements.each { |element| self[element].hide() } + + # Reposition remaining items + # Have to remove elements before repositioning + self['misc_grid'].remove(self['hide_room_desc']) + self['misc_grid'].remove(self['hide_room_titles']) + self['misc_grid'].remove(self['echo_input']) + + # Now reattach and reposition + self['misc_grid'].attach(self['hide_room_desc'], 0, 0, 1, 1) + self['hide_room_desc'].set_margin_top(5) + self['hide_room_desc'].set_margin_right(30) + + self['misc_grid'].attach(self['hide_room_titles'], 0, 1, 1, 1) + + self['misc_grid'].attach(self['echo_input'], 0, 2, 1, 1) + end + } + + wait_while { @running } + end + + def list(cat_to_list: 'all') + indent_size = 2 + print_array = + proc do |key, value, indent| + _respond("#{' ' * indent_size * indent.to_i}#{key}:") + value.sort!.each { |entry| _respond("#{' ' * indent_size * (indent.to_i + 1)}#{value.index(entry) + 1}. #{entry}") } + end + + print_value = proc { |key, value, indent| _respond("#{' ' * indent_size * indent.to_i}#{key}: #{value}") } + + categories = cat_to_list == 'all' ? %w[general internal] : [cat_to_list] + if $frontend == 'stormfront' + output = "\n" + else + output = String.new + end + categories.each do |opt| + _respond("#{output}") if !output.empty? + _respond("#{monsterbold_start}= #{opt.capitalize} =#{monsterbold_end}\n") + @@categories[opt.to_sym].each do |id, _| + value = @settings[id] + value.class == Array ? print_array.call(id, value, 1) : print_value.call(id, value, 1) + end + end + if $frontend == 'stormfront' + output = "\n" + _respond("#{output}") + end + end + + def self.update_setting(key, value) + setting = Setup.get_setting(key) + echo "** Setting #{key.inspect} does not exist" if setting.nil? + action = nil + + if value =~ /^([+-])(.*)$/ + action = Regexp.last_match(1) + value = Regexp.last_match(2).strip.downcase + end + + if value == 'reset' + @settings.delete(key) + echo " Reset #{key}" + elsif @settings[key].class == Array + if value =~ /\d/ && @settings[key][value.to_i] + @settings[key].delete_at(value.to_i) + else + @settings[key].delete(value) + end + + if action == '-' + echo " #{value.inspect} removed from #{key.inspect}" + else + @settings[key].push(value) + echo " #{value.inspect} added to #{key.inspect}" + end + + echo " #{key.inspect} is now #{@settings[key].join(', ').inspect}" + else + if @settings[key].class == FalseClass || @settings[key].class == TrueClass + value = value =~ /^true|1|yes|on/ ? true : false + elsif @settings[key].class == Integer + value = value.to_i + end + + echo "#{key.inspect} has been set to #{value.inspect}" + @settings[key] = value + end + end + end + + end + + setting_value = { 'on' => true, 'true' => true, 'yes' => true, 'off' => false, 'false' => false, 'no' => false } + previous = shortest_distances = nil + + if XMLData.game =~ /^GS/ + UserVars.mapdb_urchins_expire = 0 if UserVars.mapdb_urchins_expire.nil? + UserVars.mapdb_car_to_sos = false if UserVars.mapdb_car_to_sos.nil? + UserVars.mapdb_car_from_sos = false if UserVars.mapdb_car_from_sos.nil? + UserVars.mapdb_ice_mode = 'auto' if UserVars.mapdb_ice_mode.nil? + CharSettings['vaalor shortcut'] = false if CharSettings['vaalor shortcut'].nil? + CharSettings['get silvers'] = false if CharSettings['get silvers'].nil? + CharSettings['stop for dead'] = false if CharSettings['stop for dead'].nil? + end + CharSettings['typeahead'] = 0 if CharSettings['typeahead'].nil? + CharSettings['delay'] = 0 if CharSettings['delay'].nil? + CharSettings['hide_room_descriptions'] = false if CharSettings['hide_room_descriptions'].nil? + CharSettings['hide_room_titles'] = false if CharSettings['hide_room_titles'].nil? + CharSettings['echo_input'] = true if CharSettings['echo_input'].nil? + + show_help = proc { + output = [] + output << " Go2 v#{Go2.get_script_version}" + output << "" + output << " #{$lich_char}#{Script.current.name} Takes you where you want to go using your saved options." + output.<< " #{$lich_char}#{Script.current.name} goback Takes you back to the room your last #{Script.current.name} started in." + output << " #{$lich_char}#{Script.current.name} Takes you where you want to go, using the given options" + output << " #{' '.rjust($lich_char.length + Script.current.name.length)} instead of your saved options." + output << " #{$lich_char}#{Script.current.name} Saves the given options." + output << " #{$lich_char}#{Script.current.name} setup Brings up GUI for Lich5 users with most of the commands below" + output << "" + output << " target: " + output << " target may be a room number, a custom target, a built-in target," + output << " or part of a room title or room description." + output << "" + output << " options:" + output << " --typeahead=<#> Sets the number of typeahead lines to use." + output << " --delay=<#> Sets the delay in seconds between movements" + output << " (disables typeahead)." + output << " --echo_input= When 'on', echos the script input from when the script was called" + + if XMLData.game =~ /^GS/ + output << " --get-silvers= Sets if #{Script.current.name} has permission to access your bank" + output << " account." + output << " --get-return-trip-silvers= Sets if #{Script.current.name} should withdraw enough silvers to" + output << " return from your destination room to your starting room." + output << " --ice-mode= Sets how #{Script.current.name} should deal with rooms that make" + output << " you slip and fall." + output << " --stop-for-dead= Pauses the script if you pass a dead person." + output << " --shortcut= Sets if the shortcut to Ta'Vaalor should be used." + output << " (climbing and/or simming needed)" + output << " --use-seeking= Sets if #{Script.current.name} should use Voln symbol of seeking" + output << " when it will shorten your trip." + output << " --use-urchins= Sets if #{Script.current.name} should use urchin guides" + output << " when it will shorten your trip." + output << " --use-portmasters= Sets if #{Script.current.name} should use portmasters" + output << " when it will shorten your trip." + output << " --use-day-pass= Use a Chronomage day pass to travel between towns in the" + output << " same zone if you have one." + output << " --buy-day-pass= Buy a Chronomage day pass if you don't have an unexpired" + output << " one. get-silvers will also need to be turned on if you" + output << " want to buy one without gold ring credits. If you only" + output << " want to buy passes for certain locations, specify the" + output << " locations like so:" + output << " ;go2 --buy-day-pass=wl,imt;imt,wl;imt,sol;ill,val;ill,cys" + output << " --day-pass-container= Sets the container where you keep your day passes" + output << " --instability= Use the instability at the given room number to get into" + output << " the Elementla Confluence instead of finding an attuned one." + output << " --fwi-trinket= Use a FWI trinket to get to/from FWI" + output << " --fwi-trinket= Stop using a FWI trinket" + output << " --hide_room_descriptions= When 'on', turns room descriptions off for traveling" + output << " --hide_room_titles= When 'on', turns room titles off for traveling" + output << " --caravan-to-sos= Use the caravan to travel to the Sanctum of Scales" + output << " --caravan-from-sos= Use the caravan to travel back from the Sanctum of Scales" + elsif XMLData.game =~ /^DR/ + output << " --drag= Attempt to automatically drag someone to your destination" + output << " (this probably won't work)" + end + if XMLData.game =~ /^GSPlat|^GSF/ + output << " --portals= Sets if portals should be used." + end + if XMLData.game =~ /^GSPlat/ + output << " --old-portals= Sets if old (dangerous) portals should be used." + output << " --portal-pass= Turn this on if you have a wearable portal pass and don't" + output << " need a portal ticket." + end + output << "" + output << " other commands:" + output << "" + output << " #{$lich_char}#{Script.current.name} save new name= a custom target. target can be the same" + output << " #{''.rjust($lich_char.length + Script.current.name.length)} as before, or \"current\" for your current room" + output << " #{$lich_char}#{Script.current.name} delete custom target Deletes a saved custom target." + output << " #{$lich_char}#{Script.current.name} list Shows your settings and custom targets." + output << " #{$lich_char}#{Script.current.name} targets Shows the built-in targets." + output << "" + + respond output + } + + change_map_vaalor_shortcut = proc { |use_shortcut| + unless Map.list.any? { |room| room.timeto.any? { |_adj_id, time| time.class == Proc and time._dump =~ /$go2_use_vaalor_shortcut/ } } if use_shortcut - Room[16745].timeto['16746'] = 15 - Room[16746].timeto['16745'] = 15 + Room[16745].timeto['16746'] = 15 + Room[16746].timeto['16745'] = 15 else - Room[16745].timeto['16746'] = 15000 - Room[16746].timeto['16745'] = 15000 + Room[16745].timeto['16746'] = 15000 + Room[16746].timeto['16745'] = 15000 end - end -} + end + } -get_silver_cost = proc { |path| - cost = 0 - path.each_index { |index| + get_silver_cost = proc { |path| + cost = 0 + path.each_index { |index| Room[path[index]].tags.each { |tag| - if tag =~ /^silver-cost:#{path[index+1]}:(.*)$/ - cost_string = $1 - if cost_string =~ /^[0-9]+$/ - cost += cost_string.to_i - else - cost += StringProc.new(cost_string).call.to_i - end - end + if tag =~ /^silver-cost:#{path[index + 1]}:(.*)$/ + cost_string = $1 + if cost_string =~ /^[0-9]+$/ + cost += cost_string.to_i + else + cost += StringProc.new(cost_string).call.to_i + end + end } - } - cost -} - -# -# check for general commands -# -if script.vars.empty? or script.vars[0].strip =~ /^help$/i - show_help.call - exit -elsif script.vars[0] =~ /^targets$/i - echo 'generating list...' - dr_interesting_tags = ["alchemist", "armorshop", "bakery", "bank", "barbarian", "bard", "boutique", "cleric", "clericshop", "empath", "exchange", "fletcher", "forge", "furrier", "gemshop", "general store", "herbalist", "inn", "locksmith", "moonmage", "movers ", "necromancer", "npchealer", "paladin", "pawnshop", "ranger", "smokeshop", "stable", "thief", "town", "trader", "warmage", "weaponshop"] - gs_interesting_tags = [ "advguard", "advguard2", "advguild", "advpickup", "alchemist", "armorshop", "bakery", "bank", "bardguild", "boutique", "chronomage", "clericguild", "clericshop", "collectibles", "consignment", "empathguild", "exchange", "fletcher", "forge", "furrier", "gemshop", "general store", "herbalist", "inn", "locksmith pool", "locksmith", "mail", "movers", "npccleric", "npchealer", "pawnshop", "postoffice", "rangerguild", "smokeshop", "sorcererguild", "sunfist", "town", "voln", "warriorguild", "weaponshop", "wizardguild" ] - town_list = Map.list.find_all { |room| room.tags.include?('town') } - town_ids = town_list.collect { |room| room.id } - town_hash = Hash.new - town_ids.each { |id| town_hash[id] = Array.new } - interesting_tags = if XMLData.game =~ /^DR/ - dr_interesting_tags - else - gs_interesting_tags - end - for tag in interesting_tags - for room in Map.list.find_all { |room| room.tags.include?(tag) } - if nearest = Room[room.id].find_nearest(town_ids) - unless town_hash[nearest].any? { |line| line =~ /^ \- #{tag.ljust(17)} / } - town_hash[nearest].push " - #{tag.ljust(17)} #{room.title.first.sub(/^\[/, '').sub(/\]$/, '').ljust(34)} - #{room.id.to_s.rjust(5)}" - end - end + } + cost + } + + update_urchin_expire = proc { + if UserVars.mapdb_use_urchins + urchin_status_expires_pattern = /You will have access to the urchin guides until (?.*?)\./ + result = dothistimeout 'urchin status', 3, /You will have access to the urchin guides|You currently have no access to the urchin guides.|permanent access to the urchin guides./ + if (m = urchin_status_expires_pattern.match(result)) + UserVars.mapdb_urchins_expire = Time.parse(m[:expires].gsub(/(\d+)\/(\d+)\/(\d+) (\d+:\d+:\d+) (.*?)$/, '\3-\1-\2 \4 \5')).to_i + echo "Urchin expiration successfully updated." + elsif result =~ /permanent access to the urchin guides/ + UserVars.mapdb_urchins_expire = Time.new(Time.now.year + 1, 1, 1).to_i + echo "Urchin expiration successfully updated." + else + UserVars.mapdb_urchins_expire = 0; end - end - output = "\n" - town_list.each { |town_room| - output.concat "---------------------------------------------------------------\n" - output.concat " - town #{town_room.title.first.sub(/^\[/, '').sub(/\]$/, '').ljust(34)} - #{town_room.id.to_s.rjust(5)}\n" - output.concat "---------------------------------------------------------------\n" - town_hash[town_room.id].sort.each { |thingie| - output.concat thingie - output.concat "\n" + if UserVars.mapdb_use_urchins and (UserVars.mapdb_urchins_expire.nil? or UserVars.mapdb_urchins_expire == 0 or Time.now.to_i > UserVars.mapdb_urchins_expire) + echo "Current settings indicate to use urchins, but your access has expired or is unable to be parsed." + echo "Disable this check by running ;go2 --use-urchins=off" + end + end + } + if UserVars.mapdb_use_urchins and (UserVars.mapdb_urchins_expire.nil? or Time.now.to_i > UserVars.mapdb_urchins_expire) + before_dying { update_urchin_expire.call } + end + + # + # check for general commands + # + echo "input: #{Script.current.vars[0]}" if CharSettings['echo_input'] == true; + + if Script.current.vars.empty? or Script.current.vars[0].strip =~ /^help$/i + show_help.call + exit + elsif Script.current.vars[0] =~ /^setup$/i + Setup.new(Go2.load_go2_settings).start + Go2.save_go2_settings(Go2.data) + exit + elsif Script.current.vars[0] =~ /^targets$/i + echo 'generating list...' + dr_interesting_tags = ["alchemist", "armorshop", "bakery", "bank", "barbarian", "bard", "boutique", "cleric", "clericshop", "empath", "exchange", "fletcher", "forge", "furrier", "gemshop", "general store", "herbalist", "inn", "locksmith", "moonmage", "movers ", "necromancer", "npchealer", "paladin", "pawnshop", "ranger", "smokeshop", "stable", "thief", "town", "trader", "warmage", "weaponshop"] + gs_interesting_tags = ["advguard", "advguard2", "advguild", "advpickup", "alchemist", "armorshop", "bakery", "bank", "bardguild", "boutique", "chronomage", "clericguild", "clericshop", "cobbling", "collectibles", "consignment", "empathguild", "exchange", "fletcher", "forge", "furrier", "gemshop", "general store", "grocer", "herbalist", "inn", "locksmith pool", "locksmith", "mail", "movers", "npccleric", "npchealer", "pawnshop", "portmaster", "postoffice", "rangerguild", "smokeshop", "sorcererguild", "sunfist", "treasuremaster", "town", "voln", "warriorguild", "weaponshop", "wizardguild"] + town_list = Map.list.find_all { |room| room.tags.include?('town') and !room.tags.include?('closed') } + town_ids = town_list.collect { |room| room.id } + town_hash = Hash.new + town_ids.each { |id| town_hash[id] = Array.new } + interesting_tags = (XMLData.game =~ /^DR/ ? dr_interesting_tags : gs_interesting_tags) + for tag in interesting_tags + for room in Map.list.find_all { |iroom| iroom.tags.include?(tag) } + if (nearest = Room[room.id].find_nearest(town_ids)) + unless town_hash[nearest].any? { |line| line =~ /^ \- #{tag.ljust(17)} / } + town_hash[nearest].push " - #{tag.ljust(17)} #{room.title.first.sub(/^\[/, '').sub(/\]$/, '').ljust(34)} - #{room.id.to_s.rjust(5)}" + end + end + end + end + output = [] + town_list.each { |town_room| + output << "---------------------------------------------------------------" + output << " - town #{town_room.location.to_s.sub(/^.*?([A-Z].*?)$/, '\1').ljust(34)} - #{town_room.id.to_s.rjust(5)}" + output << "---------------------------------------------------------------" + town_hash[town_room.id].sort.each { |target| + output << target } - output.concat "\n" - } - if XMLData.game =~ /^DR/ - output.concat "---------------------------------------------------------------\n" - output.concat " - Known Nexus Rooms\n" - output.concat "---------------------------------------------------------------\n" - Map.list.find_all{ |room| room.tags.include?('nexus') } - .each{ |room| output.concat "#{room.title.first.sub(/^\[/, '').sub(/\]$/, '').ljust(45)} - #{room.id.to_s.rjust(5)}\n" } - end - respond output - exit -elsif script.vars[0] =~ /^list$/i - output = "\n" - output.concat "settings:\n" - output.concat "\n" - output.concat " typeahead: #{CharSettings['typeahead']}" - if (CharSettings['typeahead'] > 0) and (CharSettings['delay'] > 0) - output.concat " (not used because delay > 0)" - end - output.concat "\n" - output.concat " delay: #{CharSettings['delay']}\n" - if XMLData.game =~ /^GS/ - output.concat " get silvers: #{CharSettings['get silvers'] ? 'on' : 'off'}\n" - output.concat " get return silvers: #{CharSettings['get return trip silvers'] ? 'on' : 'off'}\n" - output.concat " ice mode: #{UserVars.mapdb_ice_mode.nil? ? 'auto' : UserVars.mapdb_ice_mode}\n" - output.concat " use seeking: #{CharSettings['use seeking'] ? 'on' : 'off'}\n" - output.concat " use day pass: #{UserVars.mapdb_use_day_pass == 'yes' ? 'on' : 'off'}\n" - output.concat " buy day pass: #{UserVars.mapdb_buy_day_pass.nil? ? 'off' : UserVars.mapdb_buy_day_pass}\n" - output.concat " day pass container: #{UserVars.day_pass_sack.nil? ? '(not set)' : UserVars.day_pass_sack}\n" - output.concat " stop for dead: #{CharSettings['stop for dead'] ? 'on' : 'off'}\n" - output.concat " vaalor shortcut: #{CharSettings['vaalor shortcut'] ? 'on' : 'off'}\n" - output.concat " FWI trinket: #{UserVars.mapdb_fwi_trinket ? UserVars.mapdb_fwi_trinket : '(not set)'}\n" - end - if XMLData.game =~ /^GSPlat|^GSF/ - output.concat " use portals: #{(UserVars.mapdb_use_portals == 'yes') ? 'yes' : 'no'}\n" - end - if XMLData.game =~ /^GSPlat/ - output.concat " use old portals: #{(UserVars.mapdb_use_old_portals == 'yes') ? 'yes' : 'no'}\n" - end - if XMLData.game =~ /^GSPlat|^GSF/ - output.concat " have portal pass: #{(UserVars.mapdb_have_portal_pass == 'yes') ? 'yes' : 'no'}\n" - end - output.concat "\n" - output.concat "custom targets:\n" - output.concat "\n" - GameSettings['custom targets'].sort_by {|key| key}.to_h.each do |target_name, target_nums| + output << "" + } + if XMLData.game =~ /^DR/ + output << "---------------------------------------------------------------" + output << " - Known Nexus Rooms" + output << "---------------------------------------------------------------" + Map.list.find_all { |iroom| iroom.tags.include?('nexus') } + .each { |iroom| output << "#{iroom.title.first.sub(/^\[/, '').sub(/\]$/, '').ljust(45)} - #{iroom.id.to_s.rjust(5)}" } + end + respond output + exit + elsif Script.current.vars[0] =~ /^list$/i + output = [] + output << "Go2 v#{Go2.get_script_version} settings:" + output << "" + output << " typeahead: #{CharSettings['typeahead']}" + if (CharSettings['typeahead'] > 0) and (CharSettings['delay'] > 0) + output << " (not used because delay > 0)" + end + output << "" + output << " delay: #{CharSettings['delay']}" + output << " echo input: #{CharSettings['echo_input'] ? 'on' : 'off'}" + output << "hide room descriptions: #{CharSettings['hide_room_descriptions'] ? 'on' : 'off'}" + output << " hide room titles: #{CharSettings['hide_room_titles'] ? 'on' : 'off'}" + if XMLData.game =~ /^GS/ + output << " get silvers: #{CharSettings['get silvers'] ? 'on' : 'off'}" + output << " get return silvers: #{CharSettings['get return trip silvers'] ? 'on' : 'off'}" + output << " ice mode: #{UserVars.mapdb_ice_mode}" + output << " use seeking: #{CharSettings['use seeking'] ? 'on' : 'off'}" + output << " use urchins: #{UserVars.mapdb_use_urchins ? 'on' : 'off'}" + output << " use portmasters: #{UserVars.mapdb_use_portmasters ? 'on' : 'off'}" + output << " use day pass: #{UserVars.mapdb_use_day_pass ? 'on' : 'off'}" + output << " buy day pass: #{UserVars.mapdb_buy_day_pass ? 'on' : 'off'}" + output << " day pass container: #{UserVars.day_pass_sack.nil? ? '(not set)' : UserVars.day_pass_sack}" + output << " stop for dead: #{CharSettings['stop for dead'] ? 'on' : 'off'}" + output << " vaalor shortcut: #{CharSettings['vaalor shortcut'] ? 'on' : 'off'}" + output << " FWI trinket: #{UserVars.mapdb_fwi_trinket ? UserVars.mapdb_fwi_trinket : '(not set)'}" + output << " caravan to sos: #{UserVars.mapdb_car_to_sos == true ? 'on' : 'off'}" + output << " caravan from sos: #{UserVars.mapdb_car_from_sos == true ? 'on' : 'off'}" + end + if XMLData.game =~ /^GSPlat|^GSF/ + output << " use portals: #{(UserVars.mapdb_use_portals == 'yes') ? 'yes' : 'no'}" + end + if XMLData.game =~ /^GSPlat/ + output << " use old portals: #{(UserVars.mapdb_use_old_portals == 'yes') ? 'yes' : 'no'}" + end + if XMLData.game =~ /^GSPlat|^GSF/ + output << " have portal pass: #{(UserVars.mapdb_have_portal_pass == 'yes') ? 'yes' : 'no'}" + end + output << "" + output << "custom targets:" + output << "" + GameSettings['custom targets'].sort_by { |key| key }.to_h.each do |target_name, target_nums| if target_nums.is_a?(Array) target_nums.uniq! if target_nums.length == 1 - output.concat " #{target_name.ljust(15)} = #{target_nums.to_s} - #{Map[target_nums[0]].title.first}" + output << " #{target_name.ljust(15)} = #{target_nums} - #{Map[target_nums[0]].title.first}" else - output.concat " #{target_name.ljust(15)} = #{target_nums.sort.to_s}" + output << " #{target_name.ljust(15)} = #{target_nums.sort}" end else - output.concat " #{target_name.ljust(15)} = [#{target_nums.to_s}] - #{Map[target_nums].title.first}" + output << " #{target_name.ljust(15)} = #{target_nums} - #{Map[target_nums].title.first}" end - output.concat "\n" - end - output.concat "\n" - respond output - exit -elsif script.vars[1] =~ /^save/i - unless script.vars[0] =~ /^save ([a-zA-Z0-9!@.#$%_\s-]+)\s?=\s?(current|\d+)$/ || script.vars[0] =~ /^save ([a-zA-Z0-9!@.#$%_\s-]+)\s?=\s?\[?([current\d,\s]+)\]?$/ + end + output << "" + respond output + exit + elsif Script.current.vars[1] =~ /^save/i + unless Script.current.vars[0] =~ /^save ([a-zA-Z0-9!@.#$%_\s-]+)\s?=\s?(current|\d+)$/ || Script.current.vars[0] =~ /^save ([a-zA-Z0-9!@.#$%_\s-]+)\s?=\s?\[?([current\d,\s]+)\]?$/ echo "error: format" echo "error: proper format examples - ;go2 save test=1234 OR ;go2 save test=[1234, 1432] etc." exit - end - target_name = $1.strip - target = $2.split(',') - .collect(&:strip) - - if target_name =~ /^\d+$/ + end + target_name = $1.strip + target = $2.split(',').collect(&:strip) + if target_name =~ /^\d+$/ echo "error: target name can't be just a number." exit - end - - # User included current room as a custom target. Verify exists. - if target.include?(/current/i) + end + # User included current room as a custom target. Verify exists. + if target.include?(/current/i) unless Map.current.id echo 'error: your current room was not found in the map database.' exit end end - target.map! {|element| element == "current" ? Map.current.id : element} - .map!(&:to_i) + target.map! { |element| element == "current" ? Map.current.id : element }.map!(&:to_i) - target_holder = [] - target.each do |element| - unless target_room = Map[element] - target_holder.append(element) + target_holder = [] + target.each do |element| + # unless target_room = Map[element] + unless Map[element] + target_holder.append(element) end end - unless target_holder.empty? + unless target_holder.empty? echo "error: the following rooms were not found in the map - #{target_holder}" exit - end - - custom_targets = (GameSettings['custom targets'] || Hash.new) - - if (custom_targets[target_name] && custom_targets[target_name].kind_of?(Array)) + end + if target.length == 1 + target = target.first + end + custom_targets = (GameSettings['custom targets'] || Hash.new) + if (custom_targets[target_name] && custom_targets[target_name].kind_of?(Array)) echo "Custom target #{target_name} exists. Appending this roomnumber(s)." - custom_targets[target_name] = (custom_targets[target_name] + target).uniq - elsif (custom_targets[target_name] && custom_targets[target_name].kind_of?(Integer)) + custom_targets[target_name] = (custom_targets[target_name] + Array(target)).uniq + elsif (custom_targets[target_name] && custom_targets[target_name].kind_of?(Integer)) echo "Custom target #{target_name} exists. Replacing with this room number." custom_targets[target_name] = target - else + else custom_targets[target_name] = target - end - GameSettings['custom targets'] = custom_targets - echo "custom target saved (#{target_name} => #{custom_targets[target_name]})" - exit -elsif script.vars[1] =~ /^delete$/i - delkey = script.vars[0].sub(/\s*delete\s*/i, '') - custom_targets = (GameSettings['custom targets'] || Hash.new) - if kilkey = custom_targets.keys.find { |key| key =~ /^#{delkey}$/i } or kilkey = custom_targets.keys.find { |key| key =~ /^#{delkey}/i } + end + GameSettings['custom targets'] = custom_targets + echo "custom target saved (#{target_name} => #{custom_targets[target_name]})" + exit + elsif Script.current.vars[1] =~ /^delete$/i + delkey = Script.current.vars[0].sub(/\s*delete\s*/i, '') + custom_targets = (GameSettings['custom targets'] || Hash.new) + if (kilkey = custom_targets.keys.find { |key| key =~ /^#{delkey}$/i }) or (kilkey = custom_targets.keys.find { |key| key =~ /^#{delkey}/i }) custom_targets.delete(kilkey) GameSettings['custom targets'] = custom_targets echo "custom target deleted (#{kilkey})" exit - else + else echo "#{delkey} does not appear to be a custom target" exit - end -elsif script.vars[1] =~ /^reload$/i - Map.reload - echo 'map data has been reloaded' - exit -end + end + elsif Script.current.vars[1] =~ /^reload$/i + Map.reload + echo 'map data has been reloaded' + exit + end -# -# target and/or options -# - -target_search_array = Array.new -setting_typeahead = nil -setting_delay = nil -setting_disable_confirm = false -setting_use_vaalor_shortcut = nil -setting_ice_mode = nil -setting_fwi_trinket = nil -setting_get_silvers = nil -setting_use_seeking = nil -setting_use_day_pass = nil -setting_buy_day_pass = nil -setting_day_pass_container = nil -setting_stop_for_dead = nil -setting_get_return_trip_silvers = nil -setting_have_portal_pass = nil -setting_use_portals = nil -setting_use_old_portals = nil -setting_instability = nil -setting_drag = nil - -for var in script.vars[1..-1] - if var =~ /^(?:\-\-)?typeahead=([0-9]+)$/i + # + # target and/or options + # + + target_search_array = Array.new + setting_typeahead = nil + setting_delay = nil + setting_disable_confirm = false + setting_use_vaalor_shortcut = nil + setting_ice_mode = nil + setting_fwi_trinket = nil + setting_get_silvers = nil + setting_use_seeking = nil + setting_use_urchins = nil + setting_use_portmasters = nil + setting_use_day_pass = nil + setting_buy_day_pass = nil + setting_day_pass_container = nil + setting_stop_for_dead = nil + setting_get_return_trip_silvers = nil + setting_have_portal_pass = nil + setting_use_portals = nil + setting_use_old_portals = nil + setting_instability = nil + setting_drag = nil + setting_use_caravan_to_sos = nil + setting_use_caravan_from_sos = nil + setting_hide_room_descriptions = nil + setting_hide_room_titles = nil + setting_echo_input = nil + + for var in Script.current.vars[1..-1] + if var =~ /^(?:\-\-)?typeahead=([0-9]+)$/i setting_typeahead = $1.to_i - elsif var =~ /^(?:\-\-)?delay=([0-9\.]+)$/i + elsif var =~ /^(?:\-\-)?delay=([0-9\.]+)$/i setting_delay = $1.to_f - elsif var =~ /^\-\-instability=([0-9]+)$/i + elsif var =~ /^\-\-instability=([0-9]+)$/i setting_instability = $1.to_i - elsif var =~ /^_disable_confirm_$|^--disable-confirm$/i + elsif var =~ /^_disable_confirm_$|^--disable-confirm$/i setting_disable_confirm = true - elsif var =~ /^--stop-for-dead$/i + elsif var =~ /^--stop-for-dead$/i setting_stop_for_dead = true - elsif var =~ /^--stop-for-dead=(on|true|yes|off|false|no)/i - setting_stop_for_dead = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and var =~ /^(?:\-\-)?shortcut=(on|true|yes|off|false|no)$/i - setting_use_vaalor_shortcut = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?ice\-?mode=(auto|wait|run)$/i) + elsif var =~ /^--stop-for-dead=(on|true|yes|off|false|no)/i + setting_stop_for_dead = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and var =~ /^(?:\-\-)?shortcut=(on|true|yes|off|false|no)$/i + setting_use_vaalor_shortcut = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?ice\-?mode=(auto|wait|run)$/i) setting_ice_mode = $1.downcase - elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?get[_\-]?(?:silver|coin)s?=(on|true|yes|off|false|no)$/i) - setting_get_silvers = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?use[_\-]?seeking=(on|true|yes|off|false|no)$/i) - setting_use_seeking = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-use[_\-]?day[_\-]?pass=(on|true|yes|off|false|no)$/i) - setting_use_day_pass = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-buy[_\-]?day[_\-]?pass=(.+)$/i) - if setting_value[$1] - setting_buy_day_pass = setting_value[$1] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?get[_\-]?(?:silver|coin)s?=(on|true|yes|off|false|no)$/i) + setting_get_silvers = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?use[_\-]?seeking=(on|true|yes|off|false|no)$/i) + setting_use_seeking = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?use[_\-]?urchins?=(on|true|yes|off|false|no)$/i) + setting_use_urchins = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?use[_\-]?portmasters?=(on|true|yes|off|false|no)$/i) + setting_use_portmasters = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-use[_\-]?day[_\-]?pass=(on|true|yes|off|false|no)$/i) + setting_use_day_pass = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-buy[_\-]?day[_\-]?pass=(.+)$/i) + if setting_value[$1.downcase] == true + setting_buy_day_pass = true + elsif setting_value[$1.downcase] == false + setting_buy_day_pass = false else - setting_buy_day_pass = $1 - setting_buy_day_pass.split(';').each { |location| - if location !~ /^\s*(?:wl,imt|imt,wl|wl,sol|sol,wl|imt,sol|ill,val|val,ill|ill,cys|cys,ill|val,cys|cys,val)\s*$/i - echo "warning: Location #{location} is invalid. Using it anyway." - end - } + setting_buy_day_pass = $1 + setting_buy_day_pass.split(';').each { |location| + if location !~ /^\s*(?:wl,imt|imt,wl|wl,sol|sol,wl|imt,sol|ill,val|val,ill|ill,cys|cys,ill|val,cys|cys,val)\s*$/i + echo "warning: Location #{location} is invalid. Using it anyway." + end + } end - elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-day[_\-]?pass[_\-]?(?:container|sack)=(.+)$/i) + elsif (XMLData.game =~ /^GS/) and (var =~ /^\-\-day[_\-]?pass[_\-]?(?:container|sack)=(.+)$/i) setting_day_pass_container = $1 - elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?get\-return\-trip\-silvers=(on|true|yes|off|false|no)$/i) - setting_get_return_trip_silvers = setting_value[$1] - elsif (XMLData.game =~ /^DR/) and (var =~ /^(?:\-\-)?drag=(.+)$/i) + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?get\-return\-trip\-silvers=(on|true|yes|off|false|no)$/i) + setting_get_return_trip_silvers = setting_value[$1.downcase] + elsif (XMLData.game =~ /^DR/) and (var =~ /^(?:\-\-)?drag=(.+)$/i) setting_drag = $1 - elsif (XMLData.game =~ /^GSF|^GSPlat/) and (var =~ /^(?:\-\-)?portals?=(on|true|yes|off|false|no)$/i) - setting_use_portals = setting_value[$1] - elsif (XMLData.game =~ /^GSPlat/) and (var =~ /^(?:\-\-)?old\-portals?=(on|true|yes|off|false|no)$/i) - setting_use_old_portals = setting_value[$1] - elsif (XMLData.game =~ /^GSPlat/) and (var =~ /^(?:\-\-)?portal\-pass=(on|true|yes|off|false|no)$/i) - setting_have_portal_pass = setting_value[$1] - elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?fwi\-?trinket=(.+)$/i) + elsif (XMLData.game =~ /^GSF|^GSPlat/) and (var =~ /^(?:\-\-)?portals?=(on|true|yes|off|false|no)$/i) + setting_use_portals = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GSPlat/) and (var =~ /^(?:\-\-)?old\-portals?=(on|true|yes|off|false|no)$/i) + setting_use_old_portals = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GSPlat/) and (var =~ /^(?:\-\-)?portal\-pass=(on|true|yes|off|false|no)$/i) + setting_have_portal_pass = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?fwi\-?trinket=(.+)$/i) setting_fwi_trinket = $1.downcase - else + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?caravan\-?to\-?sos=(on|true|yes|off|false|no)$/i) + setting_use_caravan_to_sos = setting_value[$1.downcase] + elsif (XMLData.game =~ /^GS/) and (var =~ /^(?:\-\-)?caravan\-?from\-?sos=(on|true|yes|off|false|no)$/i) + setting_use_caravan_from_sos = setting_value[$1.downcase] + elsif (var =~ /^(?:\-\-)?hide[_\-]?(?:room[_\-]?)?descriptions?=(on|true|yes|off|false|no)$/i) + setting_hide_room_descriptions = setting_value[$1.downcase] + elsif (var =~ /^(?:\-\-)?hide[_\-]?(?:room[_\-]?)?titles?=(on|true|yes|off|false|no)$/i) + setting_hide_room_titles = setting_value[$1.downcase] + elsif (var =~ /^(?:\-\-)?echo[_\-]?input=(on|true|yes|off|false|no)$/i) + setting_echo_input = setting_value[$1.downcase] + else target_search_array.push(var) - end -end - -target_search_string = target_search_array.join(' ') + end + end + target_search_string = target_search_array.join(' ') -# -# if only settings were given, save the settings and exit -# -if target_search_string.empty? - unless setting_delay.nil? + # + # if only settings were given, save the settings and exit + # + if target_search_string.empty? + unless setting_delay.nil? CharSettings['delay'] = setting_delay echo "delay setting changed to #{setting_delay} seconds" - end - unless setting_typeahead.nil? + end + unless setting_typeahead.nil? CharSettings['typeahead'] = setting_typeahead echo "typeahead setting changed to #{setting_typeahead}" if CharSettings['delay'].to_f > 0 - echo "typeahead setting will not be used, because the delay setting is greater than zero" + echo "typeahead setting will not be used, because the delay setting is greater than zero" end - end - if XMLData.game =~ /^GSPlat|^GSF/ + end + unless setting_hide_room_descriptions.nil? + CharSettings['hide_room_descriptions'] = setting_hide_room_descriptions + echo "go2 #{(setting_hide_room_descriptions ? 'will' : 'will not')} hide room descriptions during travel and turn them on after." + end + unless setting_hide_room_titles.nil? + CharSettings['hide_room_titles'] = setting_hide_room_titles + echo "go2 #{(setting_hide_room_titles ? 'will' : 'will not')} hide room titles during travel and turn them on after." + end + unless setting_echo_input.nil? + CharSettings['echo_input'] = setting_echo_input + echo "go2 #{(setting_echo_input ? 'will' : 'will not')} echo input when the script starts" + end + + if XMLData.game =~ /^GSPlat|^GSF/ unless setting_use_portals.nil? - UserVars.mapdb_use_portals = (setting_use_portals ? 'yes' : 'no') - echo "portals will #{'not ' unless setting_use_portals}be used" + UserVars.mapdb_use_portals = (setting_use_portals ? 'yes' : 'no') + echo "portals will #{'not ' unless setting_use_portals}be used" end - end - if XMLData.game =~ /^GSPlat/ + end + if XMLData.game =~ /^GSPlat/ unless setting_use_old_portals.nil? - UserVars.mapdb_use_old_portals = (setting_use_old_portals ? 'yes' : 'no') - echo "old portals will #{'not ' unless setting_use_old_portals}be used" + UserVars.mapdb_use_old_portals = (setting_use_old_portals ? 'yes' : 'no') + echo "old portals will #{'not ' unless setting_use_old_portals}be used" end unless setting_have_portal_pass.nil? - UserVars.mapdb_have_portal_pass = (setting_have_portal_pass ? 'yes' : 'no') - echo "the script will #{'not ' if setting_have_portal_pass}try to pull out a portal ticket to use portals" + UserVars.mapdb_have_portal_pass = (setting_have_portal_pass ? 'yes' : 'no') + echo "the script will #{'not ' if setting_have_portal_pass}try to pull out a portal ticket to use portals" end - end - if XMLData.game =~ /^GS/ + end + if XMLData.game =~ /^GS/ unless setting_use_vaalor_shortcut.nil? - CharSettings['vaalor shortcut'] = setting_use_vaalor_shortcut - $go2_use_vaalor_shortcut = setting_use_vaalor_shortcut - change_map_vaalor_shortcut.call(setting_use_vaalor_shortcut) - echo "shortcut between Ta'Vaalor and Ta'Illistim will #{'not ' unless setting_use_vaalor_shortcut}be used" + CharSettings['vaalor shortcut'] = setting_use_vaalor_shortcut + $go2_use_vaalor_shortcut = setting_use_vaalor_shortcut + change_map_vaalor_shortcut.call(setting_use_vaalor_shortcut) + echo "shortcut between Ta'Vaalor and Ta'Illistim will #{'not ' unless setting_use_vaalor_shortcut}be used" end unless setting_get_silvers.nil? - CharSettings['get silvers'] = setting_get_silvers - echo "go2 #{ if setting_get_silvers then 'may' else 'will not' end } withdraw money from your bank account for travel expenses" + CharSettings['get silvers'] = setting_get_silvers + echo "go2 #{if setting_get_silvers then 'may' else 'will not' end} withdraw money from your bank account for travel expenses" end unless setting_use_seeking.nil? - CharSettings['use seeking'] = setting_use_seeking - $go2_use_seeking = setting_use_seeking - echo "go2 #{ if setting_use_seeking then 'may' else 'will not' end } use symbol of seeking for faster travel" + CharSettings['use seeking'] = setting_use_seeking + $go2_use_seeking = setting_use_seeking + echo "go2 #{if setting_use_seeking then 'may' else 'will not' end} use symbol of seeking for faster travel" + end + unless setting_use_urchins.nil? + UserVars.mapdb_use_urchins = (setting_use_urchins.to_s =~ /on|true|yes/i ? true : false) + echo "go2 #{if setting_use_urchins then 'may' else 'will not' end} use urchin guides for faster travel" + end + unless setting_use_portmasters.nil? + UserVars.mapdb_use_portmasters = (setting_use_portmasters.to_s =~ /on|true|yes/i ? true : false) + echo "go2 #{if setting_use_portmasters then 'may' else 'will not' end} use portmasters for faster travel" end unless setting_use_day_pass.nil? - UserVars.mapdb_use_day_pass = setting_use_day_pass - echo "go2 #{ if setting_use_day_pass then 'will' else 'will not' end } use Chronomage day passes for faster travel" + UserVars.mapdb_use_day_pass = setting_use_day_pass + echo "go2 #{if setting_use_day_pass then 'will' else 'will not' end} use Chronomage day passes for faster travel" end unless setting_buy_day_pass.nil? - UserVars.mapdb_buy_day_pass = setting_buy_day_pass - echo 'setting saved' # fixme: be more descriptive + UserVars.mapdb_buy_day_pass = setting_buy_day_pass + echo 'setting saved' # fixme: be more descriptive end unless setting_day_pass_container.nil? - UserVars.day_pass_sack = setting_day_pass_container - echo 'setting saved' # fixme: be more descriptive + UserVars.day_pass_sack = setting_day_pass_container + echo 'setting saved' # fixme: be more descriptive end unless setting_stop_for_dead.nil? - CharSettings['stop for dead'] = setting_stop_for_dead - echo "go2 #{ if setting_stop_for_dead then 'will (probably)' else 'will not' end } stop when it sees dead people" + CharSettings['stop for dead'] = setting_stop_for_dead + echo "go2 #{if setting_stop_for_dead then 'will (probably)' else 'will not' end} stop when it sees dead people" end unless setting_ice_mode.nil? - UserVars.mapdb_ice_mode = setting_ice_mode - echo 'setting saved' # fixme: be more descriptive + echo "go2 ice mode is #{UserVars.mapdb_ice_mode == setting_ice_mode ? 'already' : 'now'} #{setting_ice_mode.inspect}" + UserVars.mapdb_ice_mode = setting_ice_mode end unless setting_fwi_trinket.nil? - if setting_fwi_trinket == 'off' - UserVars.mapdb_fwi_trinket = nil - else + trinket_changed = false; + if setting_fwi_trinket == 'off' + trinket_changed = true if !UserVars.mapdb_fwi_trinket.nil?; + UserVars.mapdb_fwi_trinket = nil + else + if UserVars.mapdb_trinket != setting_fwi_trinket UserVars.mapdb_fwi_trinket = setting_fwi_trinket - end - echo 'setting saved' # fixme: be more descriptive + trinket_changed = true; + end + end + echo "mapdb_fwi_trinket is now #{UserVars.mapdb_fwi_trinket.inspect}" if trinket_changed + echo "mapdb_fwi_trinket unchanged, value is #{UserVars.mapdb_fwi_trinket.inspect}" if !trinket_changed + end + unless setting_use_caravan_to_sos.nil? + UserVars.mapdb_car_to_sos = setting_use_caravan_to_sos + echo "go2 #{if setting_use_caravan_to_sos then 'will' else 'will not' end} use the caravan to travel to the Sanctum of Scales" + end + unless setting_use_caravan_from_sos.nil? + UserVars.mapdb_car_from_sos = setting_use_caravan_from_sos + echo "go2 #{if setting_use_caravan_from_sos then 'will' else 'will not' end} use the caravan to travel back from the Sanctum of Scales" end unless setting_get_return_trip_silvers.nil? - CharSettings['get return trip silvers'] = setting_get_return_trip_silvers - echo "silvers will #{'not ' unless setting_get_return_trip_silvers}be withdrawn in advance for return trips" + CharSettings['get return trip silvers'] = setting_get_return_trip_silvers + echo "silvers will #{'not ' unless setting_get_return_trip_silvers}be withdrawn in advance for return trips" end - end - exit -end + end + exit + end -unless start_room = Room.current - echo 'error: your current room was not found in the map database' - exit -end + # + # find your way out of a playershop in gemstone + # + def self.playershop_escape() + return if XMLData.room_exits_string !~ /Obvious exits:/ + playershop_suffixes = ["Outfitting", "Magic Shoppe", "Weaponry", "General Store", "Armory", "Combat Gear", "Lockpicks"] + playershop_uid_groups = [631, 632, 633, 634, 635, 636, 637, 638, 639, 640, 641, 642, 643, 644, 645, 646] + if XMLData.room_title =~ /#{playershop_suffixes.join('|')}/ or playershop_uid_groups.include?(XMLData.room_id / 1000) + move(XMLData.room_exits.first) if !XMLData.room_exits.include?('out') + move('out') + end + end + self.playershop_escape if XMLData.game =~ /^GS/ and Map.current.id.nil? -if target_search_string =~ /goback/i - last_start_room = UserVars.go2_start_room.to_s - if last_start_room - target_search_string = last_start_room - echo "Attempting to return to last start room of: #{last_start_room}" - else - echo "go2 does not have a stored start room from the last time it ran." + unless (start_room = Room.current) + echo 'error: your current room was not found in the map database' exit end -end -# -# target was given; use saved settings, override them with command line settings, but don't save them -# -if setting_drag - setting_typeahead = 0 -elsif setting_typeahead.nil? - setting_typeahead = CharSettings['typeahead'] -end + if target_search_string =~ /goback/i + last_start_room = UserVars.go2_start_room.to_s + if last_start_room + target_search_string = last_start_room + echo "Attempting to return to last start room of: #{last_start_room}" + else + echo "go2 does not have a stored start room from the last time it ran." + exit + end + end -if setting_delay.nil? - setting_delay = CharSettings['delay'] -end + # + # target was given; use saved settings, override them with command line settings, but don't save them + # + if setting_drag + setting_typeahead = 0 + elsif setting_typeahead.nil? + setting_typeahead = CharSettings['typeahead'] + end -if setting_get_silvers.nil? - $go2_get_silvers = CharSettings['get silvers'] -else - before_dying { $go2_get_silvers = CharSettings['get silvers'] } - $go2_get_silvers = setting_get_silvers -end + if setting_delay.nil? + setting_delay = CharSettings['delay'] + end -if setting_use_seeking.nil? - $go2_use_seeking = CharSettings['use seeking'] -else - before_dying { $go2_use_seeking = CharSettings['use seeking'] } - $go2_use_seeking = setting_use_seeking -end + if setting_get_silvers.nil? + $go2_get_silvers = CharSettings['get silvers'] + else + before_dying { $go2_get_silvers = CharSettings['get silvers'] } + $go2_get_silvers = setting_get_silvers + end -if setting_use_day_pass - previous_use_day_pass = UserVars.mapdb_use_day_pass - before_dying { UserVars.mapdb_use_day_pass = previous_use_day_pass } - UserVars.mapdb_use_day_pass = setting_use_day_pass -end + if setting_use_seeking.nil? + $go2_use_seeking = CharSettings['use seeking'] + else + before_dying { $go2_use_seeking = CharSettings['use seeking'] } + $go2_use_seeking = setting_use_seeking + end -if setting_buy_day_pass - previous_buy_day_pass = UserVars.mapdb_buy_day_pass - before_dying { UserVars.mapdb_buy_day_pass = previous_buy_day_pass } - UserVars.mapdb_buy_day_pass = setting_buy_day_pass -end + unless setting_use_urchins.nil? + saved_use_urchins = UserVars.mapdb_use_urchins + before_dying { UserVars.mapdb_use_urchins = saved_use_urchins } + UserVars.mapdb_use_urchins = setting_use_urchins + end -if setting_day_pass_container - previous_day_pass_container = UserVars.day_pass_sack - before_dying { UserVars.day_pass_sack = previous_day_pass_container } - UserVars.day_pass_sack = setting_day_pass_container -end + if setting_use_portmasters + saved_use_portmasters = UserVars.mapdb_use_portmasters + before_dying { UserVars.mapdb_use_portmasters = saved_use_portmasters } + UserVars.mapdb_use_portmasters = setting_use_portmasters + end -if setting_stop_for_dead.nil? - setting_stop_for_dead = CharSettings['stop for dead'] -end + if setting_use_day_pass + previous_use_day_pass = UserVars.mapdb_use_day_pass + before_dying { UserVars.mapdb_use_day_pass = previous_use_day_pass } + UserVars.mapdb_use_day_pass = setting_use_day_pass + end -if setting_ice_mode - previous_ice_mode = UserVars.mapdb_ice_mode - before_dying { UserVars.mapdb_ice_mode = previous_ice_mode } - UserVars.mapdb_ice_mode = setting_ice_mode -end + if setting_buy_day_pass + previous_buy_day_pass = UserVars.mapdb_buy_day_pass + before_dying { UserVars.mapdb_buy_day_pass = previous_buy_day_pass } + UserVars.mapdb_buy_day_pass = setting_buy_day_pass + end -if setting_fwi_trinket - previous_fwi_trinket = UserVars.mapdb_fwi_trinket - before_dying { UserVars.mapdb_fwi_trinket = previous_fwi_trinket } - if setting_fwi_trinket == 'off' + if setting_day_pass_container + previous_day_pass_container = UserVars.day_pass_sack + before_dying { UserVars.day_pass_sack = previous_day_pass_container } + UserVars.day_pass_sack = setting_day_pass_container + end + + if setting_stop_for_dead.nil? + setting_stop_for_dead = CharSettings['stop for dead'] + end + + if setting_ice_mode + previous_ice_mode = UserVars.mapdb_ice_mode + before_dying { UserVars.mapdb_ice_mode = previous_ice_mode } + UserVars.mapdb_ice_mode = setting_ice_mode + end + + if setting_fwi_trinket + previous_fwi_trinket = UserVars.mapdb_fwi_trinket + before_dying { UserVars.mapdb_fwi_trinket = previous_fwi_trinket } + if setting_fwi_trinket == 'off' UserVars.mapdb_fwi_trinket = nil - else + else UserVars.mapdb_fwi_trinket = setting_fwi_trinket - end -end + end + end -unless setting_use_portals.nil? - previous_use_portals = UserVars.mapdb_use_portals - before_dying { UserVars.mapdb_use_portals = previous_use_portals } - UserVars.mapdb_use_portals = (setting_use_portals ? 'yes' : 'no') -end + unless setting_use_portals.nil? + previous_use_portals = UserVars.mapdb_use_portals + before_dying { UserVars.mapdb_use_portals = previous_use_portals } + UserVars.mapdb_use_portals = (setting_use_portals ? 'yes' : 'no') + end -unless setting_use_old_portals.nil? - previous_use_old_portals = UserVars.mapdb_use_old_portals - before_dying { UserVars.mapdb_use_old_portals = previous_use_old_portals } - UserVars.mapdb_use_old_portals = (setting_use_old_portals ? 'yes' : 'no') -end + unless setting_use_old_portals.nil? + previous_use_old_portals = UserVars.mapdb_use_old_portals + before_dying { UserVars.mapdb_use_old_portals = previous_use_old_portals } + UserVars.mapdb_use_old_portals = (setting_use_old_portals ? 'yes' : 'no') + end -unless setting_have_portal_pass.nil? - previous_have_portal_pass = UserVars.mapdb_have_portal_pass - before_dying { UserVars.mapdb_have_portal_pass = previous_have_portal_pass } - UserVars.mapdb_have_portal_pass = (setting_have_portal_pass ? 'yes' : 'no') -end + unless setting_have_portal_pass.nil? + previous_have_portal_pass = UserVars.mapdb_have_portal_pass + before_dying { UserVars.mapdb_have_portal_pass = previous_have_portal_pass } + UserVars.mapdb_have_portal_pass = (setting_have_portal_pass ? 'yes' : 'no') + end -if setting_use_vaalor_shortcut.nil? - setting_use_vaalor_shortcut = CharSettings['vaalor shortcut'] -else - before_dying { $go2_use_vaalor_shortcut = CharSettings['vaalor shortcut'] } -end -$go2_use_vaalor_shortcut = setting_use_vaalor_shortcut + if setting_use_vaalor_shortcut.nil? + setting_use_vaalor_shortcut = CharSettings['vaalor shortcut'] + else + before_dying { $go2_use_vaalor_shortcut = CharSettings['vaalor shortcut'] } + end + $go2_use_vaalor_shortcut = setting_use_vaalor_shortcut -if setting_get_return_trip_silvers.nil? - setting_get_return_trip_silvers = CharSettings['get return trip silvers'] -end + unless setting_use_caravan_to_sos.nil? + previous_caravan_to_sos = UserVars.mapdb_car_to_sos + before_dying { UserVars.mapdb_car_to_sos = previous_caravan_to_sos } + UserVars.mapdb_car_to_sos = setting_use_caravan_to_sos + end -if XMLData.game =~ /^GS/ - change_map_vaalor_shortcut.call(setting_use_vaalor_shortcut) -end + unless setting_use_caravan_from_sos.nil? + previous_caravan_from_sos = UserVars.mapdb_car_from_sos + before_dying { UserVars.mapdb_car_from_sos = previous_caravan_from_sos } + UserVars.mapdb_car_from_sos = setting_use_caravan_from_sos + end -# -# find target -# -if defined?(Map.ids_from_uid) - uid_pattern = /u(?\d+)/ - if m = uid_pattern.match(target_search_string) - uid = m[:uid].to_i - lookup_id = Map.ids_from_uid(uid) - if lookup_id.size > 0 - target_search_string = "#{lookup_id[0]}" - end + if setting_get_return_trip_silvers.nil? + setting_get_return_trip_silvers = CharSettings['get return trip silvers'] end -end -if (target_search_string =~ /^[0-9]+$/) or (XMLData.game =~ /^GS/ and target_search_string =~ /^confluence(?:\-hot|\-cold)?$|^instability$/i) - if target_search_string =~ /^[0-9]+$/ - unless destination = Map[target_search_string.to_i] - echo "error: room number (#{target_search_string}) was not found in the map database" - exit + + if XMLData.game =~ /^GS/ + change_map_vaalor_shortcut.call(setting_use_vaalor_shortcut) + end + + # + # find target + # + if defined?(Map.ids_from_uid) + uid_pattern = /u(?\d+)/ + if (m = uid_pattern.match(target_search_string)) + uid = m[:uid].to_i + lookup_id = Map.ids_from_uid(uid) + if lookup_id.size > 0 + target_search_string = "#{lookup_id[0]}" + end + end + end + if (target_search_string =~ /^[0-9]+$/) or (XMLData.game =~ /^GS/ and target_search_string =~ /^confluence(?:\-hot|\-cold)?$|^instability$/i) + if target_search_string =~ /^[0-9]+$/ + unless (destination = Map[target_search_string.to_i]) + echo "error: room number (#{target_search_string}) was not found in the map database" + exit end confirm = false - end - if (target_search_string =~ /^confluence(?:\-hot|\-cold)?$|^instability$/i) or (XMLData.game =~ /^GS/ and destination.title.first == '[Elemental Confluence]' and XMLData.room_title != '[Elemental Confluence]') + end + if (target_search_string =~ /^confluence(?:\-hot|\-cold)?$|^instability$/i) or (XMLData.game =~ /^GS/ and destination.title.first == '[Elemental Confluence]' and XMLData.room_title != '[Elemental Confluence]') if target_search_string =~ /^confluence$/ and XMLData.room_title == '[Elemental Confluence]' - echo "you're already here..." - exit + echo "you're already here..." + exit end - town_ids = [ 228, 2300, 1438, 1005, 188, 1932, 3519, 10855, 3668 ] + town_ids = [228, 2300, 1438, 1005, 188, 1932, 3519, 10855, 3668] found_instability = false if setting_instability - Script.run('go2', setting_instability.to_s, :force => true) - if GameObj.loot.any? { |o| o.noun == 'instability' } - $mapdb_last_instability = Room.current.id - $mapdb_instability_timeto = Hash.new - for id in town_ids - path = Room[$mapdb_last_instability].path_to(id) - if path.nil? - $mapdb_instability_timeto[id] = nil - else - $mapdb_instability_timeto[id] = Map.estimate_time(path) - end + Script.run('go2', setting_instability.to_s, :force => true) + if GameObj.loot.any? { |o| o.noun == 'instability' } + $mapdb_last_instability = Room.current.id + $mapdb_instability_timeto = Hash.new + for id in town_ids + path = Room[$mapdb_last_instability].path_to(id) + if path.nil? + $mapdb_instability_timeto[id] = nil + else + $mapdb_instability_timeto[id] = Map.estimate_time(path) end - found_instability = true - end + end + found_instability = true + end else - if CharSettings['element'].nil? - r = dothistimeout 'attune', 5, /^\s*You are attuned to the Element of|^\s*ATTUNE SET/ - if r =~ /You are attuned to the Element of (.+)\./ - CharSettings['element'] = $1.downcase - elsif r =~ /ATTUNE SET/ - echo "You're not attuned to an element, so I don't know how to find an instability." - exit + if CharSettings['element'].nil? + r = dothistimeout 'attune', 5, /^\s*You are attuned to the Element of|^\s*ATTUNE SET/ + if r =~ /You are attuned to the Element of (.+)\./ + CharSettings['element'] = $1.downcase + elsif r =~ /ATTUNE SET/ + echo "You're not attuned to an element, so I don't know how to find an instability." + exit + else + echo "error: can't get right" + exit + end + end + + GameSettings['recent-instabilities'] ||= Array.new + + good_room_ids = Array.new + bad_room_ids = Array.new + got_room_text = false + to_element = { 'gust of wind' => 'air', 'burst of sparks' => 'lightning', 'waft of heat' => 'fire', 'puff of rock dust' => 'earth', 'puff of mist' => 'water', } + + check_instability = proc { + if GameObj.loot.any? { |o| o.noun == 'instability' } + r = dothistimeout 'look instability', 10, /^The air is oddly warped and distorted here, almost as if something unseen was trying to push through from the other side of an invisible barrier\. Every so often a (?:gust of wind|burst of sparks|waft of heat|puff of rock dust|puff of mist) (?:is|are) emitted from the anomaly, which quickly reseals itself\./ + if r =~ /(gust of wind|burst of sparks|waft of heat|puff of rock dust|puff of mist)/ + element = to_element[$1] + unless GameSettings['recent-instabilities'].any? { |i| (i[:room_id] == Room.current.id) and i[:element] == element } + GameSettings['recent-instabilities'].push(:room_id => Room.current.id, :element => element, :first_seen => Time.now.to_i) + end + if (element == CharSettings['element']) + $mapdb_last_instability = Room.current.id + $mapdb_instability_timeto = Hash.new + for id in town_ids + path = Room[$mapdb_last_instability].path_to(id) + if path.nil? + $mapdb_instability_timeto[id] = nil + else + $mapdb_instability_timeto[id] = Map.estimate_time(path) + end + end + found_instability = true + end else - echo "error: can't get right" - exit + echo "error: can't get right" + exit end - end - - GameSettings['recent-instabilities'] ||= Array.new - - good_room_ids = Array.new - bad_room_ids = Array.new - got_room_text = false - to_element = { 'gust of wind' => 'air', 'burst of sparks' => 'lightning', 'waft of heat' => 'fire', 'puff of rock dust' => 'earth', 'puff of mist' => 'water', } - - check_instability = proc { - if GameObj.loot.any? { |o| o.noun == 'instability' } - r = dothistimeout 'look instability', 10, /^The air is oddly warped and distorted here, almost as if something unseen was trying to push through from the other side of an invisible barrier\. Every so often a (?:gust of wind|burst of sparks|waft of heat|puff of rock dust|puff of mist) (?:is|are) emitted from the anomaly, which quickly reseals itself\./ - if r =~ /(gust of wind|burst of sparks|waft of heat|puff of rock dust|puff of mist)/ - element = to_element[$1] - unless GameSettings['recent-instabilities'].any? { |i| (i[:room_id] == Room.current.id) and i[:element] == element } - GameSettings['recent-instabilities'].push(:room_id => Room.current.id, :element => element, :first_seen => Time.now.to_i) - end - if (element == CharSettings['element']) - $mapdb_last_instability = Room.current.id - $mapdb_instability_timeto = Hash.new - for id in town_ids - path = Room[$mapdb_last_instability].path_to(id) - if path.nil? - $mapdb_instability_timeto[id] = nil - else - $mapdb_instability_timeto[id] = Map.estimate_time(path) - end - end - found_instability = true - end - else - echo "error: can't get right" - exit - end + else + GameSettings['recent-instabilities'].delete_if { |i| i[:room_id] == Room.current.id } + false + end + } + + # + # go directly to nearby recently seen attuned instabilities + # + GameSettings['recent-instabilities'].delete_if { |i| i[:first_seen] < (Time.now.to_i - 21600) } + GameSettings['recent-instabilities'].find_all { |i| i[:element] == CharSettings['element'] }.each { |i| + # fixme: would one full dijkstra be faster? + if (path = Room.current.path_to(i[:room_id])) and (Map.estimate_time(path) <= 10.0) + Script.run('go2', i[:room_id].to_s, :force => true) + break if check_instability.call + end + } + + # + # get room numbers from attune sense + # + unless found_instability + if (last_roomdesc = $_SERVERBUFFER_.reverse.find { |line| line =~ /