Files
my-botty/docs/gems_transmute_flow.md
2026-06-21 16:06:58 +02:00

4.9 KiB
Raw Permalink Blame History

GEMS-tab transmute flow (rewritten in commit 48d8445)

src/transmute/transmute.pyTransmute.convert_all_gems() and helpers.

What changed and why

The old flow drove gem upgrades through the Horadric Cube UI: it required the cube to live in the PERSONAL stash tab, opened the cube, ctrl+shift+right-clicked 3 gems into it, clicked the cube's Transmute button, then pulled the result back out. This was fragile — it depended on cube placement, cube-open detection (ScreenObjects.CubeOpened via wait_until_visible), and a pre-flight "empty the cube" pass.

The rewrite uses D2R's native GEMS-tab convert panel instead of the cube. Gems are moved directly between the GEMS stack grid and the convert panel, and conversion uses the GEMS tab's own convert button. The cube is no longer required to be in the stash and, if present in the character inventory, is left untouched.

Fixed stack-coordinate grid

GEMS_TAB_STACK_COORDS is a new module-level dict mapping every gem template (INVENTORY_<FAMILY>_<TIER>) to a fixed (x, y) screen coordinate at 1280×720. The grid is:

  • Columns by family (x): diamond 85, emerald 132, ruby 180, topaz 227, amethyst 275, sapphire 322, skull 370.
  • Rows by tier (y): chipped 154, flawed 195, standard 234, flawless 273, perfect 311.

Because gem stacks always render at these fixed slots on the GEMS tab, the flow can click them by coordinate instead of template-searching for them each time. _gems_stack_monitor_for(template) converts the screen coord to monitor coords (returns None if the template isn't in the grid, so the caller can fall back to a template search).

Panel constants (1280×720)

Constant Value Meaning
GEMS_TAB_X 223 GEMS tab click X (was 200)
GEMS_CONVERT_BUTTON (225, 500) native convert button in the GEMS panel
GEMS_CONVERT_PANEL_ROI (160, 296, 128, 160) ROI to search for the converted result
GEMS_CONVERT_FIRST_SLOT (181, 318) fallback slot to grab the result if the search misses

Per-transmute flow (new)

For each gem type/tier with enough gems to convert:

  1. Switch to GEMS tab.
  2. Load 3 gems_ctrl_shift_left_click_monitor the stack slot ×3 to move 3 gems into the convert panel. If exactly 3 weren't loaded, abort that batch.
  3. Convert_click_gems_tab_convert_button() clicks the panel's native convert button.
  4. Recover the result — template-search gems_out within GEMS_CONVERT_PANEL_ROI; if found, ctrl+shift+left-click it back onto the GEMS tab. If not found, fall back to ctrl+shift+left-click on GEMS_CONVERT_FIRST_SLOT (instead of the old behavior of clearing the cube and bailing).
  5. Leave the inventory cube untouched and return to the GEMS tab for the next iteration.

The old pre-flight "open cube → empty 12 cube slots → reopen stash" pass and the per-iteration "close cube / reopen stash" steps are removed.

Helper changes

  • _open_cube_from_stash() / _open_cube_from_gems_tab() / _open_available_cube_for_gems_tab() now operate from the GEMS tab rather than PERSONAL, and can open the cube from character inventory (_open_cube_from_inventory) when the GEMS tab is active. These remain for older inventory flows; the new gem flow doesn't need them.
  • _locate_cube() can now return 'opened' (cube UI already open on the GEMS tab) in addition to 'stash' / 'inventory'.
  • _ensure_cube_available() now treats inventory as usable ("it will stay there") instead of an error — the cube no longer has to be moved to PERSONAL.
  • _ensure_cube_in_stash() dropped the loot-column safety guard: it now ctrl+clicks any positive CubeInventory match, so the cube can be moved from reserved inventory columns too.
  • Keyboard modifier handling switched from the low-level win_input.key_down/key_up(_get_vk(...)) to keyboard.send(..., do_release=False) / keyboard.release(...) wrapped in try/finally, so ctrl+shift are always released even if the click raises. Applies to both _ctrl_shift_click_monitor (right) and _ctrl_shift_left_click_monitor (left).
  • _empty_cube_to_gems_tab() now uses _ctrl_click_monitor (plain ctrl) rather than ctrl+shift.

Gem counting (_count_gems_by_ocr)

Counting no longer template-searches the left-inventory ROI for each gem. It now reads each fixed slot from GEMS_TAB_STACK_COORDS: crop the slot icon, and skip empty slots by checking the 95th-percentile grayscale brightness (< 45 ⇒ no gem present). Occupied slots still OCR the count badge in the bottom-right quadrant. This is faster and immune to template-match drift, at the cost of depending on the fixed 1280×720 grid.

Resolution assumption

The whole flow is hard-coded to 1280×720. All coordinates above are screen coordinates at that resolution, converted to monitor coordinates at click time via convert_screen_to_monitor.