###################################################### ### INIT FILE SETTINGS ### ###################################################### default_autopickup = true default_manual_training = true travel_delay = -1 travel_open_doors = open explore_delay = -1 explore_auto_rest = true tile_show_minihealthbar = true tile_show_minimagicbar = true tile_player_status_icons = true tile_realtime_anim = true ###################################################### ### SOUND SETTINGS ### ###################################################### sound_on = true sound_debug = true sound_volume = 0.1 sound_pack += https://osp.nemelex.cards/build/latest.zip:["init.txt"] sound_pack += https://sound-packs.nemelex.cards/Autofire/BindTheEarth/BindTheEarth.zip sound_pack += https://MsNecromancer.github.io/se/DCSSv.02.zip ###################################################### ### LUA SETTINGS ### ###################################################### < local my_class = "" local my_race = "" --#################################################### --### SAVED VALUES ### --#################################################### -- Ensure defaults cleared_floors = cleared_floors or {} max_slots = max_slots or {} start_of_game = start_of_game or true -- Hook: called when saving table.insert(chk_lua_save, function() local parts = {} -- Save cleared_floors (key/value table) if cleared_floors then local floor_parts = {} for k, v in pairs(cleared_floors) do -- keys are strings, values are booleans table.insert(floor_parts, string.format("[%q] = %s", k, tostring(v))) end table.insert(parts, "cleared_floors = {" .. table.concat(floor_parts, ", ") .. "}") end -- Save max_slots (array of numbers) if max_slots then local slot_parts = {} for i, v in ipairs(max_slots) do table.insert(slot_parts, tostring(v)) end table.insert(parts, "max_slots = {" .. table.concat(slot_parts, ", ") .. "}") end -- Save start_of_game (boolean) if start_of_game ~= nil then table.insert(parts, "start_of_game = " .. tostring(start_of_game)) end -- Return a chunk of Lua that will be executed on load return table.concat(parts, "\n") end) --#################################################### --### READY ### --#################################################### function ready() my_class = you.class() my_race = you.race() if not my_class or not my_race then return end if start_of_game and you.turns() <= 0 then clear_skills() setup_macros() max_slots = max_slots_calc() start_of_game = false end default_skill_training() add_autopickup_func(my_autopickup_filter) equip_auxiliary_armour() auto_train_spells() end --#################################################### --### GET MAX SLOTS FOR RACE ### --#################################################### function max_slots_calc() local max_slots = {1, 1, 1, 1, 1, 1, 1, 2} --[1] offhand --[2] body --[3] helmet --[4] cloak --[5] gloves --[6] boots --[7] amulet --[8] rings if my_race == "Poltergeist" then max_slots[2] = 6 -- body max_slots[3] = 0 -- helmet max_slots[4] = 0 -- cloak max_slots[5] = 0 -- gloves max_slots[6] = 0 -- boots end return max_slots end --#################################################### --### DEFAULT AUTO PICKUP ### --#################################################### local logged_items = {} -- Define the auxiliary armor subtypes table globally or in a place that's loaded first -- auxiliary_armor (keep this globally) local auxiliary_armor = { hat = true, helmet = true, cloak = true, scarf = true, gloves = true, boots = true } -- Count how many auxiliary armour items are currently equipped. function count_equipped_aux() local count = 0 for _, item in ipairs(items.inventory()) do if auxiliary_armor[item:subtype()] and item.equipped then count = count + 1 end end return count end -- Autopickup filter: allow pickup while Poltergeist hasn't filled its aux "body" slots. function my_autopickup_filter(item, name) if my_race == "Poltergeist" and max_slots and max_slots[2] then local total_equipped = count_equipped_aux() if auxiliary_armor[item:subtype()] and total_equipped < max_slots[2] then crawl.mpr("Equipped: " .. (total_equipped + 1) .. "/" .. max_slots[2]) return true end end return nil end --#################################################### --### EQUIP AUXILIARY ARMOUR ### --#################################################### function equip_auxiliary_armour() if not you.feel_safe() then return end if not max_slots then max_slots = max_slots_calc() end local equipped_count = count_equipped_aux() local limit = (max_slots and max_slots[2]) or 1 if equipped_count >= limit then return end for _, item in ipairs(items.inventory()) do if equipped_count >= limit then break end if auxiliary_armor[item:subtype()] and not item.equipped then item:equip() -- verify it actually equipped, then update the counter and mpr if item.equipped then equipped_count = equipped_count + 1 crawl.mpr("Equipped auxiliary (" .. equipped_count .. "/" .. limit .. ")") else crawl.mpr("Failed to equip auxiliary (subtype: " .. tostring(item:subtype()) .. ")") end end end end --#################################################### --### DEFAULT MACROS ### --#################################################### function setup_macros() crawl.setopt("macros = M z z?") --Clears all macros crawl.setopt("autopickup_exceptions += <.*javelins?") crawl.setopt("autopickup_exceptions += <.*darts?") crawl.setopt("autopickup_exceptions += Applied Deep Elf Necromancer macros.") end crawl.setopt("macros += M 1 za.") crawl.setopt("macros += M 2 zb.") crawl.setopt("macros += M 3 zc.") crawl.formatted_mpr("Applied Necromancer macros.") elseif my_race == "Minotaur" and my_class == "Berserker" then crawl.setopt("macros += M 1 zf.") crawl.formatted_mpr("Applied Minotaur Berserker macros.") elseif my_race == "Poltergeist" and my_class == "Enchanter" then crawl.setopt("macros += M 1 za.") crawl.setopt("macros += M 2 zb*") crawl.setopt("more += Holy wrath)") else crawl.formatted_mpr("No Macros Set!!") end end --#################################################### --### SPELL AUTO LEARN ### --#################################################### -- Hook to run after each turn function auto_train_spells() if not you.feel_safe() then return end -- list of spells in the order you want to learn local spell_list = { "Ensorcelled Hibernation", "Dazzling Flash", "Tukima's Dance" } local available = you.mem_spells() for _, spell_name in ipairs(spell_list) do local can_memorise = false for _, s in ipairs(available) do if s == spell_name then can_memorise = true break end end if can_memorise and spells.level(spell_name) <= you.xl() and spells.level(spell_name) <= you.spell_levels() then if you.memorise(spell_name) then crawl.mpr("Auto-memorised spell: " .. spell_name, "lightgreen") end end end end --#################################################### --### DEFAULT TRAINING SETUP ### --#################################################### function clear_skills() local all_skills = {"Fighting","Short Blades","Long Blades","Axes","Maces & Flails","Polearms","Staves","Unarmed Combat","Throwing","Ranged Weapons","Armour","Dodging","Shields","Stealth","Spellcasting","Conjurations","Hexes","Summonings","Necromancy","Translocations","Alchemy","Forgecraft","Fire Magic","Ice Magic","Air Magic","Earth Magic","Invocations","Evocations",} for _, skill in ipairs(all_skills) do if you.can_train_skill(skill) then you.train_skill(skill, 0) you.set_training_target(skill,0) end end crawl.mpr("All skills cleared.", "lightgray") end --#################################################### --### DEFAULT SKILL TRAINING ### --#################################################### function skill_training_needed() --Runs when no skills being trained default_skill_training() return true -- TRUE: skips menu -- FALSE: Shows menu for comfirmation end function default_skill_training() -- Must have either the Race and Class or just the Class. -- {Name of Skill, Traget_Leve, Priority(O: None, 1: Normal, 2: Focused)}, -- With Priority: Train all skills at once. -- Without Priority: Train skills top to bottom in order. local skill_plans = { ["Poltergeist Enchanter"] = { {"Stealth", 6.0}, {"Hexes", 6.0}, {"Spellcasting", 2.5}, {"Fighting", 2.0}, {"Dodging", 5.0}, {"Short Blades", 4.0}, {"Ice Magic", 2.0}, {"Hexes", 10.0}, }, ["Minotaur Berserker"] = { {"Fighting", 6.0, 2}, {"Armour", 6.0, 1}, {"Axes", 12.5, 2}, {"Dodging", 2.0, 1}, {"Short Blades", 4.0, 1}, {"Stealth", 10.0, 1}, }, } local plan_name = my_race .. " " .. my_class local plan = skill_plans[plan_name] or skill_plans[my_class] if not plan then return end local train_all_at_once = (#plan[1] == 3) if start_of_game and train_all_at_once then -- Train all skills at once with priorities for _, skill_data in ipairs(plan) do local skill_name = skill_data[1] local target_level = skill_data[2] local priority = skill_data[3] you.train_skill(skill_name, priority) you.set_training_target(skill_name, target_level) end else -- Sequential training: check which skill still needs XP for _, skill_data in ipairs(plan) do local skill_name = skill_data[1] local target_level = skill_data[2] if you.skill(skill_name) < target_level then you.train_skill(skill_name, 1) you.set_training_target(skill_name, target_level) break -- only one active at a time end end end end --#################################################### --### MESSAGE HANDLER ### --#################################################### local exclude_floors = {["Temple:1"] = true, ["Necropol:1"] = true} function c_message(text, channel) --[↓] RE-SEARCH THE CURRENT FLOOR WHEN CLEARED ONCE [↓]-- local current_floor = (you.branch() .. ":" .. you.depth()) if not cleared_floors[current_floor] and channel == "plain" and text:find("Done exploring.") then if not exclude_floors[current_floor] then crawl.sendkeys("X", 6, 27) end cleared_floors[current_floor] = true end --[↑] RE-SEARCH THE CURRENT FLOOR WHEN CLEARED ONCE [↑]-- --[↓] GIVE THE CHANNEL FOR EVERY MESSAGE [↓]-- --crawl.mpr("[" .. channel .. ": ".. crawl.msgch_num(channel) .."] " .. text) end >