Problems:
1. use_wp() fired immediately after open_wp() — WP panel animation
still playing, WaypointTabs template not yet visible → silent fail
2. vizier.py + diablo.py ignored use_wp() return value → approach()
returned a truthy Location even when the WP was never used, causing
battle() to run from the wrong map location
3. go_to_act() also ignored use_wp() return value
Fixes:
- waypoint.use_wp(): retry WaypointTabs detection up to 4x (1.6s total)
before giving up; log each retry + the target WP and act being switched
- vizier/diablo approach(): check use_wp() return, return False on failure
- town_manager.go_to_act(): check use_wp() return, log + return False
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
GoldBtnVendor (small gold coin template in a tight ROI) was failing even
when the vendor window was fully open. Replace with wait_until_visible(
LeftPanel, timeout=3.0) which checks for the panel close-X in the header
— the same reliable check used by wait_for_left_inventory/left_inventory_ready.
Fixes: A5 (Malah) and A1 (Akara) buy_consumables failing every run.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- screen.py: default monitor_roi width 1280 -> 1282 (actual window size)
- diablo.py: re-detect window position before TP in CS run (2 places)
- npc_manager.py: adjust Akara ROI/poses for 1282px; lower NPC name tag
threshold 0.5->0.35 for more reliable hover detection; add NPCDialogue
visibility wait + per-threshold debug logging in press_npc_btn
- a1.py: add wait(0.5, 0.8) after trade button before GoldBtnVendor check;
guard open_trade_and_repair_menu on NPC menu result; add Logger.info
throughout open_trade_menu, heal, open_trade_and_repair_menu
- a5.py: same wait + logging pattern for Malah open_trade_menu
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Adds _log_platform_info() called from startup_checks(). On each bot
start the log now shows:
- Windows 10/11 + build number (Win11 = build >= 22000)
- Mouse input mode: relative (Win11) or absolute (Win10)
- OCR backend: tesserocr (primary) or pytesseract fallback or ERROR
Win11 (build 26200) confirmed working: mouse in relative mode,
tesserocr 5.2.0 with hover/ground botty models loading correctly.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
Resolved 7 conflicts by keeping both local (Logger.info diagnostics in
buy_consumables and repair) and remote (set_panel_check_paused health-check
suppression during vendor/repair panels). All paths now log + pause correctly.
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Implementation of centralized cooperative shutdown mechanism (C10) to replace dangerous thread killing.
- Consolidation of all timing signatures through jittered wait() for anti-cheat stealth (C1).
- Enhanced HealthManager reactivity with smart mana potion fallback and premature panel-closing protection.
- Refactored waypoint stealth logic to simulate human-like mis-aim instead of area-breaking misclicks.
- Implementation of stateless 'garbage item' filtering in PickIt to eliminate ghost item loops and OCR artifacts.
- Optimization of inventory management to automatically stash protected items that cannot be sold.
- Suppression of individual game failure notifications on Discord; alerts now trigger on 5+ consecutive fails.
- Implementation of centralized cooperative shutdown mechanism (C10) to replace dangerous thread killing.
- Consolidation of all timing signatures through jittered wait() for anti-cheat stealth (C1).
- Enhanced HealthManager reactivity with smart mana potion fallback and premature panel-closing protection.
- Refactored waypoint stealth logic to simulate human-like mis-aim instead of area-breaking misclicks.
- Implementation of stateless 'garbage item' filtering in PickIt to eliminate ghost item loops and OCR artifacts.
- Optimization of inventory management to automatically stash protected items that cannot be sold.
- Suppression of individual game failure notifications on Discord; alerts now trigger on 5+ consecutive fails.
Alex's value (2000) preserved over FiskenPoul's (200) for transmute cadence.
stash_destination=0,1,2,3 accepted from remote (matches fill_shared_stash_first=0).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- win_input.py: detect OS build via platform.win32_ver(), use
MOUSEEVENTF_ABSOLUTE only on Win10 (build < 22000)
- install.bat: detect and display Windows version on install
personal.open_inventory() returns None when the inventory cannot be opened
(e.g. after a failed vendor interaction leaves the UI in a bad state). The
previous code passed that None straight into common.get_slot_pos_and_img()
which tried to index it, crashing the bot thread with:
TypeError: 'NoneType' object is not subscriptable
Also wraps the shift-click loop in try/finally so keyboard.release("shift")
is guaranteed even if an exception fires mid-loop (prevents stuck Shift key).
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- i_char.py: rewrite _pre_buff_cta() to verify each weapon switch via BC
skill-bar template; detects wrong slot on game start (leftover from
interrupted buff cycle), retries failed switches once, logs clearly
when stuck on CTA slot to prevent dying with wrong weapon in combat
- personal.py: protect needed consumables from sell/drop in inspect_items;
check get_needs() before marking a pot for discard — if the belt needs
that pot type, skip it so fill_up_belt_from_inventory can restock later
- bot.py: add fill_up_belt_from_inventory + update_pot_needs after
buy_consumables so inventory pots reach the belt even when out of gold;
add town-heal loop at start of on_maintenance to drink health/rejuv pots
until HP >= 95% before the next run (health manager is paused in town)
- game_stats.py: add rolling 10-game pickup health check; warns in log and
sends Discord alert when zero item pickups occur across 10 games while
chickens or merc deaths are present
- params.ini: fix show_belt=n -> show_belt=k (belt key was wrong, causing
1.5s wasted recovery attempt every first game in a session)
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
- Updated bot behavior to end the game when no TP charges are left, instead of attempting to walk back to town.
- Refined item processing logic in `processing_helpers.py` to use identity checks for item comparisons and improved item removal methods.
- Enhanced game stats logging to include failure reasons and send Discord notifications for failed games.
- Improved health management logic to trigger chicken behavior based on health percentage after rapid rejuvination.
- Added error handling for item pickup failures in `pickit.py` to blacklist items that cannot be picked up.
- Introduced walking fallback nodes for Countess, Andariel, Mephisto, and Baal runs in `pather.py`.
- Implemented path data validation in run scripts for Countess, Andariel, Mephisto, and Baal to ensure paths are correctly defined.
- Enhanced item identification and stash processes in `diablo.py` with retry logic for failures.
- Updated town management to handle identification failures gracefully and log appropriate warnings.
- Improved character selection logic to provide clearer logging messages.
- Modified game restart logic to launch the game via PowerShell for better session handling.
- Added documentation for recording paths for the Countess run and created a PowerShell script for scheduled task management.
- BC and BO cast with left-click (targets self) instead of right-click
- Swap-back loop simplified to 2 attempts with match score logging
- Added full test route order: trav, pindle, eldritch_shenk, nihlathak, arcane, diablo, vizier
Removed the visual skill check (is_right_skill_selected BC/BO) that always
failed because the BC.png/BO.png templates do not match D2R icons. New flow:
switch weapon, cast BC, cast BO, buff, switch back. Only verifies swap-back
by matching the original skill icon via template matching.
- game_controller: set reason on max_game_length, chicken, force_stop
- bot.py on_end_game: set default reason when failed=True has no reason yet
- bot.py save_and_exit failure: set reason before stop()
- bot.py restart_or_exit: capture error message as failure reason
- All retry paths (stash, buy_consumables, heal, repair) now use known-good
location constants instead of corrupted self._curr_loc (False)
- Guard gamble->stash chain against False location
- Guard wait_for_tp against False location
- Add run_trav to route order (travincal then pindle)
- Fix merc icon detection: expanded ROI from 40x40 to 60x60 (matchTemplate requires search area > template)
- Add MercPanelText screen object using mercenary_screen.png for reliable merc alive check
- Bot merc check now uses MercPanelText instead of generic LeftPanel
- Diablo: wait for boss to spawn before attacking (up to 15s), use conviction aura
- Diablo/Pindle attack lengths increased (diablo 3->10s, pindle 3->8s)
- Aura key switch delay increased from 50-100ms to 200-300ms for reliable activation
- Add conviction hotkey (F5) to hammerdin config
- Move Pindle CTA pre-buff from town to after entering red portal
- More aggressive healing thresholds (health potion at 98%, rejuv at 85%)
- Max game length increased from 160s to 600s for full Diablo runs
- Crop A5_RED_PORTAL template to remove empty space (center now aligns with portal)
- Fix merc_icon ROI from 10,9,50,50 to 15,14,40,40 (matches 40x40 merc templates)
- Lower MercIcon threshold from 0.9 to 0.85, add MERC_A2_2 variant
- Add merc panel confirmation with 'O' key before resurrect (prevents false resurrect when icon detection fails)
- Override capabilities to can_teleport_natively
- src/inventory/vendor.py: Log screenshots when NotEnoughGold detected
during gambling, purchasing, and repairing
- src/ui_manager.py: Update NotEnoughGold to use new MISSING_GOLD template
from assets/npc/missing_gold/ (full dialog match instead of color-based)
- assets/npc/missing_gold/missing_gold.png: New template for the popup
- src/utils/misc.py: move_d2r_window now calculates outer window position
to place client area at target coords (was incorrectly setting outer
window to target, shifting client area unpredictably)
- src/bot.py: Call move_d2r_window(5,98) at game start to restore original
working client area position and prevent 13px offset drift
- src/screen.py: Add force param to find_and_set_window_position/set_window_position
to bypass early-return guard and skip wait when called programmatically
- src/run/pindle.py: Force window re-detection before each traverse_nodes and
select_by_template call to handle offset drift between runs
- src/pather.py: Add fallback full-image search with lower threshold (0.55) when
cropped ROI search fails in find_abs_node_pos
- src/bot.py: Move D2R window to stable position (0,0) at game start via
move_d2r_window; skip merc resurrect after first failure (no gold)
- src/game_stats.py: Add _merc_resurrect_failed flag (reset each game)
- src/utils/misc.py: Add move_d2r_window() function
- config/params.ini: Updated teleport=b, show_belt=k, override_capabilities,
restore_settings_from_backup_key=insert, graphic_debugger_key=delete
- health_manager.py: read actual merc health for heal/chicken/rejuv decisions
instead of timer-only logic; pass merc_health to belt.drink_potion stats
- processing.py: remove stale TODO comment (traceback import is used)
- Restore test/assets/ from commit 5127417^ (was moved to bottytools/botty-test-assets which is now 404)
- Remove 'Download test assets' step from CI workflow (assets are now in-repo)
- Make download_test_assets.py a no-op for backward compatibility
- Fix import: from pipes import Template -> from template_finder import Template
- Remove test/assets/ from .gitignore
- Add utils/log_rotation.py: safe_imwrite() auto-rotates screenshot dirs
when they exceed configured file count or size limits
- Add [log_rotation] config section in params.ini (pickit/info/items
max_files, max_mb, discord_notify_rotation)
- Replace 40 cv2.imwrite() calls with safe_imwrite() across 13 files
- Add failure reason tracking: bot.py catches run exceptions, stores
reason in game_stats, Discord message includes the error
- Add Discord notification when log rotation deletes old files
- Prevents disk-full crashes that stopped botty on May 30