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