From 84e4d39c7105aff883662a15f83b4251cb216157 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:07:57 -0500 Subject: [PATCH 01/15] fix(eloot.lic): v2.7.1 multiple fixes - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk --- scripts/eloot.lic | 133 ++++++++++++++++++++++++++++++++++------------ 1 file changed, 99 insertions(+), 34 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index e670d866a..30fbdac08 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -15,9 +15,12 @@ game: Gemstone tags: loot required: Lich >= 5.12.9 - version: 2.7.0 + version: 2.7.1 Improvements: Major_change.feature_addition.bugfix + v2.7.1 (2026-01-27) + - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) + - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -622,8 +625,7 @@ module ELoot # UI Setup loot_phase: { default: false }, use_disk: { default: true }, loot_defensive: { default: false }, - overflow_container: { default: '' }, - secondary_overflow: { default: '' }, + overflow_containers: { default: '' }, coin_hand_name: { default: '' }, charm_name: { default: '' }, sigil_determination_on_fail: { default: false }, @@ -743,6 +745,7 @@ module ELoot # UI Setup sell_aspect: { default: false }, sell_keep_silver: { default: 0 }, sell_deposit_coinhand: { default: false }, + trash_dump_types: { default: ["herb", "junk", "food"] }, }, skin: { skin_enable: { default: false }, @@ -948,11 +951,9 @@ module ELoot # UI Setup 00TrueTrue1515TrueOriginally from Mushroom Spore Giftbox 07/29/202301 TrueFalse2024Use Bloodtooth Bands(?)TrueTrueFalsestartTrue 04Use Group Disks(?)TrueTrueTruestartTrue11 - TrueFalseOther SettingsFalseTrue1TrueFalseTrueTrueFalse100TrueFalseTrueFalsestart55Primary Overflow:00 - 00TrueTrueEnter the name of your overflow container. This container will be used when the targeted STOW container is full.5155True - 01TrueFalsestart555Secondary Overflow:02 - TrueTrueEnter the name of your secondary overflow container. This container will be used when the primary overflow container is full.51510TrueFalse - 03TrueFalseOverflow Containers00TrueFalse100TrueFalseTrueFalsestart555Coin Bag / Coin Hand / Gambling Kit + TrueFalseOther SettingsFalseTrue1TrueFalseTrueTrueFalse100TrueFalseTrueFalsestart55(comma-separated):00 + 0065TrueTrue51510TrueinTrueTrueEnter comma-separated names of your overflow containers (e.g., "rucksack, cloak, orange pack"). These containers will be used in order when the targeted STOW container is full.wordFalse + 01TrueFalseOverflow Containers00TrueFalse100TrueFalseTrueFalsestart555Coin Bag / Coin Hand / Gambling Kit 00TrueTrue5155TrueName of item01 TrueFalsestart555Gambling Kit Silvers (?)02130TrueTruestart5100gambling_adjustment 03TrueFalseWeightless Coin Containers10FalseTrue2 @@ -1061,7 +1062,7 @@ module ELoot # UI Setup Share silversTrueTrueFalsestart55True20 TrueTruestart305300sell_keep_silver_adjustmentTrue312 TrueFalseOther Settings002FalseTrue3 - 3TrueFalseSelling3FalseTrueTrueinTrueFalseTrueFalse10150150TrueFalse50TrueFalsecenter5525Add80TrueTrueTruestart5 + TrueFalse100TrueFalse5525TrueAlchemyTrueTrueFalsestart5True00FoodTrueTrueFalsestartTrue10Locksmith TrapsTrueTrueFalsestartTrue20BoxTrueTrueFalsestartTrue30HerbTrueTrueFalsestart5True01ReagentTrueTrueFalsestartTrue11WandTrueTrueFalsestartTrue21BreakableTrueTrueFalsestartTrue31ClothingTrueTrueFalsestart5True02JunkTrueTrueFalsestartTrue12LockpickTrueTrueFalsestartTrue22TrueFalseTrash to DumpFalseTrue43TrueFalseSelling3FalseTrueTrueinTrueFalseTrueFalse10150150TrueFalse50TrueFalsecenter5525Add80TrueTrueTruestart5 00Delete80TrueTrueTrueend520 TrueTrueTrueEnter exclusion (e.g. uncut diamond)10200TrueTrue5555TrueinTrueFalseTrueTruesell_exclude_storeFalse0True fixedExclusion0013TrueFalseExclusions (?) @@ -1302,6 +1303,9 @@ module ELoot # UI Setup elsif obj.class == Gtk::Entry obj.text = @settings[key].strip obj.signal_connect('changed') { on_update(obj) } + elsif obj.class == Gtk::TextView + obj.buffer.text = @settings[key].to_s.strip + obj.buffer.signal_connect('changed') { on_update(obj) } elsif obj.class == Gtk::SpinButton obj.value = @settings[key] obj.adjustment.value = @settings[key] @@ -1501,6 +1505,8 @@ module ELoot # UI Setup end elsif obj.class == Gtk::Entry @settings[key] = obj.text.strip + elsif obj.class == Gtk::TextView + @settings[key] = obj.buffer.text.strip elsif obj.class == Gtk::SpinButton @settings[key] = obj.buffer.text end @@ -1757,6 +1763,26 @@ module ELoot # Profile loading/saving and settings @@data = Data.new(settings) end + def self.migrate_overflow_settings(settings) + # Migration helper: Convert old overflow_container and secondary_overflow to new overflow_containers format + if settings.key?(:overflow_container) || settings.key?(:secondary_overflow) + containers = [] + containers << settings[:overflow_container].to_s.strip unless settings[:overflow_container].to_s.strip.empty? + containers << settings[:secondary_overflow].to_s.strip unless settings[:secondary_overflow].to_s.strip.empty? + + unless containers.empty? + settings[:overflow_containers] = containers.join(', ') + ELoot.msg(text: " Migrated old overflow container settings to new format: #{settings[:overflow_containers]}") + end + + # Remove old keys + settings.delete(:overflow_container) + settings.delete(:secondary_overflow) + end + + settings + end + def self.load_defaults() default_hash = { :loot_types => ["alchemy", "armor", "box", "breakable", "clothing", "collectible", "food", "gem", "jewelry", "lockpick", "lm trap", "magic", "reagent", "scroll", "skin", "uncommon", "valuable", "wand"], @@ -1767,8 +1793,7 @@ module ELoot # Profile loading/saving and settings :coin_hand_name => "", :sigil_determination_on_fail => false, :charm_name => "", - :overflow_container => "", - :secondary_overflow => "", + :overflow_containers => "", :sell_loot_types => ["alchemy", "armor", "breakable", "clothing", "food", "gem", "jewelry", "lockpick", "magic", "reagent", "scroll", "skin", "uncommon", "valuable", "wand", "box", "lm trap"], :sell_container => ["default", "overflow", "box", "collectible", "forageable", "gem", "herb", "lockpick", "potion", "reagent", "scroll", "skin", "treasure", "trinket", "wand"], :sell_exclude => [], @@ -1791,6 +1816,7 @@ module ELoot # Profile loading/saving and settings :sell_shroud => false, :sell_aspect => false, :sell_keep_silver => 0, + :trash_dump_types => ["herb", "junk", "food"], :skin_enable => false, :skin_kneel => false, :skin_604 => false, @@ -1824,6 +1850,8 @@ module ELoot # Profile loading/saving and settings filename = File.join(DATA_DIR, XMLData.game, name, "eloot.yaml") if File.exist?(filename) && name == Char.name settings_hash = YAML.load_file(filename) + # Migrate old overflow settings to new format + settings_hash = ELoot.migrate_overflow_settings(settings_hash) elsif !File.exist?(filename) && name != Char.name ELoot.msg(type: "error", text: " ELoot.load_profile: Attempt to load a profile that does not exist.") elsif !File.exist?(filename) && name == Char.name @@ -2026,11 +2054,26 @@ module ELoot # Sets Inventory # Remove any extra keys and repopulate them ReadyList.ready_list.delete_if { |k, _| [:skin_weapon, :skin_weapon_blunt, :skin_sheath, :skin_sheath_blunt].include?(k) } - StowList.stow_list.delete_if { |k, _| [:overflow_container, :secondary_overflow, :appraisal_container].include?(k) } + # Remove old overflow container keys (they may use sequential numbering now) + StowList.stow_list.delete_if { |k, _| k.to_s.start_with?('overflow_container') || k == :appraisal_container } + + # Find the stow containers we need: overflow, appraisal + # Parse comma-separated overflow containers and add them dynamically + overflow_list = ELoot.data.settings[:overflow_containers].to_s.split(',').map(&:strip).reject(&:empty?) + overflow_list.each_with_index do |container_name, index| + # Create a unique key for each overflow container + key = index == 0 ? :overflow_container : "overflow_container_#{index + 1}".to_sym + # Temporarily set the setting for this specific container so ensure_items can find it + temp_settings_key = "overflow_temp_#{index}".to_sym + ELoot.data.settings[temp_settings_key] = container_name + ELoot.ensure_items(key: temp_settings_key, list: StowList.stow_list) + # Move the found item to the proper key + if StowList.stow_list[temp_settings_key] + StowList.stow_list[key] = StowList.stow_list.delete(temp_settings_key) + end + ELoot.data.settings.delete(temp_settings_key) + end - # Find the stow containers we need: stow, overflow, appraisal - ELoot.ensure_items(key: 'overflow_container', list: StowList.stow_list) - ELoot.ensure_items(key: 'secondary_overflow', list: StowList.stow_list) ELoot.ensure_items(key: 'appraisal_container', list: StowList.stow_list) # Find skin sheaths @@ -2090,10 +2133,10 @@ module ELoot # Sets Inventory container_array << StowList.default end - # Handle overflow containers + # Handle overflow containers - dynamically find all overflow container keys if ELoot.data.settings[:sell_container].include?("overflow") - [:overflow_container, :secondary_overflow].each do |key| - ELoot.ensure_items(key: key, list: StowList.stow_list) + overflow_keys = StowList.stow_list.keys.select { |k| k.to_s.start_with?('overflow_container') } + overflow_keys.each do |key| container = StowList.stow_list[key] container_array << container if container end @@ -2107,8 +2150,6 @@ module ELoot # Sets Inventory need_exit = false checks = [ - [:overflow_container, StowList.stow_list[:overflow_container], "primary overflow container"], - [:secondary_overflow, StowList.stow_list[:secondary_overflow], "secondary overflow container"], [:appraisal_container, StowList.stow_list[:appraisal_container], "appraisal container"], [:skin_sheath, ReadyList.ready_list[:skin_sheath], "bladed skinning sheath", :skin_enable], [:skin_sheath_blunt, ReadyList.ready_list[:skin_sheath_blunt], "blunt skinning sheath", :skin_enable], @@ -2118,13 +2159,26 @@ module ELoot # Sets Inventory [:charm_name, ELoot.data.charm, "fossil charm"], ] + # Dynamically add overflow container checks + overflow_list = ELoot.data.settings[:overflow_containers].to_s.split(',').map(&:strip).reject(&:empty?) + overflow_list.each_with_index do |container_name, index| + key = index == 0 ? :overflow_container : "overflow_container_#{index + 1}".to_sym + label = index == 0 ? "primary overflow container" : "overflow container #{index + 1}" + # For validation, we check against the overflow_containers setting (comma-separated list) + # but we look up the actual found object in StowList + if !container_name.empty? + checks << [:overflow_containers, StowList.stow_list[key], label] + end + end + checks.each do |setting_key, found_obj, label, conditional_key| # Only check if setting is non-empty and optional condition (like :skin_enable) is satisfied - next if ELoot.data.settings[setting_key].to_s.empty? + next if setting_key != :overflow_containers && ELoot.data.settings[setting_key].to_s.empty? next if conditional_key && !ELoot.data.settings[conditional_key] if found_obj.nil? - ELoot.msg(text: " Not able to find the #{label}: #{ELoot.data.settings[setting_key]}") + container_name = setting_key == :overflow_containers ? label.split(' ').last : ELoot.data.settings[setting_key] + ELoot.msg(text: " Not able to find the #{label}: #{container_name}") need_exit = true end end @@ -3345,8 +3399,12 @@ module ELoot # Inventory methods return unless ELoot.data.settings[:keep_closed] Inventory.open_single_container(StowList.stow_list[:default]) - Inventory.open_single_container(StowList.stow_list[:overflow_container]) - Inventory.open_single_container(StowList.stow_list[:secondary_overflow]) + + # Dynamically open all overflow containers + overflow_keys = StowList.stow_list.keys.select { |k| k.to_s.start_with?('overflow_container') } + overflow_keys.each do |key| + Inventory.open_single_container(StowList.stow_list[key]) + end containers = Array.new item.each { |loot| @@ -3433,14 +3491,19 @@ module ELoot # Inventory methods return if item&.name == "Empty" return if Inventory.single_drag_box(item) - # Try sacks in order of priority: item-specific, default, overflow, secondary overflow + # Try sacks in order of priority: item-specific, default, overflow containers (in order) containers = [ StowList.stow_list[item.type.to_sym], - StowList.stow_list[:default], - StowList.stow_list[:overflow_container], - StowList.stow_list[:secondary_overflow] + StowList.stow_list[:default] ] + # Dynamically add all overflow containers in order + overflow_keys = StowList.stow_list.keys.select { |k| k.to_s.start_with?('overflow_container') }.sort_by do |k| + # Sort by extracting number from key (overflow_container = 0, overflow_container_2 = 2, etc.) + k.to_s.match(/overflow_container_?(\d*)$/)[1].to_i + end + overflow_keys.each { |key| containers << StowList.stow_list[key] } + begin containers.each_with_index do |bag, index| if stunned? @@ -3451,14 +3514,16 @@ module ELoot # Inventory methods if bag.nil? case index + when 0 + # Skip if item-specific container not set (this is normal) when 1 ELoot.msg(type: "yellow", text: " No default container identified. This shouldn't happen.") ELoot.msg(type: "yellow", text: " Check your STOW settings. Exiting") exit - when 2 - ELoot.msg(type: "info", text: " Skipping primary overflow. No container identified.") - when 3 - ELoot.msg(type: "info", text: " Skipping secondary overflow. No container identified.") + else + # Overflow container not identified (this is normal if not all overflow containers are set) + overflow_num = index - 1 + ELoot.msg(type: "info", text: " Skipping overflow container #{overflow_num}. No container identified.") end else result = Inventory.store_item(bag, item) @@ -5733,8 +5798,8 @@ module ELoot # Sells the loot end def self.dump_herbs_junk - # Determine which types of loot we are supposed to dump - dump_stuff = ["herb", "junk", "food"].select { |type| ELoot.data.settings[:sell_loot_types].include?(type) } + # Determine which types of loot we are supposed to dump based on trash_dump_types setting + dump_stuff = ELoot.data.settings[:trash_dump_types].select { |type| ELoot.data.settings[:sell_loot_types].include?(type) } alchemy_regex = /^(some ground|flask of pure water|some powdered|some mashed|handful of sea salt|spirit shard|tincture of)/ # Collect items to dump From a71929d37ca0293ac5fc30ff0a5063e0ced2a9bf Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 28 Jan 2026 09:29:28 -0500 Subject: [PATCH 02/15] fix: add tooltip to new trash to dump section --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 30fbdac08..6a09da382 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -1062,7 +1062,7 @@ module ELoot # UI Setup Share silversTrueTrueFalsestart55True20 TrueTruestart305300sell_keep_silver_adjustmentTrue312 TrueFalseOther Settings002FalseTrue3 - TrueFalse100TrueFalse5525TrueAlchemyTrueTrueFalsestart5True00FoodTrueTrueFalsestartTrue10Locksmith TrapsTrueTrueFalsestartTrue20BoxTrueTrueFalsestartTrue30HerbTrueTrueFalsestart5True01ReagentTrueTrueFalsestartTrue11WandTrueTrueFalsestartTrue21BreakableTrueTrueFalsestartTrue31ClothingTrueTrueFalsestart5True02JunkTrueTrueFalsestartTrue12LockpickTrueTrueFalsestartTrue22TrueFalseTrash to DumpFalseTrue43TrueFalseSelling3FalseTrueTrueinTrueFalseTrueFalse10150150TrueFalse50TrueFalsecenter5525Add80TrueTrueTruestart5 + TrueFalse100TrueFalse5525TrueAlchemyTrueTrueFalsestart5True00FoodTrueTrueFalsestartTrue10Locksmith TrapsTrueTrueFalsestartTrue20BoxTrueTrueFalsestartTrue30HerbTrueTrueFalsestart5True01ReagentTrueTrueFalsestartTrue11WandTrueTrueFalsestartTrue21BreakableTrueTrueFalsestartTrue31ClothingTrueTrueFalsestart5True02JunkTrueTrueFalsestartTrue12LockpickTrueTrueFalsestartTrue22TrueFalseTrash to Dump (?)Will attempt to TRASH type after selling is done, requires type to be enabled for selling to dumpFalseTrue43TrueFalseSelling3FalseTrueTrueinTrueFalseTrueFalse10150150TrueFalse50TrueFalsecenter5525Add80TrueTrueTruestart5 00Delete80TrueTrueTrueend520 TrueTrueTrueEnter exclusion (e.g. uncut diamond)10200TrueTrue5555TrueinTrueFalseTrueTruesell_exclude_storeFalse0True fixedExclusion0013TrueFalseExclusions (?) From bf474dfa4b5df2717aaf5957cb857faa948c5f63 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 30 Jan 2026 09:42:59 -0500 Subject: [PATCH 03/15] fix: between script(s) added erroneous commas between script parameters --- scripts/eloot.lic | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 6a09da382..a0b321074 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -21,6 +21,7 @@ v2.7.1 (2026-01-27) - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk + - bugfix inbetween script(s) added erroneous commas between script parameters v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -6199,7 +6200,7 @@ module ELoot # Sells the loot ELoot.data.settings[:between].each do |i| tokens = i.split(/\s+/) if (tokens.size > 1) - Script.run(tokens[0], tokens[1..-1].join(", ")) + Script.run(tokens[0], tokens[1..-1].join(" ")) else Script.run(tokens[0]) end From fe6a9655a4ca41e620a04ebca227b046157a8e22 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 30 Jan 2026 16:32:09 -0500 Subject: [PATCH 04/15] fix rubocop --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index a0b321074..be5f314f7 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -21,7 +21,7 @@ v2.7.1 (2026-01-27) - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk - - bugfix inbetween script(s) added erroneous commas between script parameters + - bugfix inbetween script(s) added erroneous commas between script parameters v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes From bdb422bb488150a1f7d83f90f0e8805895db0542 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Sat, 31 Jan 2026 20:04:53 -0500 Subject: [PATCH 05/15] fix: update gem/alchemy to support new overflow structure force saving of migrated settings for overflow upon migration --- scripts/eloot.lic | 57 ++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index be5f314f7..c263667f2 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -806,7 +806,8 @@ module ELoot # UI Setup gem_everything_list: { default: false }, gem_only_list: { default: false }, gem_horde_container: { default: '' }, - gem_horde_containers: { default: ['default', 'gem', 'overflow1', 'overflow2'] }, + gem_horde_containers: { default: ['default', 'gem'] }, + gem_horde_use_overflow: { default: false }, gem_locker: { default: '' }, gem_locker_name: { default: '' }, gem_horde_locker_che: { default: false }, @@ -859,7 +860,8 @@ module ELoot # UI Setup alchemy_everything_list: { default: false }, alchemy_only_list: { default: false }, alchemy_horde_container: { default: '' }, - alchemy_horde_containers: { default: ['default', 'reagent', 'overflow1', 'overflow2'] }, + alchemy_horde_containers: { default: ['default', 'reagent'] }, + alchemy_horde_use_overflow: { default: false }, alchemy_locker: { default: '' }, alchemy_locker_name: { default: '' }, alchemy_horde_locker_che: { default: false }, @@ -1101,9 +1103,8 @@ module ELoot # UI Setup 00TrueFalseend10Entry Verb01TrueFalseend10Exit Verb 0214TrueFalsestartstart1520 04TrueFalseGeneral SettingsFalseTrue0TrueFalse50TrueFalseTrueDefaultTrueTrueFalsestart101010True - 00First OverflowTrueTrueFalsestart55True - 20Second OverflowTrueTrueFalsestart55True - 30GemTrueTrueFalsestart55True + 00Use All Overflow ContainersTrueTrueFalsestart55True + 20GemTrueTrueFalsestart55True 10TrueFalseOnly Hoard Gems from these ContainersFalseTrue1 TrueFalse50TrueFalseHoard all gems except those excluded belowTrueTrueFalsestart1010True 00ONLY hoard gems listed belowTrueTrueFalsestart1010True @@ -1130,9 +1131,8 @@ module ELoot # UI Setup 0214Hoard reagents in a house locker?TrueTrueFalsestartend201010True 13TrueFalsestartstart152004 TrueFalseGeneral SettingsFalseTrue0TrueFalse50TrueFalseTrueDefaultTrueTrueFalsestart101010True - 00First OverflowTrueTrueFalsestart55True - 20Second OverflowTrueTrueFalsestart55True - 30ReagentTrueTrueFalsestart55True + 00Use All Overflow ContainersTrueTrueFalsestart55True + 20ReagentTrueTrueFalsestart55True 10TrueFalseOnly Hoard Alchemy Ingredients from these ContainersFalseTrue1 TrueFalse50TrueFalseHoard all alchemy ingredients except those excluded belowTrueTrueFalsestart1010True 00ONLY hoard alchemy ingredients listed belowTrueTrueFalsestart1010True @@ -1765,6 +1765,7 @@ module ELoot # Profile loading/saving and settings end def self.migrate_overflow_settings(settings) + migrated_settings = false # Migration helper: Convert old overflow_container and secondary_overflow to new overflow_containers format if settings.key?(:overflow_container) || settings.key?(:secondary_overflow) containers = [] @@ -1779,8 +1780,39 @@ module ELoot # Profile loading/saving and settings # Remove old keys settings.delete(:overflow_container) settings.delete(:secondary_overflow) + migrated_settings = true end + # Migration: Convert old gem/alchemy hoarding overflow checkboxes to new use_overflow boolean + ['gem', 'alchemy'].each do |type| + containers_key = "#{type}_horde_containers".to_sym + use_overflow_key = "#{type}_horde_use_overflow".to_sym + + # Check if the old format with overflow1/overflow2 is present in the containers array + if settings[containers_key] && settings[containers_key].is_a?(Array) + old_containers = settings[containers_key] + + # Check if overflow1 or overflow2 are in the array + has_overflow = old_containers.include?('overflow1') || old_containers.include?('overflow2') + + if has_overflow + # Set the new use_overflow boolean to true + settings[use_overflow_key] = true + + # Remove overflow1 and overflow2 from the array + settings[containers_key] = old_containers.reject { |c| c == 'overflow1' || c == 'overflow2' } + + ELoot.msg(text: " Migrated #{type} hoarding overflow settings: enabled 'Use All Overflow Containers'") + migrated_settings = true + elsif !settings.key?(use_overflow_key) + # If the key doesn't exist and no old overflows were found, set to false + settings[use_overflow_key] = false + migrated_settings = true + end + end + end + + ELoot.save_profile() if migrated_settings settings end @@ -4311,8 +4343,17 @@ module ELoot # Gem and Reagent hoarding ELoot.data.items_to_hoard = [] obj_type = ELoot.data.hoard_type == 'alchemy' ? 'reagent' : ELoot.data.hoard_type + # Get containers from the container_settings array item_containers = ELoot.data.container_settings.filter_map { |key| StowList.stow_list[key.to_sym] } + # If use_overflow is enabled, dynamically add all overflow containers + use_overflow_key = "#{ELoot.data.hoard_type}_horde_use_overflow".to_sym + if ELoot.data.settings[use_overflow_key] + overflow_keys = StowList.stow_list.keys.select { |k| k.to_s.start_with?('overflow_container') } + overflow_containers = overflow_keys.filter_map { |key| StowList.stow_list[key] } + item_containers.concat(overflow_containers) + end + item_containers.each do |container| next unless container From 967cef513a218dc2c1db3c735b1c21913817d224 Mon Sep 17 00:00:00 2001 From: Deysh <61760541+Deysh@users.noreply.github.com> Date: Sun, 1 Feb 2026 06:33:47 -0500 Subject: [PATCH 06/15] Modify total tips calculation for locksmith Updated the total tips calculation to include a custom withdraw amount setting for the locksmith. --- scripts/eloot.lic | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index c263667f2..eed54b124 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -22,6 +22,7 @@ - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk - bugfix inbetween script(s) added erroneous commas between script parameters + - allow custom tip amount v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -981,7 +982,7 @@ module ELoot # UI Setup 00Use town locksmithTrueTrueFalsestart510True 01Display box contentsTrueTrueFalsestart510True 11Always check pool (?)TrueTrueFalsestart510True - 10TrueFalsestart1010Locksmith Withdraw Amount03 + 10TrueFalsestart1010Bank Withdraw Amount03 TrueTrueHow much to withdraw from the bank before going to the town locksmith.start10105locksmith_withdraw_amount_adjustment 04Default to using locksmith when gem bounty activeTrueTrueFalse510True 022TrueFalseLocksmithing00 @@ -6358,7 +6359,7 @@ module ELoot # Sells the loot pool_count = handle_full_pool(worker) { return true if deposit } return if pool_count > 99 else - total_tips = Sell.locksmith_determine_tip(pool_count + 1, boxes.length) + 15_000 + total_tips = Sell.locksmith_determine_tip(pool_count + 1, boxes.length) + ELoot.data.settings[:locksmith_withdraw_amount] ELoot.silver_withdraw(total_tips) ELoot.go2(original_pool) worker = ELoot.find_worker From 79c926e7d331ecdd73cb21ed1e2bb32b0b358ae8 Mon Sep 17 00:00:00 2001 From: Deysh <61760541+Deysh@users.noreply.github.com> Date: Sun, 1 Feb 2026 07:33:54 -0500 Subject: [PATCH 07/15] bugfix for box group looting msg and box disk storage --- scripts/eloot.lic | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index eed54b124..1c66694bf 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -22,7 +22,10 @@ - replaced overflow_container and secondary_overflow with single overflow_containers setting (comma-separated) - added configurable "Trash to Dump" section, instead of hardcoded herb/food/junk - bugfix inbetween script(s) added erroneous commas between script parameters - - allow custom tip amount + - allow custom bank withdraw amount + - bugfix when trying to store box in non-group disk + - bugfix in box_loot_ground locked box message + - bugfix in single_drag_box cycling thru all group disks even when use_disk_group was false v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -3600,6 +3603,7 @@ module ELoot # Inventory methods ELoot.wait_for_disk unless ELoot.data.disk.nil? # sort to prioritize characters disk + disks = disks.select { |d| d.name == Char.name } unless ELoot.data.settings[:use_disk_group] disks = Group.disks.sort_by { |d| d.name == Char.name ? 0 : 1 } disks.each do |disk| next if ELoot.data.disk_full[disk.name] # make sure its not full @@ -3679,7 +3683,10 @@ module ELoot # Inventory methods lines = ELoot.get_command("_drag ##{item.id} ##{bag.id}", ELoot.data.put_regex) end - return true if lines.any? { |l| l =~ /You are unable to handle|That is not yours|Hey, that belongs to|Get what|I could not find what you were referring/ } + lines.each do |line| + return false if line.match?(/Hey, that belongs to/) + return true if line.match?(/You are unable to handle|That is not yours|Get what|I could not find what you were referring/) + end if lines.any? { |l| l =~ /put something that you can't hold/ } ELoot.unlootable(item) @@ -4671,7 +4678,7 @@ module ELoot # Room looting box_list.each do |box| line = ELoot.get_res("open ##{box.id}", /open|locked/) - next if line&.match?(/That is locked/) + next if line&.match?(/It appears to be locked/) quiet_msg = ELoot.data.settings[:display_box_contents] ? false : true ELoot.get_command("look in ##{box.id}", ELoot.data.look_regex, silent: quiet_msg, quiet: quiet_msg) From f5a8a1c5e669bb9d62c6ac658838b6e96879cd2d Mon Sep 17 00:00:00 2001 From: Deysh <61760541+Deysh@users.noreply.github.com> Date: Sun, 1 Feb 2026 07:44:44 -0500 Subject: [PATCH 08/15] Refactor disk sorting to use sort_by! method and rubocop --- scripts/eloot.lic | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 1c66694bf..aa61b91c1 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -3603,8 +3603,9 @@ module ELoot # Inventory methods ELoot.wait_for_disk unless ELoot.data.disk.nil? # sort to prioritize characters disk + disks = Group.disks disks = disks.select { |d| d.name == Char.name } unless ELoot.data.settings[:use_disk_group] - disks = Group.disks.sort_by { |d| d.name == Char.name ? 0 : 1 } + disks.sort_by! { |d| d.name == Char.name ? 0 : 1 } disks.each do |disk| next if ELoot.data.disk_full[disk.name] # make sure its not full next unless Disk.find_by_name(disk.name) # skip the disk unless its present From c47f050d173f0248ab692d650d729130ceeadf79 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 4 Feb 2026 16:35:02 -0500 Subject: [PATCH 09/15] fix: bugfix for eonake gauntlet missing XML to properly match --- scripts/eloot.lic | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index aa61b91c1..68a4ad5e5 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -26,6 +26,7 @@ - bugfix when trying to store box in non-group disk - bugfix in box_loot_ground locked box message - bugfix in single_drag_box cycling thru all group disks even when use_disk_group was false + - bugfix for eonake gauntlet missing XML to properly match v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -2728,7 +2729,7 @@ module ELoot # Game utility type methods end unless ELoot.data.gauntlet.nil? - lines = ELoot.get_command("look ##{ELoot.data.gauntlet.id}", /You are currently wearing the eonake gauntlet/, silent: true, quiet: true) + lines = ELoot.get_command("look ##{ELoot.data.gauntlet.id}", /You are currently wearing the eonake gauntlet<\/a>/, silent: true, quiet: true) if lines.any? { |l| l =~ /(right|left) hand/ } gauntlet_hand = Regexp.last_match(1) end From fe806e86e86795c976b3ad04307e4b8e1b1d74a5 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Thu, 5 Feb 2026 09:31:15 -0500 Subject: [PATCH 10/15] fix: refactor in_region method and fix bug in destination check Refactor in_region method to improve boundary check logic and add a bugfix for destination room check. --- scripts/eloot.lic | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 68a4ad5e5..b9aa2411d 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -27,6 +27,7 @@ - bugfix in box_loot_ground locked box message - bugfix in single_drag_box cycling thru all group disks even when use_disk_group was false - bugfix for eonake gauntlet missing XML to properly match + - bugfix for in_region check if already in destination room v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -2276,9 +2277,20 @@ module ELoot # Regional bounty Selling self.by_town(tag).find { |k, _v| k.downcase.include?(town.downcase) }.last end - def self.in_region(place) # Determine if the bounty town is within the characters region + def self.in_region(place) ELoot.msg(type: "debug", text: "place: #{place}") - # vaalor ferry, west cart, east cart, RR boot + + bounty_town = Bounty.town == "Cold River" ? "Hinterwilds" : Bounty.town + place = self.tag_for_town(bounty_town, place).id + + # Early return if already at destination + return place if Room.current == Room[place] + + # Calculate path once + path = Room.current.path_to(Room[place]) + return nil unless path + + # Lazy evaluation - only compute boundaries if we need to check them boundaries = [ Map.ids_from_uid(14001002).first, # Ta'Vaalor Ferry Map.ids_from_uid(13002021).first, # Western Spine Mine Cart @@ -2296,12 +2308,8 @@ module ELoot # Regional bounty Selling Map.ids_from_uid(7133026).first, # Portmaster - Icemule Trace ] - bounty_town = Bounty.town == "Cold River" ? "Hinterwilds" : Bounty.town - - place = self.tag_for_town(bounty_town, place).id - path = Room.current.path_to(Room[place]) - - return place if path && boundaries.none? { |fence| path.include?(fence) } + # Use array intersection instead of iterating through each boundary + (path & boundaries).empty? ? place : nil end def self.furrier From 2287bf0527cae3e4ce94b3b6cac08fe7c8efc28c Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Thu, 5 Feb 2026 09:32:22 -0500 Subject: [PATCH 11/15] docs: add clarification comment in in_region method Add comment to clarify bounty town region check --- scripts/eloot.lic | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index b9aa2411d..f92aefb25 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2277,6 +2277,7 @@ module ELoot # Regional bounty Selling self.by_town(tag).find { |k, _v| k.downcase.include?(town.downcase) }.last end + # Determine if the bounty town is within the characters region def self.in_region(place) ELoot.msg(type: "debug", text: "place: #{place}") From 0b215b2e2591093778ec8afdbfe1579c177684aa Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Thu, 5 Feb 2026 09:34:21 -0500 Subject: [PATCH 12/15] refactor: string comparison for bounty town and current room --- scripts/eloot.lic | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index f92aefb25..4dd538e3e 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2278,14 +2278,15 @@ module ELoot # Regional bounty Selling end # Determine if the bounty town is within the characters region + # vaalor ferry, west cart, east cart, RR boot def self.in_region(place) ELoot.msg(type: "debug", text: "place: #{place}") - bounty_town = Bounty.town == "Cold River" ? "Hinterwilds" : Bounty.town + bounty_town = Bounty.town.eql?("Cold River") ? "Hinterwilds" : Bounty.town place = self.tag_for_town(bounty_town, place).id # Early return if already at destination - return place if Room.current == Room[place] + return place if Room.current.eql?(Room[place]) # Calculate path once path = Room.current.path_to(Room[place]) From 8cd39f00dc44dabdb64dde6380a777df57336cd7 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Sat, 7 Feb 2026 11:27:26 -0500 Subject: [PATCH 13/15] fix: reset sacks full when using --sellable/type/sell CLI --- scripts/eloot.lic | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 4dd538e3e..8087fd9eb 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -28,6 +28,7 @@ - bugfix in single_drag_box cycling thru all group disks even when use_disk_group was false - bugfix for eonake gauntlet missing XML to properly match - bugfix for in_region check if already in destination room + - reset sacks full when using --sellable/type/sell CLI v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -6962,10 +6963,15 @@ module ELoot # Starts the script type = Regexp.last_match(1) things = Regexp.last_match(2) + ELoot.data.sacks_full = [] + ELoot::Sell.box_in_hand(false) + ELoot::Sell.custom_sellable(things) if type == 'sellable' ELoot::Sell.custom_type(things) if type == 'type' ELoot::Sell.custom_list(things) if type == 'sell' + ELoot.data.sacks_full = [] + ELoot.go2(ELoot.data.start_room) ELoot::Sell.breakdown when /settings|setup/i From 014aa4d4419ebfb16169bcb6ba6ca8c9c373befd Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Sun, 8 Feb 2026 14:51:21 -0500 Subject: [PATCH 14/15] fix: LOOT match for quest corpse looting --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 8087fd9eb..9cf42db36 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -5037,7 +5037,7 @@ module ELoot # Room looting # Loot it 3.times do waitrt? - results = ELoot.get_command("loot ##{thing.id}", /You (search|plunge|break)|not in any condition|see well enough to search|You can only loot creatures|Geez! It's still alive! Not a good time for that\./, silent: false, quiet: false) + results = ELoot.get_command("loot ##{thing.id}", /You (search|plunge|break)|not in any condition|see well enough to search|You can only loot creatures|Geez! It's still alive! Not a good time for that\.|As you move to search/, silent: false, quiet: false) ELoot.msg(type: "debug", text: "Thing: #{thing.id}-#{thing.name}, Results: #{results.first}") if results.any? { |line| line =~ /not in any condition/ } && From c6b2e672ac85ece3ff11e79b6c190aebcb47f136 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 9 Feb 2026 16:06:46 -0500 Subject: [PATCH 15/15] fix: dump/trash to respect sell_exclude items --- scripts/eloot.lic | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 9cf42db36..f1c3c8fb7 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -5869,6 +5869,7 @@ module ELoot # Sells the loot dump_items = ELoot.set_selling_containers.flat_map(&:contents).select do |item| next false unless dump_stuff.any? { |type| item.type =~ /#{type}/ } || (ELoot.data.alchemy_mode && item.name =~ alchemy_regex) next false if ELoot.data.alchemy_mode && Vars.needed_reagents.any? { |r| item.name =~ /#{r}/ } + next false if !ELoot.data.settings[:sell_exclude].empty? && item.name =~ /#{ELoot.data.settings[:sell_exclude].join('|')}/ true end