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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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/40] 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 From 2244b73302b2008719f3d936bba5aa5383dbd5a2 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 16 Feb 2026 19:17:37 -0500 Subject: [PATCH 16/40] fix: add hoarding of specific valuable items, expand sacks_full debug output --- scripts/eloot.lic | 126 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 89 insertions(+), 37 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index f1c3c8fb7..f83f03bb1 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -29,6 +29,7 @@ - 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 + - update hoard gems to support specific valuable types (shell/tooth) v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -256,7 +257,7 @@ module ELoot # Data # inventory type @sacks_closed = [] - @sacks_full = [] + @sacks_full = {} @checked_bags = [] @sell_containers = [] @ready_lines = [] @@ -2556,7 +2557,7 @@ module ELoot # Script utility type methods rows << [{ value: " *** Full Disk/Sack Check ***", colspan: 7 }] rows << :separator rows << [{ value: "Disk Full: #{ELoot.data.disk_full.inspect}", colspan: 7 }] - rows << [{ value: "Sacks Full: #{ELoot.data.sacks_full.map(&:name)}", colspan: 7 }] + rows << [{ value: "Sacks Full: #{ELoot.data.sacks_full}", colspan: 7 }] rows << :separator rows << [{ value: " *** Contents ***", colspan: 7 }] @@ -3559,7 +3560,7 @@ module ELoot # Inventory methods ELoot.wait_rt raise end - next if ELoot.data.sacks_full.include?(bag) + next if ELoot.data.sacks_full.keys.include?(bag.name) if bag.nil? case index @@ -3595,7 +3596,7 @@ module ELoot # Inventory methods ELoot.msg(type: "info", text: " Failed to store the #{item.name}.") ELoot.msg(type: "info", text: " Pausing the script to handle it yourself") ELoot.msg(type: "info", text: " ;unpause #{Script.current.name} after addressing to continue!") - + ELoot.msg(type: "debug", text: " Sacks Full: #{ELoot.data.sacks_full}") unless ELoot.data.sacks_full.empty? Script.current.pause end end @@ -3640,9 +3641,9 @@ module ELoot # Inventory methods # loot item will fallback to the default sack but if both are full we need to loot manually bag = StowList.stow_list[item.type.to_sym] - bag = nil if bag.nil? || ELoot.data.sacks_full.include?(bag) + bag = nil if bag.nil? || ELoot.data.sacks_full.keys.include?(bag.name) bag ||= StowList.stow_list[:default] - bag = nil if bag.nil? || ELoot.data.sacks_full.include?(bag) + bag = nil if bag.nil? || ELoot.data.sacks_full.keys.include?(bag.name) unless bag Inventory.single_drag(item) @@ -3710,7 +3711,7 @@ module ELoot # Inventory methods if lines.any? { |l| l =~ /won't fit/i } unless item.name =~ /gold ingot/ ELoot.msg(type: "debug", text: "sacks_full(#{bag.name}) - item: #{item.inspect}") - ELoot.data.sacks_full.push(bag) + ELoot.data.sacks_full[bag.name] = [Time.now, item] end return false end @@ -3812,25 +3813,47 @@ module ELoot # Gem and Reagent hoarding def self.check_type(item) obj_type = ELoot.data.hoard_type == 'alchemy' ? 'reagent' : ELoot.data.hoard_type - + item = item.gsub(/teeth/, "tooth") noun = item.split.last - - if item =~ GameObj.type_data[obj_type][:exclusion] - return false - elsif GameObj.type_data[obj_type][:name].to_s.match?(/\b#{item}\b/) || GameObj.type_data[obj_type][:noun].to_s.match?(/\b#{noun}\b/) - return true - elsif item =~ GameObj.type_data[obj_type][:name] || noun =~ GameObj.type_data[obj_type][:noun] - return true - elsif obj_type == 'reagent' && Room.list.any? { |r| r.tags.any? { |tag| (tag.end_with? item) || ((item.start_with? tag) && item =~ /ayana/) || (item.end_with? tag) } } - return true - elsif obj_type == 'reagent' && item =~ /kezmonian honey beryl|faintly glimmering dust/i - return true - elsif obj_type == 'gem' && item =~ /(?:deep blue sapphire|fiery ruby|glistening onyx|sparkling emerald) talon/i - return true - else - return false - end + + # Cache the lookup - accessed multiple times + type_data = GameObj.type_data[obj_type] + + # Early return on exclusion + return false if type_data[:exclusion]&.match?(item) + + # Check standard name/noun matches + return true if type_data[:name]&.match?(item) || type_data[:noun]&.match?(noun) + + # Reagent-specific checks + if obj_type == 'reagent' + return true if Room.list.any? { |r| r.tags.any? { |tag| tag.end_with?(item) || (item.start_with?(tag) && item.match?(/ayana/)) || item.end_with?(tag) } } + return true if item.match?(/kezmonian honey beryl|faintly glimmering dust/i) + end + + # Gem-specific checks + if obj_type == 'gem' + return true if item.match?(/(?:deep blue sapphire|fiery ruby|glistening onyx|sparkling emerald) talon/i) + + if %w[shell tooth].include?(noun) + valuable_data = GameObj.type_data["valuable"] + return true if valuable_data[:name]&.match?(item) || valuable_data[:noun]&.match?(noun) + end + end + + false + end + + # Helper method to check if an item is a gem or gem-like valuable (shell/tooth) + def self.gem_or_valuable?(item) + return true if item.type =~ /gem/ + return false unless item.type =~ /valuable/ + + # Check if it's a shell or tooth + item_name = item.is_a?(GameObj) ? item.name : item.to_s + noun = item_name.split.last + %w[shell tooth].include?(noun) end def self.normalize_name(name) @@ -4288,8 +4311,19 @@ module ELoot # Gem and Reagent hoarding # Refresh the cache because lockers are special ELoot.get_command("look in ##{ELoot.data.stash.id}", / Date: Mon, 16 Feb 2026 19:22:52 -0500 Subject: [PATCH 17/40] fix: rubocop --- scripts/eloot.lic | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index f83f03bb1..c4180e35b 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -3813,35 +3813,35 @@ module ELoot # Gem and Reagent hoarding def self.check_type(item) obj_type = ELoot.data.hoard_type == 'alchemy' ? 'reagent' : ELoot.data.hoard_type - + item = item.gsub(/teeth/, "tooth") noun = item.split.last - + # Cache the lookup - accessed multiple times type_data = GameObj.type_data[obj_type] - + # Early return on exclusion return false if type_data[:exclusion]&.match?(item) - + # Check standard name/noun matches return true if type_data[:name]&.match?(item) || type_data[:noun]&.match?(noun) - + # Reagent-specific checks if obj_type == 'reagent' return true if Room.list.any? { |r| r.tags.any? { |tag| tag.end_with?(item) || (item.start_with?(tag) && item.match?(/ayana/)) || item.end_with?(tag) } } return true if item.match?(/kezmonian honey beryl|faintly glimmering dust/i) end - + # Gem-specific checks if obj_type == 'gem' return true if item.match?(/(?:deep blue sapphire|fiery ruby|glistening onyx|sparkling emerald) talon/i) - + if %w[shell tooth].include?(noun) valuable_data = GameObj.type_data["valuable"] return true if valuable_data[:name]&.match?(item) || valuable_data[:noun]&.match?(noun) end end - + false end @@ -3849,7 +3849,7 @@ module ELoot # Gem and Reagent hoarding def self.gem_or_valuable?(item) return true if item.type =~ /gem/ return false unless item.type =~ /valuable/ - + # Check if it's a shell or tooth item_name = item.is_a?(GameObj) ? item.name : item.to_s noun = item_name.split.last @@ -4318,10 +4318,10 @@ module ELoot # Gem and Reagent hoarding elsif name =~ /teeth$/ search_names << name.sub(/teeth$/, 'tooth') end - + jar = ELoot.data.stash.contents.find do |obj| - obj.noun =~ /^(?:jar|bottle|beaker)$/ && - search_names.any? { |n| Hoard.normalize_name(obj.after_name) =~ /^#{Regexp.escape(n)}$/i } + obj.noun =~ /^(?:jar|bottle|beaker)$/ && + search_names.any? { |n| Hoard.normalize_name(obj.after_name) =~ /^#{Regexp.escape(n)}$/i } end ELoot.msg(type: "debug", text: "jar: #{jar.inspect} | search_names: #{search_names}") @@ -4503,10 +4503,10 @@ module ELoot # Gem and Reagent hoarding elsif item_name =~ /teeth$/ search_names << item_name.sub(/teeth$/, 'tooth') end - + bottle = ELoot.data.stash.contents.find do |obj| - obj.noun =~ /^(?:jar|bottle|beaker)$/ && - search_names.any? { |name| Hoard.normalize_name(obj.after_name) =~ /^#{Regexp.escape(name)}$/i } + obj.noun =~ /^(?:jar|bottle|beaker)$/ && + search_names.any? { |name| Hoard.normalize_name(obj.after_name) =~ /^#{Regexp.escape(name)}$/i } end ELoot.msg(type: "debug", text: "bottle: #{bottle.inspect} | search_names: #{search_names}") From a4cbcabdc7bb6125fa9d0618083422f4be631761 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Tue, 17 Feb 2026 08:57:58 -0500 Subject: [PATCH 18/40] revert: hoard gem/valuable changes --- scripts/eloot.lic | 95 +++++++++++------------------------------------ 1 file changed, 22 insertions(+), 73 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index c4180e35b..bfcd35cea 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -29,7 +29,6 @@ - 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 - - update hoard gems to support specific valuable types (shell/tooth) v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -3597,6 +3596,7 @@ module ELoot # Inventory methods ELoot.msg(type: "info", text: " Pausing the script to handle it yourself") ELoot.msg(type: "info", text: " ;unpause #{Script.current.name} after addressing to continue!") ELoot.msg(type: "debug", text: " Sacks Full: #{ELoot.data.sacks_full}") unless ELoot.data.sacks_full.empty? + Script.current.pause end end @@ -3817,43 +3817,21 @@ module ELoot # Gem and Reagent hoarding item = item.gsub(/teeth/, "tooth") noun = item.split.last - # Cache the lookup - accessed multiple times - type_data = GameObj.type_data[obj_type] - - # Early return on exclusion - return false if type_data[:exclusion]&.match?(item) - - # Check standard name/noun matches - return true if type_data[:name]&.match?(item) || type_data[:noun]&.match?(noun) - - # Reagent-specific checks - if obj_type == 'reagent' - return true if Room.list.any? { |r| r.tags.any? { |tag| tag.end_with?(item) || (item.start_with?(tag) && item.match?(/ayana/)) || item.end_with?(tag) } } - return true if item.match?(/kezmonian honey beryl|faintly glimmering dust/i) - end - - # Gem-specific checks - if obj_type == 'gem' - return true if item.match?(/(?:deep blue sapphire|fiery ruby|glistening onyx|sparkling emerald) talon/i) - - if %w[shell tooth].include?(noun) - valuable_data = GameObj.type_data["valuable"] - return true if valuable_data[:name]&.match?(item) || valuable_data[:noun]&.match?(noun) - end + if item =~ GameObj.type_data[obj_type][:exclusion] + return false + elsif GameObj.type_data[obj_type][:name].to_s.match?(/\b#{item}\b/) || GameObj.type_data[obj_type][:noun].to_s.match?(/\b#{noun}\b/) + return true + elsif item =~ GameObj.type_data[obj_type][:name] || noun =~ GameObj.type_data[obj_type][:noun] + return true + elsif obj_type == 'reagent' && Room.list.any? { |r| r.tags.any? { |tag| (tag.end_with? item) || ((item.start_with? tag) && item =~ /ayana/) || (item.end_with? tag) } } + return true + elsif obj_type == 'reagent' && item =~ /kezmonian honey beryl|faintly glimmering dust/i + return true + elsif obj_type == 'gem' && item =~ /(?:deep blue sapphire|fiery ruby|glistening onyx|sparkling emerald) talon/i + return true + else + return false end - - false - end - - # Helper method to check if an item is a gem or gem-like valuable (shell/tooth) - def self.gem_or_valuable?(item) - return true if item.type =~ /gem/ - return false unless item.type =~ /valuable/ - - # Check if it's a shell or tooth - item_name = item.is_a?(GameObj) ? item.name : item.to_s - noun = item_name.split.last - %w[shell tooth].include?(noun) end def self.normalize_name(name) @@ -4311,19 +4289,8 @@ module ELoot # Gem and Reagent hoarding # Refresh the cache because lockers are special ELoot.get_command("look in ##{ELoot.data.stash.id}", / Date: Tue, 17 Feb 2026 09:17:02 -0500 Subject: [PATCH 19/40] fix: expand sacks_full info output --- scripts/eloot.lic | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index bfcd35cea..41c32fcc3 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -256,7 +256,7 @@ module ELoot # Data # inventory type @sacks_closed = [] - @sacks_full = {} + @sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } @checked_bags = [] @sell_containers = [] @ready_lines = [] @@ -2556,7 +2556,9 @@ module ELoot # Script utility type methods rows << [{ value: " *** Full Disk/Sack Check ***", colspan: 7 }] rows << :separator rows << [{ value: "Disk Full: #{ELoot.data.disk_full.inspect}", colspan: 7 }] - rows << [{ value: "Sacks Full: #{ELoot.data.sacks_full}", colspan: 7 }] + ELoot.data.sacks_full.each do |container, information| + rows << [{ value: "Sacks Full[#{container}]: #{information}", colspan: 7 }] + end rows << :separator rows << [{ value: " *** Contents ***", colspan: 7 }] @@ -3592,10 +3594,12 @@ module ELoot # Inventory methods if Room.current.tags.any?(/locksmith|locksmith pool/i) && (gold_ingot = [GameObj.right_hand, GameObj.left_hand].find { |obj| obj.name =~ /gold ingot/ }) Sell.handle_ingot(gold_ingot) else + ELoot.data.sacks_full.each do |container, information| + ELoot.msg(type: "info", text: " Sacks Full[#{container}]: #{information}") + end unless ELoot.data.sacks_full.empty? ELoot.msg(type: "info", text: " Failed to store the #{item.name}.") ELoot.msg(type: "info", text: " Pausing the script to handle it yourself") ELoot.msg(type: "info", text: " ;unpause #{Script.current.name} after addressing to continue!") - ELoot.msg(type: "debug", text: " Sacks Full: #{ELoot.data.sacks_full}") unless ELoot.data.sacks_full.empty? Script.current.pause end @@ -3711,7 +3715,7 @@ module ELoot # Inventory methods if lines.any? { |l| l =~ /won't fit/i } unless item.name =~ /gold ingot/ ELoot.msg(type: "debug", text: "sacks_full(#{bag.name}) - item: #{item.inspect}") - ELoot.data.sacks_full[bag.name] = [Time.now, item] + ELoot.data.sacks_full[bag.name] = [Time.now, Room.current.id, item] end return false end @@ -6851,7 +6855,7 @@ module ELoot # Starts the script end if !ELoot.data.settings[:track_full_sacks] - ELoot.data.sacks_full = {} + ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } ELoot.reset_disk_full end @@ -6929,7 +6933,7 @@ module ELoot # Starts the script ELoot.wait_rt # Set bags as empty to avoid false full status - ELoot.data.sacks_full = {} + ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } if Script.current.vars[2] == "alchemy_mode" ELoot.data.alchemy_mode = true @@ -6939,7 +6943,7 @@ module ELoot # Starts the script ELoot.sell # Reset bags to empty after all the selling is done - ELoot.data.sacks_full = {} + ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } ELoot.go2(ELoot.data.start_room) ELoot::Sell.breakdown @@ -6965,14 +6969,14 @@ module ELoot # Starts the script type = Regexp.last_match(1) things = Regexp.last_match(2) - ELoot.data.sacks_full = {} + ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } 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.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } ELoot.go2(ELoot.data.start_room) ELoot::Sell.breakdown From 4ab1d7d4caf45f3d562f5fe52d0c9279fed699a8 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 18 Feb 2026 14:54:55 -0500 Subject: [PATCH 20/40] fix: remove silver withdraw for pool --- scripts/eloot.lic | 24 ++---------------------- 1 file changed, 2 insertions(+), 22 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 41c32fcc3..56dc25e38 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -29,6 +29,7 @@ - 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 + - locksmith pool remove silver withdraw v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -6369,29 +6370,10 @@ module ELoot # Sells the loot # if we're here, assume we will empty out the disk ELoot.reset_disk_full - if boxes.length.positive? && ELoot.data.settings[:use_standard_tipping] - amount = ELoot.data.settings[:locksmith_withdraw_amount] - ELoot.silver_withdraw(amount) - end - ELoot.go2('locksmith pool') original_pool = Room.current.id worker = ELoot.find_worker - # if using incremental tipping, need to find out how many boxes are in the pool - if boxes.length.positive? && ELoot.data.settings[:use_incremental_tipping] - pool_count = Sell.locksmith_pool_count(worker) - if pool_count > 99 - 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) + ELoot.data.settings[:locksmith_withdraw_amount] - ELoot.silver_withdraw(total_tips) - ELoot.go2(original_pool) - worker = ELoot.find_worker - end - end - Inventory.free_hands(both: true) unless [GameObj.right_hand, GameObj.left_hand].find { |hand| hand.type =~ /box/ } ELoot.wait_for_disk @@ -6428,9 +6410,7 @@ module ELoot # Sells the loot pool_count = handle_full_pool(worker) { return true if deposit } end when /You don't have that much/ - ELoot.silver_withdraw(ELoot.data.settings[:locksmith_withdraw_amount]) - ELoot.go2(original_pool) - redo_needed = true + redo_needed = false when /already holding as many boxes/ Inventory.single_drag(box) unless box_in_hand pool_count = handle_full_pool(worker) { return true if deposit } From 5415732fc2b32b033ab734e45be081b935d24ddf Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 20 Feb 2026 10:00:12 -0500 Subject: [PATCH 21/40] fix: rubocop --- scripts/eloot.lic | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 56dc25e38..d5913dfee 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -6371,7 +6371,6 @@ module ELoot # Sells the loot ELoot.reset_disk_full ELoot.go2('locksmith pool') - original_pool = Room.current.id worker = ELoot.find_worker Inventory.free_hands(both: true) unless [GameObj.right_hand, GameObj.left_hand].find { |hand| hand.type =~ /box/ } From a60d9f9670492d9e1a2c893ab3359983ac6bd233 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 23 Feb 2026 14:58:45 -0500 Subject: [PATCH 22/40] fix: process default/overflows first for boxes --- scripts/eloot.lic | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index d5913dfee..ffc189fd9 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -30,6 +30,7 @@ - bugfix for in_region check if already in destination room - reset sacks full when using --sellable/type/sell CLI - locksmith pool remove silver withdraw + - fix to process boxes from default/overflows first, then box/disk container to prevent sacks_full emptying loot v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -2163,12 +2164,6 @@ module ELoot # Sets Inventory container_array = [] - # Add the specific type container if it's in the sell list - if type && ELoot.data.settings[:sell_container].include?(type) - container = StowList.stow_list[type.to_sym] - container_array << container if container - end - # Add the default container if ELoot.data.settings[:sell_container].include?("default") container_array << StowList.default @@ -2183,6 +2178,18 @@ module ELoot # Sets Inventory end end + # Add the specific type container if it's in the sell list + if type && ELoot.data.settings[:sell_container].include?(type) + container = StowList.stow_list[type.to_sym] + if container + unless type.eql?('box') + container_array.unshift(container) + else + container_array << container + end + end + end + # Remove duplicates and ensure an array is always returned container_array.compact.uniq end From 4e4e37d32ec93384105e377420837ec1aa18f169 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 23 Feb 2026 20:06:34 -0500 Subject: [PATCH 23/40] fix: add skin bounty creatures only --- scripts/eloot.lic | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index ffc189fd9..da4bfa994 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -31,6 +31,7 @@ - reset sacks full when using --sellable/type/sell CLI - locksmith pool remove silver withdraw - fix to process boxes from default/overflows first, then box/disk container to prevent sacks_full emptying loot + - add skin bounty creatures only v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -762,6 +763,7 @@ module ELoot # UI Setup skin_kneel: { default: false }, skin_604: { default: false }, skin_resolve: { default: false }, + skin_bounty_only: { default: false }, skin_sheath: { default: '' }, skin_weapon: { default: '' }, skin_sheath_blunt: { default: '' }, @@ -1084,11 +1086,11 @@ module ELoot # UI Setup Spell Number0Spell Name1Vibrant2 013TrueFalseKeep Scrolls (?) 104TrueFalseSelling Grid - 4FalseTrueTrueinTrueFalsestartTrueFalse10verticalTrueFalse50TrueFalse55True1025TrueTrueFalse + 4FalseTrueTrueinTrueFalsestartTrueFalse10verticalTrueFalse50TrueFalse5510210TrueFalse 30Enable skinningTrueTrueFalsestartTrue00 Kneel to skinTrueTrueFalsestartTrue10Use Sigil of ResolveTrueTrueFalsestartTrue 20Use 604TrueTrueFalsestartTrue30 - TrueFalseSettingsFalseTrue0820TrueFalsestartTrueTrueFalsestart50TrueFalsecenterTrueTrueFalsestart1055Skin Sheath (blunt) + Skin Bounty OnlyTrueTrueFalsestartTrue40TrueFalseSettingsFalseTrue0820TrueFalsestartTrueTrueFalsestart50TrueFalsecenterTrueTrueFalsestart1055Skin Sheath (blunt) 00TrueTrue10102001TrueFalsestart2055Skin Weapon (blunt) 10TrueTrue2010102011 TrueFalseBlunt Skinning01TrueFalsestart50TrueFalsecenter55TrueTrueTrueFalsestart1055Skin Sheath (edged) @@ -1863,6 +1865,7 @@ module ELoot # Profile loading/saving and settings :skin_kneel => false, :skin_604 => false, :skin_resolve => false, + :skin_bounty_only => false, :skin_sheath => "", :skin_weapon => "", :skin_sheath_blunt => "", @@ -5208,6 +5211,11 @@ module ELoot # Room looting ELoot.data.settings[:critter_exclude].length.positive? && obj.name =~ Regexp.union(ELoot.data.settings[:critter_exclude]) end + if ELoot.data.settings[:skin_bounty_only] && Bounty.task.skin? + bounty_creature = Bounty.task.creature.to_s.downcase + objs = objs.select { |obj| obj.name.to_s.downcase.include?(bounty_creature) } + end + return if objs.empty? blunts = objs.find_all { |obj| obj.name =~ /krynch|stone mastiff|krag dweller|cavern urchin/i } From e8c68d34c061fce74a64da4d4d3be57674e28a02 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Tue, 24 Feb 2026 09:35:36 -0500 Subject: [PATCH 24/40] fix: incremental tipping pool depth & skinning when bounty only checked --- scripts/eloot.lic | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index da4bfa994..19710975c 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -5211,7 +5211,8 @@ module ELoot # Room looting ELoot.data.settings[:critter_exclude].length.positive? && obj.name =~ Regexp.union(ELoot.data.settings[:critter_exclude]) end - if ELoot.data.settings[:skin_bounty_only] && Bounty.task.skin? + if ELoot.data.settings[:skin_bounty_only] + return unless Bounty.task.skin? bounty_creature = Bounty.task.creature.to_s.downcase objs = objs.select { |obj| obj.name.to_s.downcase.include?(bounty_creature) } end @@ -6388,6 +6389,15 @@ module ELoot # Sells the loot ELoot.go2('locksmith pool') worker = ELoot.find_worker + # if using incremental tipping, need to find out how many boxes are in the pool + if boxes.length.positive? && ELoot.data.settings[:use_incremental_tipping] + pool_count = Sell.locksmith_pool_count(worker) + if pool_count > 99 + pool_count = handle_full_pool(worker) { return true if deposit } + return if pool_count > 99 + end + end + Inventory.free_hands(both: true) unless [GameObj.right_hand, GameObj.left_hand].find { |hand| hand.type =~ /box/ } ELoot.wait_for_disk From 649a71e3d7190d0ef03a97d12e500a2d6341e388 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Tue, 24 Feb 2026 13:01:49 -0500 Subject: [PATCH 25/40] fix: clear on sacks_full on ;eloot pool --- scripts/eloot.lic | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 19710975c..9f7ec5bad 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -259,7 +259,7 @@ module ELoot # Data # inventory type @sacks_closed = [] - @sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + @sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } @checked_bags = [] @sell_containers = [] @ready_lines = [] @@ -3607,7 +3607,7 @@ module ELoot # Inventory methods else ELoot.data.sacks_full.each do |container, information| ELoot.msg(type: "info", text: " Sacks Full[#{container}]: #{information}") - end unless ELoot.data.sacks_full.empty? + end unless ELoot.data.sacks_full.keys.count > 1 ELoot.msg(type: "info", text: " Failed to store the #{item.name}.") ELoot.msg(type: "info", text: " Pausing the script to handle it yourself") ELoot.msg(type: "info", text: " ;unpause #{Script.current.name} after addressing to continue!") @@ -3726,7 +3726,7 @@ module ELoot # Inventory methods if lines.any? { |l| l =~ /won't fit/i } unless item.name =~ /gold ingot/ ELoot.msg(type: "debug", text: "sacks_full(#{bag.name}) - item: #{item.inspect}") - ELoot.data.sacks_full[bag.name] = [Time.now, Room.current.id, item] + ELoot.data.sacks_full[bag.name] = [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, "#{item.name}(#{item.id})"] end return false end @@ -6859,7 +6859,7 @@ module ELoot # Starts the script end if !ELoot.data.settings[:track_full_sacks] - ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } ELoot.reset_disk_full end @@ -6937,7 +6937,7 @@ module ELoot # Starts the script ELoot.wait_rt # Set bags as empty to avoid false full status - ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } if Script.current.vars[2] == "alchemy_mode" ELoot.data.alchemy_mode = true @@ -6947,7 +6947,7 @@ module ELoot # Starts the script ELoot.sell # Reset bags to empty after all the selling is done - ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } ELoot.go2(ELoot.data.start_room) ELoot::Sell.breakdown @@ -6956,6 +6956,8 @@ module ELoot # Starts the script ELoot.data.debug_logger = ELoot::DebugLogger.new if ELoot.data.settings[:debug_file] arg = Script.current.vars[2] + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } + if arg.nil? check = true deposit = true @@ -6967,20 +6969,22 @@ module ELoot # Starts the script ELoot.disk_usage ELoot::Sell.pool(deposit: deposit, check: check) + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } + ELoot::Sell.breakdown when /--(sellable|type|sell)\b\s*=?\s*(\/?[a-zA-Z,\s|]+\/?)/ ELoot.data.debug_logger = ELoot::DebugLogger.new if ELoot.data.settings[:debug_file] type = Regexp.last_match(1) things = Regexp.last_match(2) - ELoot.data.sacks_full = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } 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 = { "last cleared" => [Time.now, Room.current.id, Script.current.vars[0]] } + ELoot.data.sacks_full = { "last cleared" => [Time.now.strftime('%Y-%m-%d %H:%M:%S'), Room.current.id, Script.current.vars[0]] } ELoot.go2(ELoot.data.start_room) ELoot::Sell.breakdown From 638babbd82a686827b35d1d5b5532edfa3a48a07 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 2 Mar 2026 09:19:32 -0500 Subject: [PATCH 26/40] Fix bug in keep scrolls option Fixed bug in keep scrolls option to skip non-numeric entries. --- scripts/eloot.lic | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 9f7ec5bad..0c09986a5 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -32,6 +32,7 @@ - locksmith pool remove silver withdraw - fix to process boxes from default/overflows first, then box/disk container to prevent sacks_full emptying loot - add skin bounty creatures only + - bugfix in keep scrolls option to skip if adding non-number to entries v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -737,6 +738,7 @@ module ELoot # UI Setup next if setting.include?(text) spell_no = text[/^\d+/] + next if spell_no.nil? next if Spell[spell_no].nil? setting.push(text) From 643507dc1bfc77667555b8faa9c1d43962f292f5 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:10:33 -0400 Subject: [PATCH 27/40] Refactor overflow settings migration and loading logic --- scripts/eloot.lic | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 0c09986a5..9e5fe685f 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -1775,6 +1775,8 @@ module ELoot # Profile loading/saving and settings def self.load(settings) @@data = Data.new(settings) + # Migrate old overflow settings to new format + ELoot.migrate_overflow_settings(ELoot.data.settings) end def self.migrate_overflow_settings(settings) @@ -1825,8 +1827,9 @@ module ELoot # Profile loading/saving and settings end end - ELoot.save_profile() if migrated_settings - settings + if migrated_settings + ELoot.save_profile() + end end def self.load_defaults() @@ -1897,8 +1900,6 @@ 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 @@ -3574,7 +3575,7 @@ module ELoot # Inventory methods ELoot.wait_rt raise end - next if ELoot.data.sacks_full.keys.include?(bag.name) + next if bag && ELoot.data.sacks_full.keys.include?(bag.name) if bag.nil? case index @@ -6854,7 +6855,7 @@ module ELoot # Starts the script # Initialize/Load settings unless ELoot.data && ELoot.data.respond_to?(:version) && ELoot.data.version == ELoot.get_script_version waitrt? - ELoot.load(ELoot.load_profile()) + ELoot.load(ELoot.load_profile) ELoot.set_inventory ELoot.disk_usage exit if Script.current.vars[0] =~ /load/ From 91f026f5a099c9c8afe4872e27185328e79b29c1 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:24:27 -0400 Subject: [PATCH 28/40] Update scripts/eloot.lic Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com> --- scripts/eloot.lic | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 9e5fe685f..15c77a338 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -3608,9 +3608,11 @@ module ELoot # Inventory methods if Room.current.tags.any?(/locksmith|locksmith pool/i) && (gold_ingot = [GameObj.right_hand, GameObj.left_hand].find { |obj| obj.name =~ /gold ingot/ }) Sell.handle_ingot(gold_ingot) else - ELoot.data.sacks_full.each do |container, information| - ELoot.msg(type: "info", text: " Sacks Full[#{container}]: #{information}") - end unless ELoot.data.sacks_full.keys.count > 1 + if ELoot.data.sacks_full.keys.count > 1 + ELoot.data.sacks_full.each do |container, information| + ELoot.msg(type: "info", text: " Sacks Full[#{container}]: #{information}") + end + end ELoot.msg(type: "info", text: " Failed to store the #{item.name}.") ELoot.msg(type: "info", text: " Pausing the script to handle it yourself") ELoot.msg(type: "info", text: " ;unpause #{Script.current.name} after addressing to continue!") From 3116df6b02118c86c991050c72bf924fdc258faa Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 14:44:14 -0400 Subject: [PATCH 29/40] Refactor migration and defaults handling in eloot.lic --- scripts/eloot.lic | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 15c77a338..96db8b6e7 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -1780,7 +1780,7 @@ module ELoot # Profile loading/saving and settings end def self.migrate_overflow_settings(settings) - migrated_settings = false + migrated_settings = ELoot.seed_missing_defaults(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 = [] @@ -1832,8 +1832,11 @@ module ELoot # Profile loading/saving and settings end end - def self.load_defaults() - default_hash = { + # Returns the canonical defaults hash with no side-effects. + # Used by load_defaults (which also persists it to disk) and by + # seed_missing_defaults (which backfills missing keys at load time). + def self.defaults_hash + { :loot_types => ["alchemy", "armor", "box", "breakable", "clothing", "collectible", "food", "gem", "jewelry", "lockpick", "lm trap", "magic", "reagent", "scroll", "skin", "uncommon", "valuable", "wand"], :loot_exclude => ["black ora", "urglaes"], :loot_phase => false, @@ -1886,6 +1889,23 @@ module ELoot # Profile loading/saving and settings :favor_left => false, :log_unlootables => false } + end + + # Backfill any keys present in defaults_hash but absent from +settings+. + # Returns true if at least one key was added, so the caller knows to + # persist the profile. Safe to call without GTK. + def self.seed_missing_defaults(settings) + added = false + defaults_hash.each do |key, default_value| + next if settings.key?(key) + settings[key] = default_value + added = true + end + added + end + + def self.load_defaults() + default_hash = defaults_hash Dir.mkdir(File.join(DATA_DIR, XMLData.game)) unless File.exist?(File.join(DATA_DIR, XMLData.game)) Dir.mkdir(File.join(DATA_DIR, XMLData.game, Char.name)) unless File.exist?(File.join(DATA_DIR, XMLData.game, Char.name)) @@ -2298,7 +2318,10 @@ module ELoot # Regional bounty Selling ELoot.msg(type: "debug", text: "place: #{place}") bounty_town = Bounty.town.eql?("Cold River") ? "Hinterwilds" : Bounty.town - place = self.tag_for_town(bounty_town, place).id + destination = self.tag_for_town(bounty_town, place) + return nil unless destination + + place = destination.id # Early return if already at destination return place if Room.current.eql?(Room[place]) From b0b81c2162536fb399d0a79061c840cfc51288bd Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:46:02 -0400 Subject: [PATCH 30/40] Refactor key deletion in stow list --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 96db8b6e7..ec36bd1ee 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2123,7 +2123,7 @@ 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) } # 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 } + StowList.stow_list.delete_if { |k, _| [:overflow_container, :secondary_overflow, :appraisal_container].include?(k) } # Find the stow containers we need: overflow, appraisal # Parse comma-separated overflow containers and add them dynamically From 905a6b433f3ee435e4f93728b4b7b1e0eed605b4 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 15:49:06 -0400 Subject: [PATCH 31/40] Refactor key deletion in stow_list --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index ec36bd1ee..b1d53fc73 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2123,7 +2123,7 @@ 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) } # Remove old overflow container keys (they may use sequential numbering now) - StowList.stow_list.delete_if { |k, _| [:overflow_container, :secondary_overflow, :appraisal_container].include?(k) } + StowList.stow_list.delete_if { |k, _| k.to_s.start_with?('overflow_container') || k == :secondary_overflow || k == :appraisal_container } # Find the stow containers we need: overflow, appraisal # Parse comma-separated overflow containers and add them dynamically From 1c54f0d6c2702ea6b4790e6d966b229e21a9b27c Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 11 Mar 2026 16:19:16 -0400 Subject: [PATCH 32/40] Update tag_for_town method to use safe navigation Use safe navigation operator to handle nil case. --- scripts/eloot.lic | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index b1d53fc73..750a1c5c4 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2309,7 +2309,8 @@ module ELoot # Regional bounty Selling def self.tag_for_town(town, tag) ELoot.msg(type: "debug", text: "tag: #{tag} | town: #{town}") - self.by_town(tag).find { |k, _v| k.downcase.include?(town.downcase) }.last + match = self.by_town(tag).find { |k, _v| k.downcase.include?(town.downcase) } + match&.last end # Determine if the bounty town is within the characters region From 91ad4310e64f6ce8a6ef7ed83f2f59e77f564340 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Mon, 16 Mar 2026 15:27:03 -0400 Subject: [PATCH 33/40] fix: update F2P withdrawal for Teras bank --- scripts/eloot.lic | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 750a1c5c4..f1a2c2fed 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -33,6 +33,7 @@ - fix to process boxes from default/overflows first, then box/disk container to prevent sacks_full emptying loot - add skin bounty creatures only - bugfix in keep scrolls option to skip if adding non-number to entries + - expand F2P silver withdraw to support Teras v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -3165,7 +3166,7 @@ module ELoot # Game utility type methods balance = 0 lines = ELoot.get_command("check balance", /(?:The|A prim) teller/, silent: true, quiet: true) - if lines.find { |line| line.match(/Your balance is currently at (?[\d,]+)/) } + if lines.find { |line| line.match(/(?:Your balance is currently at |his temple for a moment. ")(?[\d,]+)/) } balance = Regexp.last_match[:silver].gsub(',', '').to_i end @@ -3188,8 +3189,8 @@ module ELoot # Game utility type methods # deposit the note and then attempt to withdraw the amount of silver needed Inventory.drag(note) - lines = ELoot.get_command("deposit ##{note.id}", /You (?:deposit|hand your)/, silent: true, quiet: true) - break if lines.find { |line| line.match(/worth (?[\d,]+)/) }.nil? + lines = ELoot.get_command("deposit ##{note.id}", /You (?:deposit|hand your)|takes your/, silent: true, quiet: true) + break if lines.find { |line| line.match(/(?:worth|for) (?[\d,]+)/) }.nil? note_amount = Regexp.last_match[:silver].gsub(',', '').to_i withdraw_amount = note_amount >= amount ? amount : note_amount dothistimeout("withdraw #{withdraw_amount} silver", 2, /The teller/) From 95d0f2538d50d3745e35478ad777c37217b90182 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 25 Mar 2026 16:01:45 -0400 Subject: [PATCH 34/40] fix: overflow container validation errors during initialization * ensure_items caller check uses include? to match 'block in set_inventory' frame label, suppressing internal temp key leak in error messages * validate_setup passes configured container name through checks tuple instead of deriving it from label.split(' ').last (returned slot number) * explicit StowList.stow_list.delete(:secondary_overflow) for defensive legacy key cleanup --- scripts/eloot.lic | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index f1a2c2fed..77bca0931 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -2011,7 +2011,7 @@ module ELoot # Sets Inventory end end - if list[key].nil? && caller_locations(1, 1)[0].label != 'set_inventory' + if list[key].nil? && !caller_locations(1, 1)[0].label.include?('set_inventory') ELoot.msg(text: " Can't find #{key}: #{item_name}. Please check ;eloot setup.", space: true) end end @@ -2125,6 +2125,7 @@ module ELoot # Sets Inventory ReadyList.ready_list.delete_if { |k, _| [:skin_weapon, :skin_weapon_blunt, :skin_sheath, :skin_sheath_blunt].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 == :secondary_overflow || k == :appraisal_container } + StowList.stow_list.delete(:secondary_overflow) # Find the stow containers we need: overflow, appraisal # Parse comma-separated overflow containers and add them dynamically @@ -2242,17 +2243,17 @@ module ELoot # Sets Inventory # 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] + checks << [:overflow_containers, StowList.stow_list[key], label, nil, container_name] end end - checks.each do |setting_key, found_obj, label, conditional_key| + checks.each do |setting_key, found_obj, label, conditional_key, configured_name| # Only check if setting is non-empty and optional condition (like :skin_enable) is satisfied 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? - container_name = setting_key == :overflow_containers ? label.split(' ').last : ELoot.data.settings[setting_key] + container_name = configured_name || ELoot.data.settings[setting_key] ELoot.msg(text: " Not able to find the #{label}: #{container_name}") need_exit = true end From 766f139dc8ad47c2043d272dde3f0b3478ca64a1 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Wed, 25 Mar 2026 17:14:13 -0400 Subject: [PATCH 35/40] fix: always check pool in process boxes not working --- scripts/eloot.lic | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 77bca0931..35e187dcf 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -15,10 +15,10 @@ game: Gemstone tags: loot required: Lich >= 5.12.9 - version: 2.7.1 + version: 2.8.0 Improvements: Major_change.feature_addition.bugfix - v2.7.1 (2026-01-27) + v2.8.0 (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 @@ -34,6 +34,7 @@ - add skin bounty creatures only - bugfix in keep scrolls option to skip if adding non-number to entries - expand F2P silver withdraw to support Teras + - bugfix in process_boxes and always check pool v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -6722,7 +6723,7 @@ module ELoot # Sells the loot def self.process_boxes boxes = ELoot.find_boxes - return unless boxes.any? + return unless boxes.any? || ELoot.data.settings[:always_check_pool] ELoot.msg(type: "debug", text: "length: #{boxes.length}") From 6d9fbbebe351bb0f735bb5d01ae7708347150dfa Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:17:25 -0400 Subject: [PATCH 36/40] fix: bugs in looting and inventory handling Fix multiple bugs related to looting and inventory management. --- scripts/eloot.lic | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 35e187dcf..534f1e770 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -35,6 +35,8 @@ - bugfix in keep scrolls option to skip if adding non-number to entries - expand F2P silver withdraw to support Teras - bugfix in process_boxes and always check pool + - bugfix for frozen bramble looting + - bugfix for manual deposit hoard when items in left hand v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -4510,7 +4512,7 @@ module ELoot # Gem and Reagent hoarding if bottle 3.times do - Inventory.drag(bottle) + Inventory.drag(bottle, to: 'left') break if ELoot.in_hand?(bottle) # assuming if we are still here and its a locker it reset on us if ELoot.data.locker || ELoot.data.use_house_locker @@ -4521,7 +4523,7 @@ module ELoot # Gem and Reagent hoarding jar = [GameObj.right_hand, GameObj.left_hand].find { |i| i.noun =~ /^(?:jar|bottle|beaker)$/ } elsif empty 3.times do - Inventory.drag(empty) + Inventory.drag(empty, to: 'left') break if ELoot.in_hand?(empty) # assuming if we are still here and its a locker it reset on us if ELoot.data.locker || ELoot.data.use_house_locker @@ -4552,7 +4554,7 @@ module ELoot # Gem and Reagent hoarding items_to_hoard.each do |thing| thing_name = Hoard.normalize_name(thing.name) - Inventory.drag(thing) + Inventory.drag(thing, to: 'right') result = ELoot.get_res("_drag ##{thing.id} ##{jar.id}", /You (add|put)|The.*?is full/) @@ -5085,7 +5087,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\.|As you move to search/, silent: false, quiet: false) + results = ELoot.get_command("loot ##{thing.id}", /You (search|plunge|break|tentatively)|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/ } && @@ -5106,7 +5108,7 @@ module ELoot # Room looting end end - break if results.any? { |line| line =~ /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\./ } || + break if results.any? { |line| line =~ /You (search|plunge|break|tentatively)|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\./ } || thing.nil? || thing.status =~ /gone/ end @@ -6848,6 +6850,7 @@ module ELoot # Sells the loot return if lines.any?(/That's not quite my field|That's basically worthless here|Can't say I'm interested in that|This is a pawnshop, sir, not a junkshop|The company don't buy trash|as if you were a lunatic/) + 20.times { break if !ELoot.in_hand?(item) sleep 0.1 From 5318ef355fac2ffb0bca75852916c6ad11c52089 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:22:40 -0400 Subject: [PATCH 37/40] fix: remove unnecessary blank lines in eloot.lic --- scripts/eloot.lic | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 534f1e770..8b8d9a970 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -6849,8 +6849,7 @@ module ELoot # Sells the loot lines = ELoot.get_command("sell ##{item.id}", /You (offer to sell|ask)/) return if lines.any?(/That's not quite my field|That's basically worthless here|Can't say I'm interested in that|This is a pawnshop, sir, not a junkshop|The company don't buy trash|as if you were a lunatic/) - - + 20.times { break if !ELoot.in_hand?(item) sleep 0.1 From a4ea55293e49976c8620af1e07ed4c3f258c9155 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 3 Apr 2026 10:25:09 -0400 Subject: [PATCH 38/40] fix: additional rubocop blank space removal --- scripts/eloot.lic | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 8b8d9a970..00cd7aa64 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -6849,7 +6849,7 @@ module ELoot # Sells the loot lines = ELoot.get_command("sell ##{item.id}", /You (offer to sell|ask)/) return if lines.any?(/That's not quite my field|That's basically worthless here|Can't say I'm interested in that|This is a pawnshop, sir, not a junkshop|The company don't buy trash|as if you were a lunatic/) - + 20.times { break if !ELoot.in_hand?(item) sleep 0.1 From 75904563ecab2ed69f72f4b0a00a67dee3808ee4 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 3 Apr 2026 12:12:59 -0400 Subject: [PATCH 39/40] fix: CR recommendations drag method calls in eloot.lic --- scripts/eloot.lic | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index 00cd7aa64..a030f0159 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -4512,7 +4512,7 @@ module ELoot # Gem and Reagent hoarding if bottle 3.times do - Inventory.drag(bottle, to: 'left') + Inventory.drag(bottle, 'left') break if ELoot.in_hand?(bottle) # assuming if we are still here and its a locker it reset on us if ELoot.data.locker || ELoot.data.use_house_locker @@ -4523,7 +4523,7 @@ module ELoot # Gem and Reagent hoarding jar = [GameObj.right_hand, GameObj.left_hand].find { |i| i.noun =~ /^(?:jar|bottle|beaker)$/ } elsif empty 3.times do - Inventory.drag(empty, to: 'left') + Inventory.drag(empty, 'left') break if ELoot.in_hand?(empty) # assuming if we are still here and its a locker it reset on us if ELoot.data.locker || ELoot.data.use_house_locker @@ -4554,7 +4554,7 @@ module ELoot # Gem and Reagent hoarding items_to_hoard.each do |thing| thing_name = Hoard.normalize_name(thing.name) - Inventory.drag(thing, to: 'right') + Inventory.drag(thing, 'right') result = ELoot.get_res("_drag ##{thing.id} ##{jar.id}", /You (add|put)|The.*?is full/) From 3fcb94b1d9dd678b74cdb4516f8cf49b22f48f12 Mon Sep 17 00:00:00 2001 From: "Ryan P. McKinnon" <15917743+mrhoribu@users.noreply.github.com> Date: Fri, 3 Apr 2026 15:53:20 -0400 Subject: [PATCH 40/40] fix: hoarding_list single respect type on select prevents situation when you have both `pink sapphire` gem and `sparkling pink sapphire band` jewelry in your inventory causing it to select both on single select to jar. --- scripts/eloot.lic | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/eloot.lic b/scripts/eloot.lic index a030f0159..1fc55cfa2 100644 --- a/scripts/eloot.lic +++ b/scripts/eloot.lic @@ -37,6 +37,7 @@ - bugfix in process_boxes and always check pool - bugfix for frozen bramble looting - bugfix for manual deposit hoard when items in left hand + - bugfix for hoarding when valid hoard items have same name as none valid items v2.7.0 (2026-01-19) - added ground looting of boxes - added support for group disks when looting boxes @@ -4432,7 +4433,7 @@ module ELoot # Gem and Reagent hoarding ELoot.data.items_to_hoard.concat(container.contents.to_a) end - return ELoot.data.items_to_hoard.select { |item| item.name =~ /#{single}/ } if single + return ELoot.data.items_to_hoard.select { |item| item.name =~ /#{single}/ && item.type =~ /#{obj_type}/ } if single ELoot.data.items_to_hoard.reject! { |item| item.type !~ /#{obj_type}/ }