# This prevents the "More" prompt from triggering for distortion weapons runrest_ignore_message += distortion runrest_ignore_message += reaches for .* distortion runrest_ignore_message += wielding .* distortion # Optional: If you find other messages stopping you, add them here runrest_ignore_message += is wielding { local function autopickup(it, name) if it.is_useless then return false end local class = it.class(true) if class == "armour" then local good_slots = {cloak="Cloak", helmet="Helmet", gloves="Gloves", boots="Boots"} st, _ = it.subtype() if good_slots[st] ~= nil and items.equipped_at(good_slots[st]) == nil then return true end end end clear_autopickup_funcs() add_autopickup_func(autopickup) } < farming_enabled = false macro_timer = 0 user_limit = 5000 -- Prevent engine timeout/crashes function do_stop() if stop_activity then stop_activity() elseif crawl.stop_activity then crawl.stop_activity() elseif you.stop_activity then you.stop_activity() else crawl.sendkeys("\27") end end function is_ff_active() if you.status then return you.status("Fusillade") end if status then return status("Fusillade") end return false end function get_level_turns() if you.turns_on_level then return you.turns_on_level() end if turns_on_level then return turns_on_level() end return 0 end -- NEW: Helper to check if a monster has specifically dangerous spells function has_dangerous_spells(mon) local spells = mon:spells() if not spells then return false end for _, sname in ipairs(spells) do if sname == "Warp Body" or sname == "Brain Bite" or sname == "Call Down Damnation" then return true end end return false end -- SCANNER: Returns the highest threat in LOS and its coordinates function get_threat_info() local max_threat = -1 local tx, ty = nil, nil local adj_x, adj_y = nil, nil for r = 1, 7 do for dx = -r, r do for dy = -r, r do local mon = monster.get_monster_at(dx, dy) if mon and not mon:is_safe() then local threat = mon:threat() -- NEW LOGIC: Upgrade threat if monster has dangerous spells if threat < 2 and has_dangerous_spells(mon) then threat = 2 end if threat > max_threat then max_threat = threat tx, ty = dx, dy end if math.max(math.abs(dx), math.abs(dy)) == 1 then adj_x, adj_y = dx, dy end end end end end return max_threat, tx, ty, adj_x, adj_y end -- Helper: Checks for adjacent escape square function get_escape_square() for dx = -1, 1 do for dy = -1, 1 do if not (dx == 0 and dy == 0) then local mon = monster.get_monster_at(dx, dy) if mon and not mon:is_safe() then local ex, ey = -dx, -dy if view.is_safe_square(ex, ey) then return ex, ey end end end end end return nil, nil end -- Helper: Movement/Melee Translation function move_or_attack(dx, dy) local keys = { [-1] = {[-1] = "y", [0] = "h", [1] = "b"}, [0] = {[-1] = "k", [1] = "j"}, [1] = {[-1] = "u", [0] = "l", [1] = "n"} } if keys[dx] and keys[dx][dy] then crawl.process_keys(keys[dx][dy]) return true end return false end -- Toggle function bound to ; function toggle_pan_farm() if not farming_enabled then local res = crawl.yesno("Are you sure you want to start Pan Farming? (y/n)", true, "n") if not res then return end if crawl.yesno("Run for a LONG session (10,000 turns)?", true, "n") then user_limit = 10000 elseif crawl.yesno("Run for a MEDIUM session (5,000 turns)?", true, "n") then user_limit = 5000 elseif crawl.yesno("Run for a SHORT session (1,000 turns)?", true, "n") then user_limit = 1000 else user_limit = 100 end farming_enabled = true macro_timer = 0 crawl.mpr("Intelligent Pan Farm: ENABLED (Limit: " .. user_limit .. " turns)") else farming_enabled = false crawl.mpr("Intelligent Pan Farm: DISABLED") end end -- Ready Loop function ready() if not farming_enabled then return end -- 1. SAFETY CHECKS local cur_hp, max_hp = you.hp() if cur_hp < (max_hp * 0.73) then farming_enabled = false crawl.mpr("HP Low! Emergency Stop.") do_stop() return end local cur_mp, _ = you.mp() if cur_mp < 8 then farming_enabled = false crawl.mpr("Mana Low! Emergency Stop.") do_stop() return end if get_level_turns() >= 25000 then farming_enabled = false crawl.mpr("Level Turn Limit reached. Stopping macro.") do_stop() return end -- 2. MACRO TIMER RESET macro_timer = macro_timer + 1 if macro_timer >= user_limit then farming_enabled = false crawl.mpr("Target turns reached (" .. user_limit .. ")! Stopping macro.") do_stop() macro_timer = 0 return end -- Initial Turn Delay crawl.delay(15) -- 3. COMBAT SCAN local max_threat, tx, ty, adj_x, adj_y = get_threat_info() if max_threat >= 0 then -- LOGIC A: SERIOUS THREAT (Threat 2 or 3, or dangerous spells) if max_threat >= 0 then if not is_ff_active() then crawl.mpr("Dangerous enemy! Casting Fusillade...") if spells.cast("Fulsome Fusillade", tx, ty) then crawl.delay(100) return end end if adj_x then local ex, ey = get_escape_square() if ex then crawl.mpr("Kiting dangerous threat...") move_or_attack(ex, ey) else crawl.mpr("Blocked! Blinking...") spells.cast("Blink", 0, 0) end crawl.delay(100) else crawl.process_keys(".") crawl.delay(50) end return end -- LOGIC B: LOW THREAT (Threat 0 or 1, no dangerous spells) if max_threat <= 1 then if adj_x then crawl.mpr("Low threat adjacent. Melee attack.") move_or_attack(adj_x, adj_y) crawl.delay(50) else crawl.process_keys(".") crawl.delay(50) end return end else crawl.process_keys(".") end end > -- Bind the toggle to the semicolon (;) key macros += M ; ===toggle_pan_farm