Probed the live client by pressing F1-F8 and reading the right skill slot; D2R renders the key label into the icon, so the crops are self-proving. Actual binds: f2=Holy Shield, f3=Redemption, f4=a charged item skill, f5=TELEPORT, f6=Concentration, f8=an aura with no template (Conviction). f1 and f7 are UNBOUND. Against that, [hammerdin] was wrong three ways: - conviction=f5 pointed at TELEPORT, so every attack-aura cast would have teleported the character — the exact hazard the [fohdin] profile section already warns about. Conviction also does nothing for magic-damage hammers (Bug 17), so it is now unbound rather than remapped. - concentration=f8 pointed at Conviction; Concentration is on f6. The build was running with no Concentration at all — less hammer damage and no party aura for the merc, which plausibly fed the Travincal chickens. - blessed_hammer=f1 pointed at nothing. The hammer lives permanently on LEFT-click and no hotkey moves it to the right slot, so the preflight's right-slot check could never pass; it scored 44.8% all session while the hammer sat correctly on the left the whole time. The check now inspects the left slot and presses no key, matching the comment that was already above it. The stored blessed_hammer.png was a right-slot capture with "F1" baked into the image, which is why it scored 34.4% against the unlabelled left slot. Recaptured from the live left slot. Co-Authored-By: Claude Opus 5 <[email protected]>
813 lines
30 KiB
INI
813 lines
30 KiB
INI
; There is detailed documentation for each parameter in the README.md
|
|
[general]
|
|
; Personal values can reference env keys from repo-root .env:
|
|
; Example syntax:
|
|
; custom_message_hook=${BOTTY_CUSTOM_MESSAGE_HOOK}
|
|
; custom_loot_message_hook=${ENV:BOTTY_CUSTOM_LOOT_MESSAGE_HOOK}
|
|
; bnet_name=${BOTTY_BNET_NAME}
|
|
; bnet_pass=${BOTTY_BNET_PASS}
|
|
; char_name=${BOTTY_CHAR_NAME}
|
|
; difficulty: game difficulty to create ("normal", "nightmare", "hell")
|
|
;
|
|
; Hammerdin difficulty guide (CTA build with Conviction aura):
|
|
; NORMAL - Very easy. 1-2h Hammer kills most packs. No CTA needed.
|
|
; NIGHTMARE - Recommended starting point. Bosses hit ~100-200 dmg.
|
|
; CTA + Conviction drops resists. Need decent armor (ED/HR).
|
|
; Gear targets: ~200 AR, ~15 ED, ~30% HR, ~50% FCR on hammer.
|
|
; HELL - Bosses hit 400-800+ dmg per swing. Conviction is mandatory.
|
|
; Gear targets: ~350+ AR, ~20+ ED, ~50%+ HR, ~60%+ FCR,
|
|
; ~150% IAS on weapon. Full Rejuv belt recommended.
|
|
; If you chicken/die repeatedly, drop to Nightmare first.
|
|
difficulty=normal
|
|
; name: bot profile name used in logs/messages and mod launch option replacement
|
|
name=profile1
|
|
; randomize_runs: 0 = run in listed order, 1 = shuffle run order
|
|
randomize_runs=0
|
|
; target_tz: target Terror Zone id (leave as default unless you know the mapping)
|
|
target_tz=1
|
|
; saved_games_folder: optional override path to D2R Saved Games folder (blank = auto)
|
|
saved_games_folder=
|
|
; level_max_steps: max pathing steps for leveling-style routines
|
|
level_max_steps=20
|
|
|
|
; Set to 1 to enable auto-login and auto-launch of D2R on startup.
|
|
; Credentials below are ONLY used when auto_login=1.
|
|
auto_login=0
|
|
bnet_name=${BOTTY_BNET_NAME}
|
|
bnet_pass=${BOTTY_BNET_PASS}
|
|
|
|
; Character name to auto-select from the character selection screen
|
|
; If empty, bot relies on the saved character template from previous sessions
|
|
char_name=${BOTTY_CHAR_NAME}
|
|
|
|
; messaging
|
|
; custom_loot_message_hook: optional separate webhook for loot notifications
|
|
custom_loot_message_hook=${BOTTY_CUSTOM_LOOT_MESSAGE_HOOK}
|
|
; custom_message_hook: main webhook for status/death/chicken messages
|
|
custom_message_hook=${BOTTY_CUSTOM_MESSAGE_HOOK}
|
|
; discord_log_chicken: 1 = send chicken/death style notifications
|
|
discord_log_chicken=1
|
|
; discord_log_errors: 1 = send a Discord message + error screenshot every time a
|
|
; run fails (approach/battle/exception). Set to 0 to keep error screenshots on
|
|
; disk only. Can also be toggled via [discord_events] error=0.
|
|
discord_log_errors=1
|
|
; discord_status_runs: send periodic status every X completed runs (blank/0 disables)
|
|
discord_status_runs=10
|
|
; discord_status_count: legacy fallback, send periodic status every X games (blank/0 disables)
|
|
discord_status_count=20
|
|
; pickup_drought_window: warn/alert after this many consecutive games with zero
|
|
; item pickups. Raise this if you run a strict pickit and 0-pickup streaks are
|
|
; expected/normal for you (a fast boss-only rush route with a tight filter can
|
|
; easily go 10 games without a keep-worthy drop).
|
|
pickup_drought_window=10
|
|
; message_api_type: "" disables messaging, "discord" or "generic_api"
|
|
message_api_type=discord
|
|
|
|
; breaks
|
|
; break_length_m: scheduled break duration in minutes (0 = disabled)
|
|
break_length_m=0
|
|
; max_runtime_before_break_m: runtime before taking scheduled break (0 = disabled)
|
|
max_runtime_before_break_m=0
|
|
|
|
; timers / fail handling
|
|
; d2r_path: Diablo II: Resurrected install path
|
|
d2r_path=C:\Program Files (x86)\Diablo II Resurrected
|
|
; max_consecutive_fails: stop bot after this many failed runs in a row
|
|
max_consecutive_fails=5
|
|
; max_game_length_s: emergency timeout per run/game
|
|
; 900: a full Chaos Sanctuary clear (3 seals + bosses + loot) takes ~10 min;
|
|
; 600 force-quit a game while literally waiting for Diablo to spawn (2026-06-10).
|
|
; Genuinely stuck games are caught much earlier by max_maintenance_time_s and
|
|
; approach step timeouts.
|
|
max_game_length_s=900
|
|
; max_maintenance_time_s: if the town maintenance loop (heal/buy/stash/repair) takes
|
|
; longer than this many seconds, save-and-exit and rejoin a fresh game.
|
|
; Prevents the bot staying stuck in A5 town forever when NPCs or pathing fail.
|
|
max_maintenance_time_s=240
|
|
; auto_downgrade_threshold: if combined chickens+deaths exceed this number within 1 hour,
|
|
; bot automatically lowers difficulty by one tier (hell->nightmare->normal) and restarts.
|
|
; Set to 0 to disable. (NOTE: feature is parsed but not yet active in bot logic)
|
|
auto_downgrade_threshold=0
|
|
|
|
restart_d2r_when_stuck=1
|
|
; hardcore: 1 enables hardcore-safe assumptions in some routines
|
|
hardcore=0
|
|
|
|
; screenshots
|
|
; info_screenshots: save screenshots for info/chicken/death events
|
|
info_screenshots=1
|
|
; error_screenshots: save a screenshot to log/screenshots/error/ every time a run
|
|
; fails (approach failure, battle failure, or an exception) so logs and visuals can
|
|
; be reviewed side by side. Falls back to info_screenshots if unset.
|
|
error_screenshots=1
|
|
; loot_screenshots: save screenshots for picked loot
|
|
loot_screenshots=0
|
|
; pickit_screenshots: save screenshots for pickit debugging
|
|
pickit_screenshots=1
|
|
|
|
; recovery
|
|
; disable_run_after_failures: after this many CONSECUTIVE failures of the same run
|
|
; (e.g. run_vizier), the bot disables just that run for the rest of the session and
|
|
; keeps doing the other runs instead of stopping. A single success resets the count.
|
|
; If every run gets disabled the bot stops for investigation. Set high to effectively
|
|
; disable this behaviour.
|
|
disable_run_after_failures=5
|
|
; stash_scan_interval: scan all stash tabs and export stash_list.csv every X runs (0 disables)
|
|
stash_scan_interval=0
|
|
|
|
[discord_events]
|
|
; Fine-grained Discord event toggles (1=send, 0=disable)
|
|
; status: periodic status + generic bot messages (breaks, shop notifications, etc.)
|
|
status=1
|
|
; item_keep: send kept item notifications (loot webhooks/embeds)
|
|
item_keep=1
|
|
; death: send death notifications
|
|
death=1
|
|
; chicken: send chicken (emergency leave) notifications
|
|
chicken=1
|
|
; stash_full: send stash full notifications
|
|
stash_full=1
|
|
; gold_full: send gold full notifications
|
|
gold_full=1
|
|
; error: send run-failure notifications (message + error screenshot)
|
|
error=1
|
|
|
|
[stealth]
|
|
; Multiplies all wait() calls by a random value in this range each call
|
|
; 1.0 = no change. Set range wider for more human-like timing variation.
|
|
wait_jitter_min = 0.85
|
|
wait_jitter_max = 1.20
|
|
|
|
; Extra pixel variance added to every mouse click (on top of existing randomize=5)
|
|
; 0 = off, 10 = +/-10px extra random offset per click
|
|
click_variance = 8
|
|
|
|
; Re-shuffle run order after completing a full rotation (vs only at session start)
|
|
; 0: keep [pindle, diablo] fixed so every game ENDS in A4 town (Diablo run TPs
|
|
; there) — the next game then spawns at A4 where Jamella/Cain/Tyrael work,
|
|
; avoiding the A5 Malah vendor entirely (stale templates in current patch).
|
|
reshuffle_each_rotation = 0
|
|
|
|
; Probability (0-100) of randomly skipping a run each game
|
|
; 0 = never skip, 20 = skip ~1 in 5 runs
|
|
skip_run_chance = 0
|
|
|
|
; Probability (0-100) of taking an unscheduled AFK break after any given run
|
|
afk_break_chance = 5
|
|
; Break duration range in minutes
|
|
afk_break_min_m = 2
|
|
afk_break_max_m = 12
|
|
|
|
; Vary run/battle duration by a Gaussian factor (default +/-15%)
|
|
; 0.0 = no variation, 0.3 = up to +/-30% variation
|
|
run_duration_variance = 0.15
|
|
|
|
; Micro-pause between actions (simulates human hesitation in milliseconds)
|
|
micro_pause_min_ms = 20
|
|
micro_pause_max_ms = 120
|
|
|
|
; Vary kill time to avoid perfectly consistent boss fight durations
|
|
vary_kill_time = 1
|
|
|
|
; Human mouse curve complexity (1.0 = default, 0.5 = more direct, 1.5 = more winding)
|
|
human_curve_complexity = 1.0
|
|
|
|
; Arrival-to-click delay: human-like pause between mouse arriving and clicking (milliseconds)
|
|
; 50-800ms range simulates "is this the right thing?" hesitation
|
|
click_delay_min_ms = 50
|
|
click_delay_max_ms = 800
|
|
|
|
; Key press duration variance: how long a key is held (milliseconds)
|
|
; Most presses are short (20-100ms), some linger (up to 200ms)
|
|
key_press_min_ms = 20
|
|
key_press_max_ms = 200
|
|
|
|
; Skill rotation hesitation: pause before casting a skill (milliseconds)
|
|
; Prevents machine-speed skill spam
|
|
skill_hesitation_min_ms = 80
|
|
skill_hesitation_max_ms = 300
|
|
|
|
; Wrong waypoint chance: 2-3% of selecting wrong TP portal then correcting
|
|
; Humans occasionally misclick waypoint targets
|
|
wrong_waypoint_chance = 0.025
|
|
|
|
; Skill mistake chance: 1-2% chance of miscasting and correcting
|
|
; Simulates human error during combat
|
|
skill_mistake_chance = 0.015
|
|
|
|
[routes]
|
|
; Controls which farm runs Botty performs each game.
|
|
; "order" is a comma-delimited list and runs left-to-right when randomize_runs=0.
|
|
; If randomize_runs=1 (in [general]), Botty shuffles enabled runs each game.
|
|
;
|
|
; Hammerdin keyrun recommendation (stable-first):
|
|
; order=run_countess, run_arcane, run_nihlathak
|
|
;
|
|
; Route quick notes:
|
|
; run_trav (Act 3 Travincal council farm; short/high-density run)
|
|
; run_pindle (Act 5 Nihlathak temple red portal boss farm)
|
|
; run_eldritch (Act 5 Frigid Highlands Eldritch-only run)
|
|
; run_eldritch_shenk (Act 5 Eldritch then Shenk in same game)
|
|
; run_nihlathak (Act 5 Halls of Vaught, teleport strongly recommended)
|
|
; run_arcane (Act 2 Arcane Sanctuary / Summoner, teleport strongly recommended)
|
|
; run_diablo (Act 4 Chaos Sanctuary, teleport recommended)
|
|
; run_vizier (Act 4 Chaos Vizier-only route; lighter/faster than full Diablo run)
|
|
; run_andariel (Act 1 Catacombs)
|
|
; run_countess (Act 1 Forgotten Tower)
|
|
; run_mephisto (Act 3 Durance of Hate)
|
|
; run_baal (Act 5 Throne of Destruction)
|
|
; run_baal_xp (Join public Baal games, hide, collect XP, leave — see [baal_xp])
|
|
; The leech is self-contained: it leaves the public game and re-enters its own
|
|
; game inside the cycle, so it must NOT sit between real runs in the rotation.
|
|
; Keep it out of order= (the profile layer may re-arm it between cycles) and
|
|
; enable it with run_baal_xp=1 in the profile's [routes] section.
|
|
order=run_pindle
|
|
|
|
[char]
|
|
; ==========================
|
|
; ==== Mandatory Fields ====
|
|
; ==========================
|
|
; These configs have to be alligned with your d2r settings and char build
|
|
; type: character build profile to use (must match one section below)
|
|
; examples: blizz_sorc, hammerdin, fohdin
|
|
type=fohdin
|
|
; belt_rows: in-game belt size (2/3/4)
|
|
belt_rows=4
|
|
; casting_frames: your char cast breakpoint (affects action timing)
|
|
casting_frames=8
|
|
; cta_casting_frames: cast breakpoint on CTA swap (if used)
|
|
cta_casting_frames=8
|
|
; attack_frames: base attack animation timing for non-cast attacks
|
|
attack_frames=15
|
|
; cta_available: 1 if Call to Arms swap exists, else 0
|
|
cta_available=0
|
|
;Do we want to cast non-cta buffs (ex energy shield) with cta
|
|
buff_with_cta=0
|
|
|
|
; safer_routines: enable for optional defensive maneuvers/etc during combat/runs at the cost of increased runtime (ex. hardcore players)
|
|
safer_routines=1
|
|
|
|
; num_loot_columns: Number of empty columns from left to right of inventory to be used for looting.
|
|
; Store charms, etc. to the right of the inventory.
|
|
num_loot_columns=4
|
|
|
|
; game hotkeys:
|
|
; NOTE: each key must match your in-game binding exactly
|
|
force_move=e
|
|
inventory_screen=i
|
|
potion1=1
|
|
potion2=2
|
|
potion3=3
|
|
potion4=4
|
|
; show_belt is different from the default hotkey as "~" is for many keyboards not reachable without also pressing altgr
|
|
show_belt=k
|
|
show_items=alt
|
|
; stand_still cannot be the default "shift" as it would interfere with merc healing
|
|
stand_still=capslock
|
|
; teleport: leave empty if you can't use
|
|
teleport=b
|
|
town_portal=6
|
|
; call to arms settings:
|
|
; weapon_switch/battle_orders/battle_command only used when cta_available=1
|
|
weapon_switch=w
|
|
battle_orders=7
|
|
battle_command=8
|
|
|
|
; ==========================
|
|
; ==== Optional configs ====
|
|
; ==========================
|
|
stash_gold=1
|
|
use_merc=1
|
|
|
|
; Attack length for barbarians should be as high as 8-10 and even 10-12 for trav/shenk
|
|
;
|
|
; Hammerdin attack lengths (seconds of hammer spam per boss):
|
|
; atk_len_trav = 4.0 (Council of 3 - 3 council members, easy)
|
|
; atk_len_pindle = 8.0 (Pindle — Hell: 13094-16070 HP, 75% fire, 100% poison)
|
|
; Pindle stats by difficulty:
|
|
; Normal: 1064-1588 HP, 75% fire, 70% poison
|
|
; Nightmare: 4773-5859 HP, 100% poison
|
|
; Hell: 13094-16070 HP, 75% fire, 50% cold, 33% light, 100% poison
|
|
; With Conviction (-33% res), Hell Pindle = 50% fire, 17% cold, 0% light, 67% poison
|
|
; CTA adds +100% dmg to hammer. Need ~60%+ FCR and good IAS to kill in 8s.
|
|
; atk_len_nihlathak = 4.0 (Nihlathak - single boss)
|
|
; atk_len_eldritch = 3.0 (Eldritch only - single boss)
|
|
; atk_len_shenk = 4.0 (Shenk only - single boss)
|
|
; atk_len_arc = 2.5 (Summoner in Arcane - single boss)
|
|
; atk_len_diablo = 10.0 (Diablo in CS - longest single boss)
|
|
; atk_len_countess = 3.0 (Countess - single boss, easy)
|
|
; atk_len_andariel = 4.0 (Andariel - single boss)
|
|
; atk_len_mephisto = 12.0 (Mephisto - single boss, high HP)
|
|
; atk_len_baal = 10.0 (Baal - single boss)
|
|
; atk_len_baal_waves = 30.0 (Baal's spawn waves before boss)
|
|
;
|
|
; Chaos Sanctuary (Diablo run) individual fights:
|
|
; atk_len_cs_trashmobs = 2.0 (Trash packs in CS)
|
|
; atk_len_diablo_vizier = 2.0 (Vizier of Chaos - seal boss A)
|
|
; atk_len_diablo_infector = 4.0 (Infector of Souls - seal boss C)
|
|
; atk_len_diablo_deseis = 5.0 (Lord De Seis - seal boss B, hardest seal)
|
|
;
|
|
; Increase these if your hammer kills slower (low IAS/FCR).
|
|
; Decrease if your hammer kills faster (high IAS/FCR, good gear).
|
|
; If you die during a fight, the attack length is too long for your defense.
|
|
atk_len_arc=2.5
|
|
atk_len_eldritch=3.0
|
|
atk_len_nihlathak=4.0
|
|
atk_len_pindle=8.0
|
|
atk_len_shenk=4.0
|
|
atk_len_diablo=3.0
|
|
atk_len_trav=4.0
|
|
|
|
; Boss run attack lengths (per-character defaults in kill_* methods)
|
|
; Adjust these if your build is faster/slower against these bosses
|
|
atk_len_andariel=4.0
|
|
atk_len_countess=3.0
|
|
atk_len_mephisto=12.0
|
|
atk_len_baal=10.0
|
|
atk_len_baal_waves=30.0
|
|
|
|
; Chaos Sanctuary settings
|
|
atk_len_cs_trashmobs=2.0
|
|
atk_len_diablo_deseis=5.0
|
|
atk_len_diablo_infector=4.0
|
|
atk_len_diablo_vizier=2.0
|
|
cs_mob_detect=0
|
|
; cs_town_visits is currently broken, ignore for now
|
|
cs_town_visits=0
|
|
kill_cs_trash=1
|
|
|
|
; Belt settings
|
|
belt_hp_columns=1
|
|
belt_mp_columns=1
|
|
belt_rejuv_columns=2
|
|
|
|
; Potion/chicken settings
|
|
take_health_potion=0.60
|
|
take_mana_potion=0.40
|
|
take_rejuv_potion_health=0.45
|
|
take_rejuv_potion_mana=0.10
|
|
heal_merc=0.70
|
|
heal_rejuv_merc=0.45
|
|
chicken=0.40
|
|
merc_chicken=0.20
|
|
|
|
; Misc.
|
|
; helps reduce accidental pickups when enabled especially on walking characters
|
|
enable_no_pickup=0
|
|
; fill_shared_stash_first: 1 = prefer shared stash tabs before personal stash
|
|
fill_shared_stash_first=0
|
|
; to gamble, add any/all of the following: circlet, ring, coronet, talon, amulet
|
|
gamble_items=
|
|
; open_chests: 1 = open clickable chests along path when possible
|
|
open_chests=1
|
|
; pre_buff_every_run: 1 = always recast buffs at run start
|
|
pre_buff_every_run=1
|
|
; runs_per_repair: visit repair vendor every X runs (blank/0 disables)
|
|
runs_per_repair=5
|
|
; repair_npc: preferred repair vendor strategy.
|
|
; - a5_larzuk (recommended: stays in A5, no cross-act trip; falls back to Halbu)
|
|
; - a4_halbu (requires WP trip to A4 every repair — act desync risk if it fails)
|
|
; - in_act (never leave the current act to repair; repairs only if the act has a
|
|
; vendor, otherwise skips. Use this for routes whose town has no repair vendor,
|
|
; e.g. Travincal/A3, where any other setting means a cross-act trip every cycle)
|
|
; 2026-06-10: switched to a5_larzuk — session logs showed Halbu detection failing
|
|
; 100% (body score ~0.39) and each failed A4 trip desynced the bot's act state.
|
|
repair_npc=a5_larzuk
|
|
; runs_per_stash: stash/sell every X runs (blank/0 disables)
|
|
runs_per_stash=4
|
|
; sell_junk: 1 = vendor non-keep items automatically
|
|
sell_junk=1
|
|
; protect_shields_from_sell: 1 = never vendor items with "shield" in detected name (recommended safety)
|
|
protect_shields_from_sell=1
|
|
; protect_charms_from_sell: 1 = never drop/vendor charms regardless of pickit verdict
|
|
; (recommended safety — a misread charm can't be un-dropped). Set to 0 to let your
|
|
; pickit rules decide keep/discard for charms same as any other item.
|
|
protect_charms_from_sell=1
|
|
; pick_rares_for_gold: 1 = pick all yellow (rare) ground items; non-keep rares will be sold
|
|
; Requires sell_junk=1 to convert extra pickups into gold.
|
|
pick_rares_for_gold=0
|
|
; pick_gold: 1 = pick up ground gold piles, 0 = ignore all ground gold
|
|
pick_gold=1
|
|
|
|
[transmute]
|
|
;stash tabs by priority where to put transmuted gems
|
|
stash_destination=0,1,2,3
|
|
; Add these possible gems to "transmute" to transmute them:
|
|
; chipped, flawed, standard, flawless
|
|
transmute=flawless
|
|
;how often we want to run transmute routine(e.g. every 100 games)
|
|
transmute_every_x_game=60
|
|
; number of stash tabs (ROTW has more than 6, adjust as needed)
|
|
stash_tabs=6
|
|
; potion transmute settings
|
|
; convert_rejuv: 1 = convert regular Rejuv Potions to Full Rejuv via cube (3 -> 1)
|
|
convert_rejuv=1
|
|
; min_rejuv_to_convert: minimum regular rejuv potions in inventory before starting conversion
|
|
min_rejuv_to_convert=6
|
|
|
|
; ===========================
|
|
; ==== Builds: Sorceress ====
|
|
; ===========================
|
|
[sorceress]
|
|
energy_shield=f4
|
|
frozen_armor=f7
|
|
static_field=f5
|
|
telekinesis=f6
|
|
thunder_storm=
|
|
|
|
[light_sorc]
|
|
; chain_lightning must be bound to left skill (hotkey optional as it shouldnt change)
|
|
chain_lightning=
|
|
; lightning must be right skill, hotkey required
|
|
lightning=
|
|
; frozen orb must be right skill, hotkey recommended to increase safty for you and merc at trav!
|
|
frozen_orb=
|
|
|
|
[blizz_sorc]
|
|
; blizzard must be right skill, hotkey required
|
|
blizzard=f1
|
|
; ice_blast must be left skill (hotkey optional as it shouldnt change)
|
|
ice_blast=f2
|
|
|
|
[blizzorb_sorc]
|
|
; frozen orb must be left skill and preselected (no hotkey required)
|
|
|
|
;All others must be right skill and hotkey required!
|
|
blizzard=f1
|
|
glacial_spike=f7
|
|
|
|
[nova_sorc]
|
|
; nova must be right skill, hotkey required
|
|
nova=f1
|
|
|
|
[hydra_sorc]
|
|
; only supports Pindle and Eldritch currently
|
|
; alt_attack is any alternate attacking right skill. Fireball,Lightning,Frozen Orb, hotkey required
|
|
alt_attack=f7
|
|
; hydra must be right skill, hotkey required
|
|
hydra=f1
|
|
|
|
; =========================
|
|
; ==== Builds: Paladin ====
|
|
; =========================
|
|
[paladin]
|
|
cleansing=f9
|
|
holy_shield=f2
|
|
redemption=f3
|
|
vigor=f4
|
|
|
|
[fohdin]
|
|
; foh must be left skill, hotkey required
|
|
blessed_hammer=f1
|
|
concentration=f8
|
|
conviction=f5
|
|
foh=f6
|
|
holy_bolt=f7
|
|
|
|
[hammerdin]
|
|
; Verified against the live client 2026-09-04 by pressing F1-F8 and reading the
|
|
; right skill slot (D2R renders the key label into the icon, so the crops are
|
|
; self-proving): f2=Holy Shield, f3=Redemption, f4=a charged item skill,
|
|
; f5=TELEPORT, f6=Concentration, f8=an aura with no template (Conviction);
|
|
; f1 and f7 are UNBOUND — pressing them changes nothing.
|
|
;
|
|
; Blessed Hammer sits permanently on LEFT-click. No hotkey puts it on the right
|
|
; slot, so it needs no key here; the preflight checks the left slot directly.
|
|
blessed_hammer=
|
|
concentration=f6
|
|
; conviction was set to f5 — which is TELEPORT on this client, so every
|
|
; attack-aura cast would have teleported the character. Conviction is also
|
|
; useless to a hammerdin (Bug 17: it does not boost magic damage) and
|
|
; Concentration is the correct aura, so leave this unbound.
|
|
conviction=
|
|
|
|
; =========================
|
|
; ==== Builds: Warlock ====
|
|
; =========================
|
|
[warlock]
|
|
; All skills should be on right-click unless otherwise specified
|
|
deathmark=f3
|
|
lethargy=f4
|
|
;Set summon_demon to one of the three demons of your choice.
|
|
summon_demon=f5
|
|
;If you are summoning a 2nd demon set hotkey here. Can be same as above
|
|
summon_demon2=
|
|
psychic_ward=
|
|
|
|
[fire_lock]
|
|
; Supported runs: Pindle
|
|
;flame_wave must be assigned to left-click and doesn't require hotkey
|
|
ring_of_fire=f1
|
|
apocalypse=f2
|
|
|
|
[abyss_lock]
|
|
; Supported runs: Pindle
|
|
;miasma_bolt must be assigned to left-click and doesn't require hotkey
|
|
miasma_chain=f1
|
|
abyss=f2
|
|
|
|
[echo_lock]
|
|
; Supported runs: Trav (tele only)
|
|
echo_strike=f1
|
|
eldritch_blast=f2
|
|
hex_bane=f3
|
|
;Set ring of fire if you want to stun before echo blast
|
|
ring_of_fire=
|
|
|
|
; ==========================
|
|
; ==== Builds: Assassin ====
|
|
; ==========================
|
|
; Currently no Trav implementaiton!
|
|
[trapsin]
|
|
; We assume fire blast or shock web is left-click skill which is optional hotkey if pre-assigned.
|
|
skill_left=
|
|
; Assume all other skills are right-click and hotkey required!
|
|
burst_of_speed=f1
|
|
death_sentry=f2
|
|
fade=
|
|
lightning_sentry=f3
|
|
shadow_warrior=f4
|
|
mind_blast=f5
|
|
|
|
; ===========================
|
|
; ==== Builds: Barbarian ====
|
|
; ===========================
|
|
; Supported runs: Trav, Pindle, Eld, Shenk, Nihlathak (tele only)
|
|
; Make sure leap hotkey is set if you do not have Enigma
|
|
; Ensure Battle Order/Command hotkeys are set above in the [char] section
|
|
[barbarian]
|
|
cry_frequency=0.7
|
|
find_item=
|
|
leap=
|
|
shout=
|
|
war_cry=
|
|
|
|
; ===========================
|
|
; ==== Builds: Amazon ====
|
|
; ===========================
|
|
; Supported runs: Trav, Pindle, Eld, Shenk, Nihlathak (tele only)
|
|
; Make sure leap hotkey is set if you do not have Enigma
|
|
; Ensure Battle Order/Command hotkeys are set above in the [char] section
|
|
[amazon]
|
|
;all must be right-click skill
|
|
valkyrie=f1
|
|
|
|
[javazon]
|
|
; charged strike must be left-click skill and preselected, no hotkey required
|
|
|
|
;all others must be right-click
|
|
lightning_fury=f2
|
|
|
|
; ==========================
|
|
; ==== Builds: Necro ====
|
|
; ==========================
|
|
; Pindle+eld+shenk+trav (walking only!)
|
|
; needs all of these skills
|
|
;skill_left is just some ranged damage spell (spear,teeth, nova,etc)
|
|
;leave teleport blank for now this build currently is walking only
|
|
;tested with something like this https://d2.maxroll.gg/d2planner/3x01067c
|
|
;recomended to set skeleton mage to same as revive hot hey
|
|
;skeleton mages cause pathing issues not ideal to use yet
|
|
[necro]
|
|
amp_dmg=
|
|
bone_armor=
|
|
clay_golem=
|
|
clear_pindle_pack=
|
|
corpse_explosion=
|
|
heart_of_wolverine=
|
|
raise_mage=
|
|
raise_revive=
|
|
raise_skeleton=
|
|
skill_left=
|
|
|
|
[poison_necro]
|
|
bone_armor=
|
|
# Can use any golem
|
|
clay_golem=
|
|
clear_pindle_pack=
|
|
corpse_explosion=
|
|
heart_of_wolverine=
|
|
# Can Use any curse
|
|
lower_res=
|
|
poison_nova=
|
|
raise_mage=
|
|
raise_revive=
|
|
raise_skeleton=
|
|
# Not Required
|
|
skill_left=
|
|
|
|
[bone_necro]
|
|
bone_armor=
|
|
bone_spear=
|
|
bone_spirit=
|
|
bone_wall=
|
|
clay_golem=
|
|
teeth=
|
|
; Damage scaling. One setting to adjust kill speed to account for better/worse gear.
|
|
; ex: 2 will cast all attack skills twice a long, .5 half as long. Currently only used by bone necro
|
|
damage_scaling=1
|
|
|
|
|
|
; ==== Builds: Basic ====
|
|
; Supported runs: UNTESTED (this is your job!)
|
|
; this will basically continuously left attack, unless right attack is available.
|
|
; if the buffs are not set they are not used (they are part of the prebuff setup)
|
|
|
|
[basic]
|
|
left_attack=1
|
|
right_attack=
|
|
buff_1=
|
|
buff_2=
|
|
|
|
|
|
; ==== Builds: Basic Ranged====
|
|
; Supported runs: UNTESTED (this is your job!)
|
|
; this will basically continuously left attack, unless right attack is available.
|
|
; if the buffs are not set they are not used (they are part of the prebuff setup)
|
|
|
|
[basic_ranged]
|
|
left_attack=
|
|
right_attack=
|
|
buff_1=
|
|
buff_2=
|
|
|
|
|
|
; ==== Run: Cold Plains clear ====
|
|
; Roams an outdoor area and kills with ONE configured skill. Works with any build
|
|
; and from clvl 1, so it is the levelling counterpart to the boss runs.
|
|
; Enable by adding run_cold_plains to [routes] order above.
|
|
;
|
|
; PREREQUISITE: the character must already have the destination waypoint.
|
|
; A fresh character has none - walk there once by hand first.
|
|
[cold_plains]
|
|
; Any Act 1 waypoint label from src/ui/waypoint.py _WAYPOINTS, e.g.
|
|
; "Cold Plains", "Stony Field", "Dark Wood", "Black Marsh".
|
|
area=Cold Plains
|
|
; Key holding the attack skill. NOTE Fireball is clvl 12 - on a fresh character
|
|
; put Fire Bolt (clvl 1) here and re-bind to Fireball later; nothing else changes.
|
|
attack_hotkey=
|
|
; Most sorc/caster skills cast on right click. Melee builds want "left".
|
|
attack_button=right
|
|
; How many roam-or-fight steps before heading back to town.
|
|
max_steps=12
|
|
; Casts per engagement before re-scanning for targets.
|
|
casts_per_target=4
|
|
; Ignore anything further than this many px from the character.
|
|
target_radius=600
|
|
; Delay between casts. Raise if you out-run your cast animation.
|
|
cast_delay=0.25
|
|
; Hard runtime cap per run, seconds - stops a bad area pinning the bot.
|
|
max_runtime_s=180
|
|
; Engagements per step, so an unkillable/misdetected target cannot stall the run.
|
|
max_engagements=8
|
|
|
|
[baal_xp]
|
|
; Baal XP farm: join public Baal games, hide, collect XP, leave. Repeat.
|
|
; Enable by adding run_baal_xp to [routes] order above.
|
|
enabled=1
|
|
; Substring to match against game names (case-insensitive). Empty = join first game.
|
|
game_name_filter=baal
|
|
; Max seconds to wait in a game before leaving (XP keeps ticking while you hide).
|
|
max_wait_s=900
|
|
; Leave early if XP gained in this game reaches this value.
|
|
xp_threshold=50000000
|
|
; Leave immediately if HP drops below this percent.
|
|
min_hp_pct=40
|
|
; Screen position (1280x720) to walk to and stand still.
|
|
; NOTE: this is a SCREEN coordinate and the character is drawn at ~(640,340),
|
|
; so the old (640,360) meant "click on yourself" and the character never moved.
|
|
; (775,135) runs up-and-right to the pillar, off the lane the waves path down.
|
|
hide_x=775
|
|
hide_y=135
|
|
; Max seconds to wait for a matching game to appear in the browser.
|
|
join_timeout_s=180
|
|
; Difficulty of the public games to join: normal | nightmare | hell.
|
|
; Hiding in a game above the character's level is a death sentence.
|
|
difficulty=normal
|
|
; Join games in this player band. This is a PREFERENCE, not a hard gate: when
|
|
; no game in the band is listed, the best remaining game is joined anyway and
|
|
; the in-game checks (portal wait, party size, XP idle) decide whether it is
|
|
; worth staying. Keep min_players at 1: a public Baal game spawns at 1-2 players
|
|
; and fills within seconds, so a 3-player floor skips every real game and the
|
|
; join fails every cycle (observed 2026-09-02: all listed games read 1-2p and
|
|
; were skipped, the fallback candidate's join never completed, and the cycle
|
|
; failed until the controller's circuit breaker restarted D2R).
|
|
min_players=1
|
|
max_players=7
|
|
; Take the host's town portal to the Throne rather than hiding in town.
|
|
; XP is shared by area, so town hiding earns nothing during the actual run.
|
|
take_portal=1
|
|
; Skip town maintenance when run_baal_xp is the only route. A leech buys,
|
|
; repairs and stashes nothing, and the vendor/waypoint pathing strands the
|
|
; character against the town wall when it fails.
|
|
skip_town_maintenance=1
|
|
; How long to watch for a portal to open before giving up on this game.
|
|
portal_wait_s=480
|
|
; If no portal opens, leave and try another game this many times.
|
|
portal_game_attempts=3
|
|
; If the in-game party has at least this many portraits, stay put even
|
|
; with no portal yet - a game that full is a real run.
|
|
stay_party_size=6
|
|
; Only enter a portal whose hover label contains this. A Baal town has
|
|
; several portals; the others go wherever their owner was standing.
|
|
portal_label=THRONE
|
|
; If more than this many players leave at once the run is over - leave too.
|
|
leave_on_departures=3
|
|
; Leave once XP has not moved for this long - the run has finished.
|
|
xp_idle_s=120
|
|
; Open the chat every chat_poll_s and look for the next-game call.
|
|
; Best-effort: the OCR model renders the mixed-case chat font poorly, so this
|
|
; is a bonus signal - xp_idle_s is the reliable one.
|
|
chat_monitor=1
|
|
chat_poll_s=20
|
|
; Chat words that mean 'stop hiding here and leave'.
|
|
; ng = host is rolling the next game
|
|
; bot = someone called us out
|
|
chat_leave_tokens=ng,bot
|
|
; Chat words that mean 'take the portal up to the Throne'.
|
|
chat_portal_tokens=up
|
|
; Fuzzy-match strength for the portal label (labels OCR badly on a bright ring).
|
|
portal_label_ratio=0.7
|
|
; Skip re-reading a portal we already rejected for this long.
|
|
portal_recheck_s=25
|
|
; Leave a game early once every portal in it reads clearly as a non-match.
|
|
portal_stale_s=90
|
|
|
|
[advanced_options]
|
|
; startup hotkeys
|
|
; select_runs_key: open run selector UI
|
|
select_runs_key=pagedown
|
|
; restore_settings_from_backup_key: restore backed-up D2R settings
|
|
restore_settings_from_backup_key=insert
|
|
; settings_backup_key: create backup of current D2R settings
|
|
settings_backup_key=pause
|
|
; auto_settings_key: auto-apply required D2R settings
|
|
auto_settings_key=pageup
|
|
; graphic_debugger_key: toggle on-screen debug layers
|
|
graphic_debugger_key=delete
|
|
; resume_key: start/pause bot loop
|
|
resume_key=f11
|
|
; exit_key: hard stop bot
|
|
exit_key=f12
|
|
; cycle_pickit_profile_key: cycle through pickit profiles in config/pickit_profiles/
|
|
cycle_pickit_profile_key=f10
|
|
|
|
; etc.
|
|
; graphic_debugger_layer_creator: 1 = enable interactive layer creator tooling
|
|
graphic_debugger_layer_creator=0
|
|
; hwnd_window_process: process regex used to locate D2R window handle
|
|
hwnd_window_process=D2R\.exe
|
|
; hwnd_window_title: optional title regex override for window lookup
|
|
hwnd_window_title=
|
|
; launch_options: will replace <name> with setting for [general] "name" above
|
|
launch_options=-mod <name> -txt
|
|
; logg_lvl: logging verbosity (debug/info/warning/error)
|
|
logg_lvl=debug
|
|
; message_body_template: payload template for generic_api mode
|
|
message_body_template={{"content": "{msg}"}}
|
|
; message_headers: optional JSON headers for generic_api mode
|
|
message_headers=
|
|
; ocr_during_pickit: 1 = run OCR while looting (slower, more diagnostics)
|
|
ocr_during_pickit=0
|
|
;use "can_teleport_natively" or "can_teleport_with_charges" if you want to force certain behavior in case autodetection isn't working properly
|
|
override_capabilities=can_teleport_natively
|
|
; pathing_delay_factor: movement/click delay multiplier (1 fast .. 10 slow)
|
|
pathing_delay_factor=2
|
|
; If you want to control Hyper-V window from host use 0,51 here
|
|
; window_client_area_offset: x,y pixel offset for captured game client area
|
|
window_client_area_offset=0,0
|
|
|
|
[log_rotation]
|
|
; Log rotation prevents screenshot directories from filling the disk.
|
|
; Each managed directory has a max file count and max total size.
|
|
; When limits are exceeded, oldest files are deleted automatically.
|
|
; Checked every 60 seconds (to avoid I/O overhead during runs).
|
|
;
|
|
; The text log (log/log.txt) is size-capped separately: it rotates at 50 MB,
|
|
; keeps 5 zipped backups in log/archive/ (max 30 archives). Override the per-file
|
|
; cap with the BOTTY_LOG_MAX_MB environment variable (e.g. set 100 for 100 MB).
|
|
|
|
; pickit directory (log/screenshots/pickit/):
|
|
; Can grow very fast — every item scan writes a PNG + JSON.
|
|
; pickit_max_files=500 ; max files before rotation kicks in
|
|
; pickit_max_mb=500 ; max total size in MB
|
|
pickit_max_files=300
|
|
pickit_max_mb=200
|
|
|
|
; info directory (log/screenshots/info/):
|
|
; Debug screenshots for deaths, chickens, errors, etc.
|
|
; info_max_files=200 ; max files before rotation kicks in
|
|
; info_max_mb=500 ; max total size in MB
|
|
info_max_files=100
|
|
info_max_mb=200
|
|
|
|
; items directory (log/screenshots/items/):
|
|
; Loot screenshots sent to Discord.
|
|
; items_max_files=100
|
|
; items_max_mb=100
|
|
items_max_files=50
|
|
items_max_mb=50
|
|
|
|
; discord_notify_rotation: 1 = send Discord message when log rotation deletes files
|
|
discord_notify_rotation=0
|