fix(eloot.lic): v2.11.1 locksmith pool/town locksmith fixes + Locksmith Priority option - #2401
Open
mrhoribu wants to merge 12 commits into
Open
fix(eloot.lic): v2.11.1 locksmith pool/town locksmith fixes + Locksmith Priority option#2401mrhoribu wants to merge 12 commits into
mrhoribu wants to merge 12 commits into
Conversation
Updated version to 2.11.1 and added fixes for locksmith pool recovery issues.
Contributor
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Add RSpec tests for ELoot::Loot.loot_specials and box-looting call sites, ensuring proper routing and recovery behavior.
Contributor
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@scripts/eloot.lic`:
- Around line 5261-5264: Return an explicit :recovered status from loot_specials
when pool recovery has already re-looted and finalized the box instead of
returning []. In scripts/eloot.lic:5261-5264, update that recovery branch; in
scripts/eloot.lic:4885-4887, make box_loot return before Sell.save_trash_box
when the result is :recovered; in scripts/eloot.lic:4930-4931, skip to the next
ground box for the same result. In spec/scripts/eloot_spec.rb:241-245, assert
the recovery status and add caller coverage preventing duplicate box
finalization.
🪄 Autofix
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 374747ae-fc53-4f49-86ba-5d3ce946b8e4
📒 Files selected for processing (2)
scripts/eloot.licspec/scripts/eloot_spec.rb
Refactor loot handling to prevent double finalization during recovery. Ensure both loot_specials and loot_regular return :recovered when applicable.
Fix handling of boxes that the town locksmith refuses to open, preventing infinite loops and ensuring proper routing of boxes.
Added tests for ELoot::Sell.town_openable? and box routing.
Fix trash/drop behavior to respect unsellable items and refactor duplicated code into a helper function.
Refactor ELoot methods for marked unsellable and toss. Consolidate trash/drop logic into ELoot.toss helper and ensure all call sites utilize this shared method.
Fix interpolation check for toss_cmd in eloot_spec.rb
Added 'Locksmith Priority' option for loot management and fixed multiple issues related to box handling and recovery processes.
Added RSpec tests for ELoot::Sell locksmith_priority routing, including scenarios for process_boxes and route_town_then_pool methods.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Started as a fix for the v2.11.0 locksmith pool "sell to free space and resume" recovery
not firing for
loot_specialsitems. Grew to cover two more pre-existing bugs found whiletracing it (double finalization on recovery, and boxes the town locksmith always refuses
being routed to it anyway), a mark-status guard on trash/drop, and — per review discussion
on this PR — a new Locksmith Priority option for when both routing checkboxes are on.
box_lootdrainsloot_specialsbeforeloot_regular, and onlyloot_regularwas wiredto the pool recovery, so orbs, cursed items, keepers, and uncommon weapons/armor still
paused the script mid-return with the box and the stuck item in hand.
Room looting and critter-bag looting are unchanged throughout.
Reported symptom
From a player's
eloot.log(15h session, v2.11.0, debug on). ThreeFailed to store/Pausing the scriptevents, all with the same caller chain:box_loot(4858)->loot_specials(5182)->single_drag(3701)Loot.room(5259)->loot_specials(5182)->single_drag(3701)box_loot(4858)->loot_specials(5182)->single_drag(3701)The recovery never ran once in the whole session -- zero
Selling to free spacemessages-- despite 78
stow_box_itementries during the same pool returns.A second report surfaced a related defect:
caseboxes, which only the locksmith pool ora player locksmith can open, were still carried to town on every sell run when routing
sent boxes there (gem bounty setting, pool disabled, F2P, tipping unset, or deposit
failure) -- a silver withdrawal, a trip, refused bells, and the box never opening.
Root cause
1. Missing call-site wiring.
loot_specialstook onlyobjs, so it had no boxcontext and called
Inventory.single_drag(thing)-- defaulton_full: :pause. Therecovery hangs off
Loot.stow_box_item, reachable only fromloot_regular.2. Double finalization on recovery (pre-existing, v2.11.0).
loot_regular's docstringpromised
:recoveredso "the caller should stop iterating," but all three of its recoveryexits were bare
return-- returningnil.box_lootdiscarded the value and ranSell.save_trash_boxanyway, after the nested recovery had already trashed or stowed thebox.
3. Box routing ignores per-box openability (pre-existing).
process_boxesdecidedpool-vs-town for the entire list at once, so any route that sent
caseboxes to townproduced a permanent no-op loop.
Changes
scripts/eloot.licloot_specialstakesbox:,location:,data:,sell_recovered:keyword args, alldefaulted, and stows via
Loot.stow_box_itemwhen a box is given.loot_regular's recovery exits nowreturn :recoveredinstead ofnil, matching thedocstring;
box_loot/box_loot_groundskip finalization on:recovered.Sell.town_openable?(new): false forcasenouns (POOL_ONLY_NOUNS) and false for anybox name
Sell.remember_town_refusalrecorded this session.process_boxespartitions on that predicate and only ever hands the town locksmith boxesit can open, guarded by
Sell.pool_available?.locksmith_openwidens its activator match to catch the NPC ignoring a box that isverifiably in hand, recording a session-scoped refusal so an unrecognized box type costs
one attempt instead of every run.
ELoot.marked_unsellable?/ELoot.toss: trash/drop now checks in-game mark statusbefore ever issuing trash or drop, and refuses to toss anything marked -- consolidates 5
duplicated trash/drop-and-check-hand call sites into one helper.
locksmith_prioritysetting ('pool'default /'locksmith'), exposed as aGtkComboBoxTextdropdown in the Locksmithing frame (Pool First / Locksmith First),sensitive only when both "Use locksmith pool" and "Use town locksmith" are checked.
"Locksmith First" routes town-openable boxes to town first via the new
Sell.route_town_then_poolhelper, then pools whatever's left (including anything aruntime town refusal knocks back out). "Pool First" is unchanged and remains the
default -- no behavior change for anyone who doesn't touch the new setting. The existing
locksmith_when_gem_bountyoverride is a narrower, more specific routing decision andkeeps its current order regardless of this preference.
branch) and trimmed to match the terser style of older entries; content unchanged.
spec/scripts/eloot_spec.rb-- 41 new examples across five describe blocks (32 from theoriginal fix set, plus 9 for Locksmith Priority), following the existing
extract-from-source-and-eval pattern.
Sell.route_town_then_poolhas no navigation of itsown, so it's exercised for real against a small stand-in for
Sell/ELootrather thanasserted structurally.
Not in scope
The no-disk case still pauses.
pool_full_recovery?requireshas_disk, sincepool_sell_recoveryhas to park the box somewhere to free both hands to sell. Closing itneeds a staging decision with real player cost (ground/re-pool/carry) -- a product
decision, deliberately left alone.
always_check_poolisn't honored on the Locksmith First path -- consistent with theexisting gem-bounty branch, which also doesn't check that setting; pool is only visited if
boxes remain after the town step.
Testing
bundle exec rspec spec/scripts/eloot_spec.rb-- 81 examples, 0 failures.Regression, runnable spec subset (
spec/autostart spec/bigshot spec/log spec/rofl-puzzles spec/scripts): 149 -> 190 examples, 0 failures.The routing was also replayed against the reported scenario with the shipped
process_boxesbody and stubbed collaborators (2 cases + gem bounty; case + steel chest;cases-only with pool unavailable; mixed with pool unavailable), all matching expected
routing.
For the new priority option specifically,
Sell.route_town_then_poolwas verified bydeliberately breaking it three ways (dropped the
town_openable?filter, skipped the boxrefresh before pooling, dropped the
pool_available?guard) and confirming each broke aspecific new example, then reverting -- so the new specs aren't just matching whatever the
code happens to say.
Also clean:
ruby -con both changed files, ASCII-only byte scan (0 bytes > 127), RuboCop1.39.0 with the vendored
Custom/AsciiOnlySourcecop -- no offenses.Reviewer notes
a mark-status fix + refactor, and a feature addition. Happy to split the Locksmith
Priority option into its own PR if you'd rather keep this one to the bug-fix set --
flagging it since it's the one piece that isn't a fix.
POOL_ONLY_NOUNSis a second place to maintain.gameobj-data.xmlalreadyenumerates these box descriptors. Raised separately rather than expanding this PR.
pool_full_recovery?'shas_disktest is looser than whatsingle_drag_boxactually requires; not reachable in the logged session, worth aseparate look.
gems); none touch
eloot.lic, please confirm against a full CI run.Checklist
ruby -ccleancaseis the only town-unopenable noun (community/Discord check)