##### Crawl Init file ############################################### # For descriptions of all options, as well as some more in-depth information # on setting them, consult the file # options_guide.txt # in your /docs directory. If you can't find it, the file is also available # online at: # https://github.com/crawl/crawl/blob/master/crawl-ref/docs/options_guide.txt # # Crawl uses the first file of the following list as its option file: # * init.txt in the -rcdir directory (if specified) # * .crawlrc in the -rcdir directory (if specified) # * init.txt (in the Crawl directory) # * ~/.crawl/init.txt (Unix only) # * ~/.crawlrc (Unix only) # * ~/init.txt (Unix only) # * settings/init.txt (in the Crawl directory) ##### Some basic explanation of option syntax ####################### # Lines beginning with '#' are comments. The basic syntax is: # # field = value or field.subfield = value # # Only one specification is allowed per line. # # The terms are typically case-insensitive except in the fairly obvious # cases (the character's name and specifying files or directories when # on a system that has case-sensitive filenames). # # White space is stripped from the beginning and end of the line, as # well as immediately before and after the '='. If the option allows # multiple comma/semicolon-separated terms (such as # autopickup_exceptions), all whitespace around the separator is also # trimmed. All other whitespace is left intact. # # There are three broad types of Crawl options: true/false values (booleans), # arbitrary values, and lists of values. The first two types use only the # simple =, with later options - which includes your options that are different # from the defaults - overriding earlier ones. List options allow using +=, ^=, # -=, and = to append, prepend, remove, and reset, respectively. Usually you will # want to use += to add to a list option. Lastly, there is := which you can use # to create an alias, like so: # ae := autopickup_exceptions # From there on, 'ae' will be treated as if it you typed autopickup_exceptions, # so you can save time typing it. # ##### Other files ################################################### # You can include other files from your options file using the 'include' # option. Crawl will treat it as if you copied the whole text of that file # into your options file in that spot. You can uncomment some of the following # lines by removing the beginning '#' to include some of the other files in # this folder. # Some useful, more advanced options, implemented in LUA. # include = advanced_optioneering.txt # Alternative vi bindings for Dvorak users. # include = dvorak_command_keys.txt # Alternative vi bindings for Colemak users. # include = colemak_command_keys.txt # Alternative vi bindings for Neo users. # include = neo_command_keys.txt # Override the vi movement keys with a non-command. # include = no_vi_command_keys.txt # Turn the shift-vi keys into safe move, instead of run. # include = safe_move_shift.txt # github.com/refracta/dcss-webtiles-extension-module/blob/main/modules/sound-support/README.md sound_on = true one_SDL_sound_channel = true sound_volume = 0.07 sound_fade_time = 2.8 sound_pack += https://osp.nemelex.cards/build/latest.zip:["init.txt"] sound_pack += https://sound-packs.nemelex.cards/Autofire/BindTheEarth/BindTheEarth.zip # github.com/brianfaires/crawl-rc/blob/main/buehler.rc # config, constants, util, color-inscribe, fully-rest, inscribe-stats, misc-alerts, remind-id, pa-armour, pa-misc, pa-weapons ################################### Begin lua/config.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_lua_config_file then return end loaded_lua_config_file = true CONFIG = { } -- Inscribe stats CONFIG.inscribe_weapons = true CONFIG.inscribe_armour = true ---- Pickup/Alert system CONFIG.pickup_armour = true CONFIG.pickup_weapons = true CONFIG.pickup_staves = true CONFIG.alert_system_enabled = true CONFIG.alert_armour = true CONFIG.alert_weapons = false CONFIG.alert_orbs = false CONFIG.alert_talismans = false CONFIG.alert_staff_resists = true CONFIG.alert_one_time_items = true one_time_alerts = { "partisan", "demon trident", "trishula", "crystal plate armour", "gold dragon scales", "pearl dragon scales", "storm dragon scales", "shadow dragon scales", "wand of digging", "buckler", "kite shield", "tower shield" } -- one_time_alerts (do not remove this comment) } ############################### End lua/config.lua ############################### ########################################################################################## ################################### Begin lua/constants.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { -- Lists of things that may need to be updated as crawl changes if loaded_lua_constants_file then return end local loaded_lua_constants_file = true all_undead_races = { "Demonspawn", "Mummy", "Poltergeist", "Revenant", } -- all_undead_races (do not remove this comment) all_missiles = { " stone", "poisoned dart", "atropa", "curare", "datura", "boomerang", "javelin", "large rock", "throwing net", } -- all_missiles (do not remove this comment) all_misc = { "box of beasts", "condenser vane", "figurine of a ziggurat", "Gell's gravitambourine", "horn of Geryon", "lightning rod", "phantom mirror", "phial of floods", "sack of spiders", "tin of tremorstones", } -- all_misc (do not remove this comment) staff_schools = { fire = "Fire Magic", cold = "Ice Magic", earth = "Earth Magic", air = "Air Magic", poison = "Poison Magic", death = "Necromancy", conjuration = "Conjurations", } -- staff_schools (do not remove this comment) gods_with_allies = { "Beogh", "Hepliaklqana", "Jiyva", "Yredelemnul", } -- gods_with_allies (do not remove this comment) all_weap_schools = { "axes", "maces & flails", "polearms", "long blades", "short blades", "staves", "unarmed combat", "ranged weapons", } -- all_weap_schools (do not remove this comment) all_portal_names = { "Bailey", "Bazaar", "Desolation", "Gauntlet", "Ice Cave", "Ossuary", "Sewer", "Trove", "Volcano", "Wizlab", "Ziggurat", } -- all_portal_names (do not remove this comment) all_training_skills = { "Air Magic", "Alchemy", "Armour", "Axes", "Conjurations", "Dodging", "Earth Magic", "Evocations", "Fighting", "Fire Magic", "Forgecraft", "Hexes", "Ice Magic", "Invocations", "Long Blades", "Maces & Flails", "Necromancy", "Polearms", "Ranged Weapons", "Shapeshifting", "Shields", "Short Blades", "Spellcasting", "Staves", "Stealth", "Summonings", "Translocations", "Unarmed Combat", "Throwing", } -- all_training_skills (do not remove this comment) -- Color map to single digit tags (less text than explicit) -- 0:black, 1:blue, 2:green, 3:cyan, 4:red, 5:magenta, 6:brown, -- 7:lightgrey, 8:darkgrey, 9:lightblue, 10:lightgreen, 11:lightcyan, -- 12:lightred, 13:lightmagenta, 14:yellow, 15:white COLORS = { blue = 1, green = 2, cyan = 3, red = 4, magenta = 5, brown = 6, lightgrey = 7, darkgrey = 8, lightblue = 9, lightgreen = 10, lightcyan = 11, lightred = 12, lightmagenta = 13, yellow = 14, white = "w", black = 0, } -- COLORS (do not remove this comment) RACE_SIZE = { VERY_SMALL = -2, SMALL = -1, NORMAL = 0, LARGE = 1, VERY_LARGE = 2 } function get_size_penalty() local race = you.race() if race == "Spriggan" then return RACE_SIZE.VERY_SMALL elseif race == "Kobold" then return RACE_SIZE.SMALL elseif race == "Formicid" or race == "Armataur" or race == "Naga" then return RACE_SIZE.LARGE elseif race == "Oni" or race == "Troll" then return RACE_SIZE.VERY_LARGE else return RACE_SIZE.NORMAL end end } ############################### End lua/constants.lua ############################### ########################################################################################## ################################### Begin lua/util.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_util_lua then return end local loaded_util_lua = true ---- Text Formatting ---- function colorize_itext(color, str) return string.format("<%s>%s", color, str, color) end -- Removes tags from text, and optionally escapes special characters -- function cleanup_text(text, escape_chars) local keep_going = true while keep_going do local opening = text:find("<") local closing = text:find(">") if opening and closing and opening < closing then local new_text = "" if opening > 1 then new_text = text:sub(1, opening-1) end if closing < #text then new_text = new_text..text:sub(closing+1, #text) end text = new_text else keep_going = false end end text = text:gsub("\n", "") if escape_chars then local special_characters = "([%^%$%(%)%%%.%[%]%*%+%-%?])" text = text:gsub(special_characters, "%%%1") end return text end --- Key codes & modifiers --- KEYS = { LF = string.char(10), CR = string.char(13) } function control_key(c) return string.char(string.byte(c) - string.byte('a') + 1) end --- Code readability --- function if_el(cond, a, b) if cond then return a else return b end end --- Helper --- function you_have_allies() return you.skill("Summonings") + you.skill("Necromancy") > 0 or util.contains(gods_with_allies, you.god()) end function you_are_undead() return util.contains(all_undead_races, you.race()) end function you_are_pois_immune() return you.res_poison() >= 3 end function is_body_armour(it) return it and it.subtype() == "body" end function is_armour(it) return it and it.class(true) == "armour" end function is_shield(it) return it and it.subtype() == "shield" end function is_weapon(it) return it and (it.delay ~= nil) end function is_staff(it) return it and it.class(true) == "magical staff" end function is_ring(it) return it and it.name("base") == "ring" end function is_amulet(it) return it and it.name("base") == "amulet" end function is_orb(it) return it and it.name("base"):find("orb of ") end function is_talisman(it) return it and it.name("base"):find("talisman") end function get_mut(mutation, include_temp) return you.get_base_mutation_level(mutation, include_temp) end function have_shield() return items.equipped_at("shield") ~= nil end function get_body_armour() return items.equipped_at("armour") end } ############################### End lua/util.lua ############################### ########################################################################################## ################################### Begin lua/color-inscribe.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { -- Colorize inscriptions -- -- Long inscriptions can break certain menus. In-game inscriptions seem limited to 78 chars. -- If INSCRIPTION_MAX_LENGTH is exceeded, ending tags are removed. A final tag is added to resume writing in lightgrey. local INSCRIPTION_MAX_LENGTH = 70 local function colorize_text(text, s, tag) local idx = text:find(s) if not idx then return text end if idx > 1 then -- Avoid '!r' or an existing color tag local prev = text:sub(idx-1, idx-1) if prev == "!" or prev == ">" then return text end end local retval = text:gsub("("..s..")", "<"..tag..">%1") return retval end local multi_plus = "%++" local multi_minus = "%-+" local pos_num = "%+%d+%.?%d*" local neg_num = "%-%d+%.?%d*" local colorize_tags = { { "rF"..multi_plus, COLORS.lightred }, { "rC"..multi_plus, COLORS.lightblue }, { "rN"..multi_plus, COLORS.lightmagenta }, { "rF"..multi_minus, COLORS.red }, { "rC"..multi_minus, COLORS.blue }, { "rN"..multi_minus, COLORS.magenta }, { "rPois", COLORS.green }, { "rElec", COLORS.lightcyan }, { "rCorr", COLORS.yellow }, { "rMut", COLORS.brown }, { "Slay"..pos_num, COLORS.white}, { "Str"..pos_num, COLORS.white }, { "Dex"..pos_num, COLORS.white }, { "Int"..pos_num, COLORS.white }, { "AC"..pos_num, COLORS.white }, { "EV"..pos_num, COLORS.white }, { "SH"..pos_num, COLORS.white }, { "HP"..pos_num, COLORS.white }, { "MP"..pos_num, COLORS.white }, { "Slay"..neg_num, COLORS.darkgrey }, { "Str"..neg_num, COLORS.darkgrey }, { "Dex"..neg_num, COLORS.darkgrey }, { "Int"..neg_num, COLORS.darkgrey }, { "AC"..neg_num, COLORS.darkgrey }, { "EV"..neg_num, COLORS.darkgrey }, { "SH"..neg_num, COLORS.darkgrey }, { "HP"..neg_num, COLORS.darkgrey }, { "MP"..neg_num, COLORS.darkgrey }, } --colorize_tags (do not remove this comment) ------------------- Hooks ------------------- function c_assign_invletter_color_inscribe(it) local text = it.inscription for _, tag in ipairs(colorize_tags) do text = colorize_text(text, tag[1], tag[2]) end if text:len() > INSCRIPTION_MAX_LENGTH then text = text:gsub("<.*>", "").."<7>" end it.inscribe(text, false) end -- To colorize more, need a way to: -- intercept messages before they're displayed -- insert tags that affect menus -- colorize artefact text -- function c_message_color_inscribe(text, _) -- local orig_text = text -- text = colorize_text(text) -- if text == orig_text then return end -- local cleaned = cleanup_text(text) -- if cleaned:sub(2, 4) == " - " then -- text = " "..text -- end -- crawl.mpr(text) -- end } ############################### End lua/color-inscribe.lua ############################### ########################################################################################## ################################### Begin lua/fully-rest.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { ----- Fully rest off effects ----- local status_to_wait_off = { "berserk", "short of breath", "corroded", "vulnerable", "confused", "marked", "tree%-form", "sluggish" } local waiting_for_recovery = false local explore_after_recovery = false crawl.setopt("runrest_ignore_message += recovery:.*") crawl.setopt("runrest_ignore_message += duration:.*") local function fully_recovered() -- Confirm sure HP and MP are full local hp, mhp = you.hp() if hp ~= mhp then return false end local mp, mmp = you.mp() if mp ~= mmp then return false end -- Statuses that will always rest off local status = you.status() for s in iter.invent_iterator:new(status_to_wait_off) do if status:find(s) then return false end end -- If stat drain, don't wait for slow if status:find("slowed") then return you.strength() <= 0 or you.dexterity() <= 0 or you.intelligence() <= 0 end return true end -- Attach full recovery to auto-explore function macro_explore_full_recovery() if fully_recovered() then crawl.do_commands({"CMD_EXPLORE"}) else explore_after_recovery = true crawl.do_commands({"CMD_REST"}) end end crawl.setopt("macros += M o ===macro_explore_full_recovery") function ch_stop_running_full_recovery(kind) if kind == "run" and not fully_recovered() then waiting_for_recovery = true crawl.setopt("message_colour += mute:You start waiting.") end end function c_message_fully_recover(text, _) if text:find("You start waiting.") or text:find("You start resting.") then if not fully_recovered() then waiting_for_recovery = true crawl.setopt("message_colour += mute:You start waiting.") end elseif waiting_for_recovery and channel == "timed_portal" then you.stop_activity() waiting_for_recovery = false crawl.setopt("message_colour -= mute:You start waiting.") explore_after_recovery = false end end function ready_fully_recover() if waiting_for_recovery then if fully_recovered() then you.stop_activity() crawl.setopt("message_colour -= mute:You start waiting.") waiting_for_recovery = false crawl.mpr("Fully recovered.") if explore_after_recovery then crawl.sendkeys("o") explore_after_recovery = false end elseif not you.feel_safe() then you.stop_activity() waiting_for_recovery = false explore_after_recovery = false else crawl.do_commands({"CMD_SAFE_WAIT"}) end else explore_after_recovery = false end end } ############################### End lua/fully-rest.lua ############################### ########################################################################################## ################################### Begin lua/inscribe-stats.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { ----- Inscribe stats on items ----- local function inscribe_armour_stats(it) -- Will add to the beginning of inscriptions, or replace it's own values -- This gsub's stats individually to avoid overwriting tags -- NUM_PATTERN searches for numbers w/ decimal, to avoid artefact inscriptions local NUM_PATTERN = "[%+%-%=]%d+%.%d*" local abbr = if_el(is_shield(it), "SH", "AC") local primary, ev = get_armour_info_strings(it) local new_insc if it.inscription:find(abbr..NUM_PATTERN) then new_insc = it.inscription:gsub(abbr..NUM_PATTERN, primary) if ev and ev ~= "" then new_insc = new_insc:gsub("EV"..NUM_PATTERN, ev) end else new_insc = primary if ev and ev ~= "" then new_insc = new_insc..", "..ev end if it.inscription and it.inscription ~= "" then new_insc = new_insc.." "..it.inscription end end it.inscribe(new_insc, false) end local function inscribe_weapon_stats(it) local new_inscr = get_weapon_info(it) local idx = it.inscription:find("DPS:") if idx then if idx + #new_inscr <= #it.inscription then new_inscr = new_inscr..it.inscription:sub(idx + #new_inscr, #it.inscription) end if idx > 1 then new_inscr = it.inscription:sub(1, idx-1)..new_inscr end end it.inscribe(new_inscr, false) return new_inscr end local skipped_first_redraw = false ------------------ Hook ------------------ function ready_inscribe_stats() for it in iter.invent_iterator:new(items.inventory()) do if is_weapon(it) or is_staff(it) then if CONFIG.inscribe_weapons then inscribe_weapon_stats(it) end elseif is_armour(it) then if CONFIG.inscribe_armour then inscribe_armour_stats(it) end end end -- This redraw can causes crashes if called during an autopickup. -- Be sure not to hook any of this to c_message, or anything that can trigger during an autopickup if skipped_first_redraw then crawl.redraw_screen() else skipped_first_redraw = true end end } ############################### End lua/inscribe-stats.lua ############################### ########################################################################################## ################################### Begin lua/misc-alerts.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_misc_alerts then return end loaded_misc_alerts = true ------ Max piety w/ amulet of faith reminder ---- if not alerted_max_piety or you.turns() == 0 then alerted_max_piety = 0 end local function persist_alerted_max_piety() return "alerted_max_piety = "..alerted_max_piety..KEYS.LF end table.insert(chk_lua_save, persist_alerted_max_piety) local function alert_remove_faith() if alerted_max_piety == 0 and you.piety_rank() == 6 then local am = items.equipped_at("amulet") if am and am.subtype() == "amulet of faith" and not am.artefact then if you.god() == "Uskayaw" or you.god() == "Kikubaaqudgha" then return end crawl.mpr("6 star piety! Maybe ditch that amulet soon.") crawl.more() alerted_max_piety = 1 end end end ------------------ Hook ------------------ function ready_misc_alerts() if CONFIG.alert_remove_faith then alert_remove_faith() end end } ############################### End lua/misc-alerts.lua ############################### ########################################################################################## ################################### Begin lua/remind-id.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { ---- Remind to identify items when you have scroll of ID + unidentified item ---- local function remind_unidentified_items() for it in iter.invent_iterator:new(items.inventory()) do if not it.is_identified then for s in iter.invent_iterator:new(items.inventory()) do if s and s.name("qual"):find("scroll of identify") then crawl.mpr("----You have something to identify.----", "plain") break end end return end end end crawl.setopt("runrest_stop_message += You have something to identify") ---- Track if found ID yet ---- if not found_scroll_of_id or you.turns() == 0 then found_scroll_of_id = 0 end local function persist_found_scroll_of_id() return "found_scroll_of_id = "..found_scroll_of_id..KEYS.LF end table.insert(chk_lua_save, persist_found_scroll_of_id) ------------------- Hooks ------------------- function c_message_remind_identify(text, channel) if channel ~= "plain" then return end if text:find(" of identify") then found_scroll_of_id = 1 if not text:find("drop") and not text:find("read") then remind_unidentified_items() end elseif found_scroll_of_id == 0 then local idx = text:find(" %- ") if idx then local slot = text:sub(idx - 1, idx - 1) local it = items.inslot(items.letter_to_index(slot)) if it.class(true) == "scroll" and it.quantity >= CONFIG.stop_on_scrolls_count or it.class(true) == "potion" and it.quantity >= CONFIG.stop_on_pots_count then you.stop_activity() end end end end function c_assign_invletter_remind_identify(it) if not it.is_identified or it.name("qual"):find("scroll of identify") then remind_unidentified_items() end end } ############################### End lua/remind-id.lua ############################### ########################################################################################## ################################### Begin lua/pickup-alert/pa-armour.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_pa_armour then return end loaded_pa_armour = true ----------------------------------- Begin lua/pickup-alert/pa-util.lua ----------------------------------- --------------- https://github.com/brianfaires/crawl-rc/ --------------- if loaded_pa_util then return end loaded_pa_util = true function pa_show_alert_msg(alert_text, item_name) crawl.mpr("----"..alert_text..""..item_name.."----") you.stop_activity() end --- Custom def of ego/branded --- function has_ego(it) if it.class(true) == "weapon" then return it.branded or it.artefact end if it.artefact or it.branded then return true end local basename = it.name("base") if basename:find("troll leather") then return true end if basename:find("dragon scales") and not basename:find("steam") then return true end return false end function get_ego(it) if it.artefact then return "arte" end local basename = it.name("base") if basename:find("troll leather") then return "Regen+" end if basename:find("dragon scales") and not basename:find("steam") then return basename end return it.ego() end --------- Armour (Shadowing crawl calcs) --------- function get_shield_penalty(sh) local pen = 2/5 * sh.encumbrance * sh.encumbrance / (20 + 6 * get_size_penalty()) * (27 - you.skill("Shields")) / 27 -- Round to 2 decimals, which mimics scale==100 return math.floor(100 * pen) / 100 end function get_armour_ac(it) local it_plus = if_el(it.plus, it.plus, 0) if it.artefact and it.is_identified then local art_ac = it.artprops["AC"] if art_ac then it_plus = it_plus + art_ac end end if it.artefact and it.is_identified then local art_ac = it.artprops["AC"] if art_ac then it_plus = it_plus + art_ac end end local deformed = get_mut("deformed body", true) > 0 local pseudopods = get_mut("pseudopods", true) > 0 local ac = it.ac * (you.skill("Armour") / 22 + 1) + it_plus if pseudopods or (deformed and is_body_armour(it)) then ac = ac - it.ac / 2 end return ac end function get_aevp(encumb, str) return 2 * encumb * encumb * (45 - you.skill("Armour")) / (5 * (str + 3) * 45) end function get_armour_ev(it) -- This function computes the armour-based component to standard EV (not paralysed, etc) -- Factors in stat changes from this armour and removing current one local str = you.strength() local dex = you.dexterity() local art_ev = 0 -- Adjust str/dex/EV for artefact stat changes local worn = items.equipped_at("armour") if worn and worn.artefact then if worn.artprops["Str"] then str = str - worn.artprops["Str"] end if worn.artprops["Dex"] then dex = dex - worn.artprops["Dex"] end if worn.artprops["EV"] then art_ev = art_ev - worn.artprops["EV"] end end local no_art_dex = dex if it.artefact then if it.artprops["Str"] then str = str + it.artprops["Str"] end if it.artprops["Dex"] then dex = dex + it.artprops["Dex"] end if it.artprops["EV"] then art_ev = art_ev + it.artprops["EV"] end end if str <= 0 then str = 1 end local size_factor = -2 * get_size_penalty() local dodge_bonus = 8*(10 + you.skill("Dodging") * dex) / (20 - size_factor) / 10 local normalize_zero_to_zero = 8*(10 + you.skill("Dodging") * no_art_dex) / (20 - size_factor) / 10 local encumb = it.encumbrance - 2 * get_mut("sturdy frame", true) if encumb < 0 then encumb = 0 end local armour_penalty = encumb - 3 if armour_penalty > 0 then if armour_penalty >= str then dodge_bonus = dodge_bonus * (str / (armour_penalty * 2)) else dodge_bonus = dodge_bonus * (1 - armour_penalty / (str * 2)) end end local aevp = get_aevp(encumb, str) return dodge_bonus - aevp + art_ev - normalize_zero_to_zero end function get_shield_sh(it) local dex = you.dexterity() if it.artefact and it.is_identified then local art_dex = it.artprops["Dex"] if art_dex then dex = dex + art_dex end end local cur = items.equipped_at("shield") if cur and cur.artefact and cur.slot ~= it.slot then local art_dex = cur.artprops["Dex"] if art_dex then dex = dex - art_dex end end local it_plus = if_el(it.plus, it.plus, 0) local skill = you.skill("Shields") local basename = it.name("base") local sh_size if basename:find("tower shield") then sh_size = 0 elseif basename:find("kite shield") then sh_size = -1 else sh_size = -2 end local base_sh = it.ac * 2 + sh_size*get_size_penalty() local shield = base_sh * (50 + skill*5/2) shield = shield + 200*it_plus shield = shield + if_el(skill < 3, 76*skill, 38*(3+skill)) shield = shield + dex*38*(base_sh+13)/26 return (shield + 50) / 200 end --------- Weapons (Shadowing crawl calcs) --------- function get_hands(it) if you.race() ~= "Formicid" then return it.hands end local st, _ = it.subtype() if st == "giant club" or st == "giant spiked club" then return 2 end return 1 end function get_weap_min_delay(it) -- This is an abbreviated version of the actual calculation. -- Intended only to be used to prevent skill from reducing too far in get_weap_delay() local basename = it.name("base") local adj_base_delay = it.delay / 2 if it.ego() == "heavy" then adj_base_delay = 1.5 * adj_base_delay end local min_delay = math.floor(adj_base_delay) if it.weap_skill == "Short Blades" and min_delay > 5 then min_delay = 5 end if min_delay > 7 then min_delay = 7 end if basename:find("longbow") then min_delay = 6 elseif (basename:find("crossbow") or basename:find("arbalest")) and min_delay < 10 then min_delay = 10 end return min_delay end function get_weap_delay(it, ignore_brands) local delay = it.delay - get_skill(it.weap_skill)/2 local min_delay = get_weap_min_delay(it) if delay < min_delay then delay = min_delay end if not ignore_brands then if it.ego() == "speed" then delay = delay * 2 / 3 elseif it.ego() == "heavy" then delay = delay * 1.5 end end if delay < 3 then delay = 3 end local sh = items.equipped_at("shield") if sh then delay = delay + get_shield_penalty(sh) end if it.is_ranged then local body = items.equipped_at("armour") if body then local str = you.strength() if it.artefact then if it.artprops["Str"] then str = str + it.artprops["Str"] end end local cur = items.equipped_at("weapon") if cur and cur ~= it and cur.artefact then if cur.artprops["Str"] then str = str - cur.artprops["Str"] end end delay = delay + get_aevp(body.encumbrance, str) end end return delay / 10 end --------- Other damage calcs --------- -- Count all slay bonuses from weapons/armour/jewellery function get_slay_bonuses() local sum = 0 -- Slots can go as high as 18 afaict for i = 0,20 do local it = items.equipped_at(i) if it then if is_ring(it) then if it.artefact then local name = it.name() local idx = name:find("Slay") if idx then local slay = tonumber(name:sub(idx+5, idx+5)) if slay == 1 then local next_digit = tonumber(name:sub(idx+6, idx+6)) if next_digit then slay = 10 + next_digit end end if name:sub(idx+4, idx+4) == "+" then sum = sum + slay else sum = sum - slay end end elseif it.ego(true) == "Slay" then sum = sum + it.plus end elseif it.artefact and (is_armour(it) or is_amulet(it)) then local slay = it.artprops["Slay"] if slay then sum = sum + slay end end end end if you.race() == "Demonspawn" then sum = sum + 3 * get_mut("augmentation", true) sum = sum + get_mut("sharp scales", true) end return sum end function get_staff_school(it) for k,v in pairs(staff_schools) do if it.name("base") == "staff of "..k then return v end end end function get_staff_bonus_dmg(it, no_brand_dmg) if no_brand_dmg and it.name("base") ~= "staff of earth" and it.name("base") ~= "staff of conjuration" then return 0 end local evo_skill = you.skill("Evocations") local school = get_staff_school(it) if not school then return 0 end local spell_skill = get_skill(school) local chance = (evo_skill + spell_skill/2) / 15 if chance > 1 then chance = 1 end -- 0.625 is an acceptable approximation -- Earth magic does more, but reduced by armour. Poison/draining bonus effects are ignored. local avg_dmg = 0.625 * (evo_skill/2 + spell_skill) return avg_dmg*chance end --------- get_weap_dmg() --------- function get_weap_dmg(it, no_brand_dmg, no_weight_all_brands) -- Returns an adjusted weapon damage = damage * speed -- Includes stat/slay changes between weapon and the one currently wielded -- Aux attacks not included local it_plus = if_el(it.plus, it.plus, 0) -- Adjust str/dex/slay from artefacts local str = you.strength() local dex = you.dexterity() -- Adjust str/dex/EV for artefact stat changes if not it.equipped then local wielded = items.equipped_at("weapon") if wielded and wielded.artefact then if wielded.artprops["Str"] then str = str - wielded.artprops["Str"] end if wielded.artprops["Dex"] then dex = dex - wielded.artprops["Dex"] end if wielded.artprops["Slay"] then it_plus = it_plus - wielded.artprops["Slay"] end end if it.artefact and it.is_identified then if it.artprops["Str"] then str = str + it.artprops["Str"] end if it.artprops["Dex"] then dex = dex + it.artprops["Dex"] end if it.artprops["Slay"] then it_plus = it_plus + it.artprops["Slay"] end end end local stat if it.is_ranged or it.weap_skill:find("Blades") then stat = dex else stat = str end local stat_mod = 0.75 + 0.025 * stat local skill_mod = (1 + get_skill(it.weap_skill)/25/2) * (1 + you.skill("Fighting")/30/2) it_plus = it_plus + get_slay_bonuses() local pre_brand_dmg_no_plus = it.damage * stat_mod * skill_mod local pre_brand_dmg = pre_brand_dmg_no_plus + it_plus if is_staff(it) then return (pre_brand_dmg + get_staff_bonus_dmg(it, no_brand_dmg)) end local ego = it.ego() if not ego then return pre_brand_dmg end if not no_brand_dmg then if ego == "spectralizing" then return 2 * pre_brand_dmg end if ego == "heavy" then return (1.8 * pre_brand_dmg_no_plus + it_plus) end if ego == "flaming" or ego == "freezing" then return 1.25 * pre_brand_dmg end if ego == "draining" then return (1.25 * pre_brand_dmg + 2) end if ego == "electrocution" then return (pre_brand_dmg + 3.5) end -- Ballparking venom as 5 dmg since it totally breaks the paradigm if ego == "venom" then return (pre_brand_dmg + 5) end if ego == "pain" then return (pre_brand_dmg + you.skill("Necromancy")/2) end -- Distortion does 5.025 extra dmg, + 5% chance to banish if ego == "distortion" then return (pre_brand_dmg + 6) end -- Weighted average of all the easily computed brands was ~ 1.17*dmg + 2.13 if ego == "chaos" then return (1.25 * pre_brand_dmg + 2) end if not no_weight_all_brands then if ego == "protection" then return 1.15 * pre_brand_dmg end if ego == "vampirism" then return 1.25 * pre_brand_dmg end if ego == "holy wrath" then return 1.15 * pre_brand_dmg end if ego == "antimagic" then return 1.1 * pre_brand_dmg end end end return pre_brand_dmg end function get_weap_dps(it, no_brand_dmg, no_weight_all_brands) return get_weap_dmg(it, no_brand_dmg, no_weight_all_brands) / get_weap_delay(it) end ---- Weapon info strings ---- function get_weapon_info(it) if not it.delay then return end local dmg = get_weap_dmg(it) local dmg_str = string.format("%.1f", dmg) if dmg < 10 then dmg_str = string.format("%.2f", dmg) end if dmg > 99.9 then dmg_str = ">100" end local delay = get_weap_delay(it) local delay_str = string.format("%.1f", delay) if delay < 1 then delay_str = string.format("%.2f", delay) delay_str = delay_str:sub(2, #delay_str) end local dps = get_weap_dps(it) local dps_str = string.format("%.1f", dps) if dps < 10 then dps_str = string.format("%.2f", dps) end if dps > 99.9 then dps_str = ">100" end local it_plus = if_el(it.plus, it.plus, 0) local acc = it.accuracy + it_plus if acc >= 0 then acc = "+"..acc end --This would be awesome if it didn't ruin the main UI --dps_str = "DPS="..dps_str.." " --return dps_str.."("..dmg_str.."/"..delay_str.."), Acc"..acc.."" dps_str = "DPS="..dps_str.." " return dps_str.."("..dmg_str.."/"..delay_str.."), Acc"..acc end local function format_stat(abbr, val, is_worn) local stat_str = string.format("%.1f", val) if is_worn then stat_str = "="..stat_str elseif val >= 0 then stat_str = "+"..stat_str end return abbr..stat_str end function get_armour_info_strings(it) if not is_armour(it) or is_orb(it) then return "", "" end local cur = items.equipped_at(it.equip_type) local cur_ac = 0 local cur_sh = 0 local cur_ev = 0 local is_worn = it.ininventory and cur and cur.slot == it.slot if cur and not is_worn then -- Only show deltas if not same item if is_shield(cur) then cur_sh = get_shield_sh(cur) cur_ev = get_shield_penalty(cur) else cur_ac = get_armour_ac(cur) cur_ev = get_armour_ev(cur) end end if is_shield(it) then local sh_str = format_stat("SH", get_shield_sh(it) - cur_sh, is_worn) local ev_str = format_stat("EV", get_shield_penalty(it) - cur_ev, is_worn) return sh_str, ev_str else local ac_str = format_stat("AC", get_armour_ac(it) - cur_ac, is_worn) if not is_body_armour(it) then return ac_str end local ev_str = format_stat("EV", get_armour_ev(it) - cur_ev, is_worn) return ac_str, ev_str end end function get_skill(skill) if not skill:find(",") then return you.skill(skill) end local skills = crawl.split(skill, ",") local sum = 0 local count = 0 for _, s in ipairs(skills) do sum = sum + you.skill(s) count = count + 1 end return sum/count end ------------------------------- End lua/pickup-alert/pa-util.lua ------------------------------- ------------------------------------------------------------------------------------------ ----------------------------------- Begin lua/pickup-alert/pa-data.lua ----------------------------------- --------------- https://github.com/brianfaires/crawl-rc/ --------------- if loaded_pa_data then return end loaded_pa_data = true ---------------------------- Begin persistent data ---------------------------- if not pa_all_level_alerts or you.turns() == 0 then pa_all_level_alerts = { } pa_items_picked = { } pa_items_alerted = { } pa_single_alert_items = { } for _,v in ipairs(one_time_alerts) do table.insert(pa_single_alert_items, v) end alerted_first_ranged_one_handed = 0 alerted_first_ranged_two_handed = 0 armour_high_score = 0 weapon_high_score = 0 unbranded_high_score = 0 polearm_high_score = 0 polearm_onehand_high_score = 0 end local function persist_table(table_name, table) local cmd_init = table_name.." = {" local cmd = cmd_init for v in iter.invent_iterator:new(table) do if cmd ~= cmd_init then cmd = cmd..", " end cmd = cmd.."\""..v.."\"" end return cmd .. "}" .. KEYS.LF end local function persist_var(var_name, var) return var_name .. " = " .. var .. KEYS.LF end table.insert(chk_lua_save, function() return persist_table("pa_all_level_alerts", pa_all_level_alerts) end) table.insert(chk_lua_save, function() return persist_table("pa_single_alert_items", pa_single_alert_items) end) table.insert(chk_lua_save, function() return persist_table("pa_items_picked", pa_items_picked) end) table.insert(chk_lua_save, function() return persist_table("pa_items_alerted", pa_items_alerted) end) table.insert(chk_lua_save, function() return persist_var("armour_high_score", armour_high_score) end) table.insert(chk_lua_save, function() return persist_var("alerted_first_ranged_one_handed", alerted_first_ranged_one_handed) end) table.insert(chk_lua_save, function() return persist_var("alerted_first_ranged_two_handed", alerted_first_ranged_two_handed) end) table.insert(chk_lua_save, function() return persist_var("polearm_high_score", polearm_high_score) end) table.insert(chk_lua_save, function() return persist_var("polearm_onehand_high_score", polearm_onehand_high_score) end) table.insert(chk_lua_save, function() return persist_var("unbranded_high_score", unbranded_high_score) end) table.insert(chk_lua_save, function() return persist_var("weapon_high_score", weapon_high_score) end) ---- Accessors into persistent data ---- function get_rare_item_index(it) local qualname = it.name("qual") for i,v in ipairs(pa_single_alert_items) do if v ~= "" and qualname:find(v) then return i end end return -1 end function remove_from_pa_single_alert_items(it) local idx = get_rare_item_index(it) if idx ~= -1 then util.remove(pa_single_alert_items, pa_single_alert_items[idx]) return true end return false end function pa_previously_picked(it) local name = it.name("qual") if not it.is_identified then name = "+0 " .. name end return util.contains(pa_items_picked, name) end function pa_previously_alerted(it) local name = it.name("qual") if not it.is_identified then name = "+0 " .. name end return util.contains(pa_items_alerted, name) end --- Multi store/remove data --- local function add_remove_item_and_less_enchanted(table_ref, it, remove_item) -- Add (or remove) an item name to a table, along with all less enchanted versions -- e.g. "+3 flail" will add: "+3 flail", "+2 flail", "+1 flail", "+0 flail" local name = it.name("qual") if not it.is_identified then name = "+0 " .. name end if util.contains(table_ref, name) ~= remove_item then return end if remove_item then util.remove(table_ref, name) else table.insert(table_ref, name) end if it.artefact then return end -- Do less enchanted items too local plus = tonumber(name:sub(2,2)) if not plus then return end if plus > 0 then if tonumber(name:sub(3,3)) then plus = 10 * plus + tonumber(name:sub(3,3)) end for i=plus,1,-1 do name = name:gsub("+"..i, "+"..(i-1)) if remove_item then util.remove(table_ref, name) else table.insert(table_ref, name) end end end end function insert_item_and_less_enchanted(table_ref, it) add_remove_item_and_less_enchanted(table_ref, it, false) end function remove_item_and_less_enchanted(table_ref, it) add_remove_item_and_less_enchanted(table_ref, it, true) end --- Set all single high scores --- function update_high_scores(it) local ret_val = nil if is_armour(it) then local ac = get_armour_ac(it) if ac > armour_high_score then armour_high_score = ac if not ret_val then ret_val = "Strongest armour" end end elseif is_weapon(it) then local it_plus = if_el(it.plus, it.plus, 0) local score = get_weap_dps(it) + (it.accuracy + it_plus) / 2 if score > weapon_high_score then weapon_high_score = score if not ret_val then ret_val = "Good weapon" end end local unbranded_score = get_weap_dps(it, false) + (it.accuracy + it_plus) / 2 if unbranded_score > unbranded_high_score then unbranded_high_score = score if not ret_val then ret_val = "High pure damage" end end if it.weap_skill == "Polearms" and you_have_allies() then if score > polearm_high_score then polearm_high_score = score if not have_shield() and not ret_val then ret_val = "Good polearm" end end if get_hands(it) == 1 and score > polearm_onehand_high_score then polearm_onehand_high_score = score if not ret_val then ret_val = "Good polearm" end end end end return ret_val end --- Startup code --- -- Starting items: Remove from pa_single_alert_items, and add to pa_items_picked if you.turns() == 0 then for inv in iter.invent_iterator:new(items.inventory()) do local idx = get_rare_item_index(inv) if idx ~= -1 then util.remove(pa_single_alert_items, pa_single_alert_items[idx]) end insert_item_and_less_enchanted(pa_items_picked, inv) end end ------------------------------- End lua/pickup-alert/pa-data.lua ------------------------------- ------------------------------------------------------------------------------------------ ----------------------------------- Begin lua/pickup-alert/pa-main.lua ----------------------------------- --------------- https://github.com/brianfaires/crawl-rc/ --------------- if loaded_pa_main then return end loaded_pa_main = true local pause_pickup_alert_sys = false local last_ready_item_alerts_turn = 0 function pa_alert_item(it, alert_type) local name = it.name("plain") local qualname = it.name("qual") if not (is_talisman(it) or it.is_identified) then name = "+0 " .. name qualname = "+0 " .. qualname end if not pa_previously_alerted(it) and not pa_previously_picked(it) then if is_weapon(it) or is_staff(it) then pa_show_alert_msg("Item alert, "..alert_type..": ", name.." "..get_weapon_info(it)) elseif is_body_armour(it) then local ac, ev = get_armour_info_strings(it) pa_show_alert_msg("Item alert, "..alert_type..": ", name.." "..ac..", "..ev) elseif is_armour(it) then pa_show_alert_msg("Item alert, "..alert_type..": ", name) else pa_show_alert_msg("Item alert, "..alert_type..": ", name) end insert_item_and_less_enchanted(pa_items_alerted, it) table.insert(pa_all_level_alerts, qualname) end -- Returns true to make other code more concise; indicates that we tried to alert this item return true end crawl.setopt("runrest_stop_message += Item alert, ") ------------------- Hooks ------------------- function c_assign_invletter_item_alerts(it) if is_weapon(it) or is_armour(it) then if not pa_previously_picked(it) then insert_item_and_less_enchanted(pa_items_picked, it) update_high_scores(it) remove_from_pa_single_alert_items(it) end end remove_item_and_less_enchanted(pa_items_alerted, it) util.remove(pa_all_level_alerts, it.name("qual")) end function c_message_item_alerts(text, _) if text:find("You start waiting.") or text:find("You start resting.") then pause_pickup_alert_sys = true elseif text:find("Done exploring.") or text:find("Partly explored") then local all_alerts = "" for v in iter.invent_iterator:new(pa_all_level_alerts) do if all_alerts == "" then all_alerts = v else all_alerts = all_alerts..", "..v end end pa_all_level_alerts = {} if all_alerts ~= "" then crawl.mpr("Recent alerts: "..all_alerts.."") end end end function ready_item_alerts() if you.turns() == last_ready_item_alerts_turn then return end last_ready_item_alerts_turn = you.turns() if not pause_pickup_alert_sys then generate_inv_weap_arrays() update_high_scores(items.equipped_at("armour")) else pause_pickup_alert_sys = false end end ---- Autopickup main ---- add_autopickup_func(function (it, _) if pause_pickup_alert_sys then return end -- Check for pickup local retVal = false if loaded_pa_armour and CONFIG.pickup_armour and is_armour(it) then retVal = pa_pickup_armour(it) elseif loaded_pa_weapons and CONFIG.pickup_weapons and is_weapon(it) then retVal = do_pa_weapon_pickup(it) elseif loaded_pa_misc and CONFIG.pickup_staves and is_staff(it) then retVal = pa_pickup_staff(it) end if retVal == true then remove_from_pa_single_alert_items(it) return true end if CONFIG.alert_system_enabled then -- Update inventory high scores before alerting; in case XP gained same turn item is dropped ready_item_alerts() -- Not picking up this item. Check for alerts if loaded_pa_misc then if CONFIG.alert_one_time_items then pa_alert_rare_item(it) end if is_staff(it) and CONFIG.alert_staff_resists then pa_alert_staff(it) elseif is_orb(it) and CONFIG.alert_orbs then pa_alert_orb(it) elseif is_talisman(it) and CONFIG.alert_talismans then pa_alert_talisman(it) end end if is_armour(it) and loaded_pa_armour and CONFIG.alert_armour then pa_alert_armour(it) elseif is_weapon(it) and loaded_pa_weapons and CONFIG.alert_weapons then do_pa_weapon_alerts(it) end end end) ------------------------------- End lua/pickup-alert/pa-main.lua ------------------------------- ------------------------------------------------------------------------------------------ -- (Resuming lua/pickup-alert/pa-armour.lua) -- -- If training armour in early/mid game, alert user to any armour that is the strongest found so far local function alert_armour_upgrades(it) if not is_body_armour(it) then return false end if you.skill("Armour") == 0 then return false end if you.xl() > 12 then return false end if (it.artefact or it.branded) and not it.is_identified then return false end if armour_high_score == 0 then local cur = get_body_armour() if not cur then return false end armour_high_score = get_armour_ac(cur) else local itAC = get_armour_ac(it) if itAC > armour_high_score then armour_high_score = itAC return pa_alert_item(it, "Strongest armour yet") end end return false end -- Equipment autopickup (by Medar, gammafunk, buehler, and various others) function pa_pickup_armour(it) if it.is_useless then return false end if is_body_armour(it) then local cur = get_body_armour() -- Exclusions if not cur then return false end if it.branded and not it.is_identified then return false end if it.encumbrance > cur.encumbrance then return false end -- Pick up AC upgrades, new egos that don't lose AC, and artefacts that don't lose 5+ AC local ac_delta = get_armour_ac(it) - get_armour_ac(cur) if it.artefact and ac_delta > -5 then return true end if cur.artefact then return false end if get_ego(it) == get_ego(cur) then return ac_delta > 0 or ac_delta == 0 and it.encumbrance < cur.encumbrance elseif has_ego(it) and not has_ego(cur) then return ac_delta >= 0 end elseif is_shield(it) then local cur = items.equipped_at("shield") -- Exclusions if not cur then return false end if not it.is_identified then return false end if cur.name("base") ~= it.name("base") then return false end -- Pick up SH upgrades, artefacts, and added egos if it.artefact then return true end if cur.artefact then return false end if cur.branded then if get_ego(cur) == get_ego(it) then return it.plus > cur.plus end return false end if it.branded then return true end return it.plus > cur.plus else if is_orb(it) then return false end -- Aux armour: Pickup artefacts, AC upgrades, and new egos local st, _ = it.subtype() -- Skip boots/gloves/helmet if wearing Lear's hauberk local body_arm = get_body_armour() if body_arm and body_arm.name("qual"):find("Lear's hauberk") and st ~= "cloak" then return false end -- No autopickup if mutation interference if st == "gloves" then -- Ignore demonic touch if you're wearing a shield if not items.equipped_at("shield") then if get_mut("demonic touch", true) >= 3 then return false end end -- Ignore claws if you're wielding a weapon if not items.equipped_at("weapon") then if get_mut("claws", true) > 0 then return false end end elseif st == "boots" then if get_mut("hooves", true) > 0 then return false end if get_mut("talons", true) > 0 then return false end elseif it.name("base"):find("helmet") then if get_mut("horns", true) > 0 then return false end if get_mut("beak", true) > 0 then return false end if get_mut("antennae", true) > 0 then return false end end if it.artefact then return true end local cur = items.equipped_at(st) if not cur then return true end if not it.is_identified then return false end if it.branded then if get_ego(it) ~= get_ego(cur) then return true end if get_armour_ac(it) > get_armour_ac(cur) then return true end else if cur.branded or cur.artefact then return false end if get_armour_ac(it) > get_armour_ac(cur) then return true end end end return false end ---- alert_armour_while_mutated() ---- -- Special cases where you have temporary or innate mutations that interfere with armour -- Alert when an ego item is usable but interferes with mutation, or unusable due to temp mutations local function alert_armour_while_mutated(it, type) local it_plus = if_el(it.plus, it.plus, 0) if type == "gloves" then local claws_lvl_innate = get_mut("claws", false) if claws_lvl_innate >= 3 then return end local touch_lvl_innate = get_mut("demonic touch", false) if touch_lvl_innate >= 3 then return end local claws_lvl = get_mut("claws", true) local touch_lvl = get_mut("demonic touch", true) if claws_lvl > 0 or touch_lvl >= 3 then if it.artefact or it.branded then pa_alert_item(it, "Branded gloves") end local cur_gloves = items.equipped_at("gloves") if not cur_gloves or it_plus > cur_gloves.plus then pa_alert_item(it, "Enchanted gloves") end end elseif type == "boots" then local hooves_lvl_innate = get_mut("hooves", false) if hooves_lvl_innate >= 3 then return end local talons_lvl_innate = get_mut("talons", false) if talons_lvl_innate >= 3 then return end local hooves_lvl = get_mut("hooves", true) local talons_lvl = get_mut("talons", true) if hooves_lvl + talons_lvl > 0 then if it.artefact or it.branded then pa_alert_item(it, "Branded boots") end local cur_boots = items.equipped_at("boots") if not cur_boots or it_plus > cur_boots.plus then pa_alert_item(it, "Enchanted boots") end end elseif type == "helmet" then local horns_lvl_innate = get_mut("horns", false) local antennae_lvl_innate = get_mut("antennae", false) if it.name("base"):find("helmet") then if horns_lvl_innate > 0 then return end if antennae_lvl_innate > 0 then return end if get_mut("beak", false) > 0 then return end else -- hat/crown/etc if horns_lvl_innate >= 3 then return end if antennae_lvl_innate >= 3 then return end end local horns_lvl = get_mut("horns", true) local antennae_lvl = get_mut("antennae", true) local beak_lvl = get_mut("beak", true) if horns_lvl + antennae_lvl + beak_lvl > 0 then if it.artefact or it.branded then pa_alert_item(it, "Branded headgear") end local cur_helmet = items.equipped_at("helmet") if not cur_helmet or it_plus > cur_helmet.plus then pa_alert_item(it, "Enchanted headgear") end end end end ---- alert_interesting_armour() ---- -- Alerts armour items that did trigger autopickup, but are worth consideration -- Includes: Artefacts, added or changed egos, and -- body armour AC/EV/Encumbrance changes, defined by following heuristics: -- Lighter: EV/AC >= { 0.6, 0.8, 1.2, 2 } for ego: {gain, diff, same, lose} -- Or: Gain/Diff ego while losing <=4AC -- Heavier: AC/EV >= { 0.4, 0.7, 0.8, 2 } for ego: {gain, diff, same, lose} -- Penalty == 0.75*encumb_change (or 0 if irrelevant) -- Adjusting the heuristic values up will mean fewer alerts, and down will alert more often. -- If you want a specific alert to occur more or less often, look for the line of code below with the alert text, -- Then modify the values in the same line of code. local function alert_interesting_armour(it) if it.artefact then return pa_alert_item(it, "Artefact armour") end if is_body_armour(it) then local cur = get_body_armour() if not cur then return false end if it.encumbrance == cur.encumbrance then if has_ego(it) then if not has_ego(cur) then return pa_alert_item(it, "Gain ego") end if get_ego(it) ~= get_ego(cur) then return pa_alert_item(it, "Diff ego") end end --if get_armour_ac(it) > get_armour_ac(cur) then return pa_alert_item(it, "Stronger armour") end elseif it.encumbrance < cur.encumbrance then -- Lighter armour local ev_gain = get_armour_ev(it) - get_armour_ev(cur) local ac_lost = get_armour_ac(cur) - get_armour_ac(it) if has_ego(it) then if not cur.artefact and not has_ego(cur) then if ev_gain/ac_lost >= 0.6 or ac_lost <= 4 then return pa_alert_item(it, "Gain ego (Lighter armour)") end elseif get_ego(it) ~= get_ego(cur) then if ev_gain/ac_lost >= 0.8 or ac_lost <= 4 then return pa_alert_item(it, "Diff ego (Lighter armour)") end else if ev_gain/ac_lost >= 1.2 then return pa_alert_item(it, "Lighter armour (Same ego)") end end else if cur.artefact or has_ego(cur) then if ev_gain/ac_lost >= 2 and ev_gain >= 3 then return pa_alert_item(it, "Lighter armour (Lost ego)") end else -- Neither has ego if ev_gain/ac_lost >= 1.2 then return pa_alert_item(it, "Lighter armour") end end end else -- Heavier armour local ac_gain = get_armour_ac(it) - get_armour_ac(cur) local ev_lost = get_armour_ev(cur) - get_armour_ev(it) local encumb_penalty = 0 if you.skill("Spellcasting") + you.skill("Ranged Weapons") > 1 then encumb_penalty = (it.encumbrance - cur.encumbrance)*0.75 end local total_loss = ev_lost + encumb_penalty if has_ego(it) then if not cur.artefact and not has_ego(cur) then if ac_gain/total_loss >= 0.4 or total_loss <= 6 then return pa_alert_item(it, "Gain ego (Heavier armour)") end elseif get_ego(it) ~= get_ego(cur) then if ac_gain/total_loss >= 0.7 or total_loss <= 6 then return pa_alert_item(it, "Diff ego (Heavier armour)") end else if ac_gain/total_loss >= 0.8 then return pa_alert_item(it, "Heavier armour (Same ego)") end end else if cur.artefact or has_ego(cur) then if ac_gain/total_loss >= 2 and ac_gain >= 3 then return pa_alert_item(it, "Heavier armour (Lost ego)") end else -- Neither has ego if ac_gain/total_loss >= 0.8 then return pa_alert_item(it, "Heavier armour") end end end end elseif is_shield(it) then --if it.is_useless then return end local cur = items.equipped_at("shield") if not cur then return false end if it.branded and it.ego() ~= cur.ego() then return pa_alert_item(it, "New ego") end else -- Aux armour local st, _ = it.subtype() local cur = items.equipped_at(st) if not cur then return elseif get_armour_ac(it) > get_armour_ac(cur) then pa_alert_item(it, "Stronger armour") else alert_armour_while_mutated(it, st) end end end function pa_alert_armour(it) if it.is_useless then return end alert_armour_upgrades(it) if it.is_identified or not has_ego(it) then alert_interesting_armour(it) end end } ############################### End lua/pickup-alert/pa-armour.lua ############################### ########################################################################################## ################################### Begin lua/pickup-alert/pa-misc.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_pa_misc then return end loaded_pa_misc = true ---- Alert rare items ---- function pa_alert_rare_item(it) local index = get_rare_item_index(it) if index == -1 then return end local do_alert = true -- Don't alert if already wearing a larger shield if pa_single_alert_items[index] == "buckler" then local sh = items.equipped_at("shield") if sh and sh.name("base") ~= "orb" then do_alert = false end elseif pa_single_alert_items[index] == "kite shield" then local sh = items.equipped_at("shield") if sh and sh.name("base"):find("tower shield") then do_alert = false end end if do_alert then pa_show_alert_msg("It's your first ", pa_single_alert_items[index].."!") crawl.more() end remove_from_pa_single_alert_items(it) end ---- Alert orbs ---- function pa_alert_orb(it) if it.is_identified and not have_shield() then pa_alert_item(it, "New orb") end end ---- Alert talismans ---- function pa_alert_talisman(it) if it.is_identified then pa_alert_item(it, "New talisman") end end ---- Alert for needed resists ---- function pa_alert_staff(it) if not it.is_identified then return false end local needRes = false local basename = it.name("base") if basename == "staff of fire" then needRes = you.res_fire() == 0 elseif basename == "staff of cold" then needRes = you.res_cold() == 0 elseif basename == "staff of air" then needRes = you.res_shock() == 0 elseif basename == "staff of poison" then needRes = you.res_poison() == 0 elseif basename == "staff of death" then needRes = you.res_draining() == 0 end if needRes then pa_alert_item(it, "Staff resistance") end end ---- Smart staff pickup ---- function pa_pickup_staff(it) if it.is_useless or not it.is_identified then return false end local school = get_staff_school(it) if get_skill(school) == 0 then return false end -- Check for previously picked staves for v in iter.invent_iterator:new(pa_items_picked) do if v:find(it.name("base")) then return false end end return true end } ############################### End lua/pickup-alert/pa-misc.lua ############################### ########################################################################################## ################################### Begin lua/pickup-alert/pa-weapons.lua ################################### ############### https://github.com/brianfaires/crawl-rc/ ############### { if loaded_pa_weapons then return end loaded_pa_weapons = true ---- Begin inv arrays ---- -- Use these arrays to compare potential upgrades against entire inventory -- But only update these arrays once per turn, in ready() local inv_weap_data = {} local function make_weapon_struct(it) local weap_data = {} weap_data.dps = get_weap_dps(it) weap_data.acc = it.accuracy + it.plus weap_data.ego = get_ego(it) weap_data.branded = has_ego(it) weap_data.basename = it.name("base") weap_data.subtype = it.subtype() weap_data.is_ranged = it.is_ranged weap_data.hands = get_hands(it) weap_data.artefact = it.artefact weap_data.plus = it.plus weap_data.weap_skill = it.weap_skill weap_data.skill_lvl = get_skill(it.weap_skill) --weap_data.it = it return weap_data end -- High scores for melee/ranged, 1/2-handed, branded/unbranded -- (Don't put these closing curly braces on a line by themself) local top_school = "unarmed combat" local egos = { } local inv_max_dmg = { melee_1 = 0, melee_1b = 0, melee_2 = 0, melee_2b = 0, ranged_1 = 0, ranged_1b = 0, ranged_2 = 0, ranged_2b = 0, melee_only = 0 } -- inv_max_dmg (do not remove this comment) local inv_max_dmg_acc = { melee_1 = 0, melee_1b = 0, melee_2 = 0, melee_2b = 0, ranged_1 = 0, ranged_1b = 0, ranged_2 = 0, ranged_2b = 0, melee_only = 0 } -- inv_max_dmg_acc (do not remove this comment) local function set_top_school() local max = 0 for v in iter.invent_iterator:new(all_weap_schools) do if get_skill(v) > max then max = get_skill(v) top_school = v end end end local function get_weap_tag(it) local ret_val = if_el(it.is_ranged, "ranged_", "melee_") ret_val = ret_val..get_hands(it) if has_ego(it) then ret_val = ret_val.."b" end return ret_val end local function enforce_dmg_floor(target, floor) if inv_max_dmg[target] < inv_max_dmg[floor] then inv_max_dmg[target] = inv_max_dmg[floor] inv_max_dmg_acc[target] = inv_max_dmg_acc[floor] end end function generate_inv_weap_arrays() inv_weap_data = {} for k, _ in pairs(inv_max_dmg) do inv_max_dmg[k] = 0 inv_max_dmg_acc[k] = 0 end set_top_school() for cur in iter.invent_iterator:new(items.inventory()) do if is_weapon(cur) and not is_staff(cur) then update_high_scores(cur) inv_weap_data[#inv_weap_data + 1] = make_weapon_struct(cur) if has_ego(cur) then table.insert(egos, get_ego(cur)) end local dmg = inv_weap_data[#inv_weap_data].dps local weap_type = get_weap_tag(cur) if dmg > inv_max_dmg[weap_type] then inv_max_dmg[weap_type] = dmg local cur_plus = cur.plus if not cur_plus then cur_plus = 0 end inv_max_dmg_acc[weap_type] = cur.accuracy + cur_plus -- Keep a separate count for all melee weapons if weap_type:find("melee") then inv_max_dmg["melee_only"] = dmg inv_max_dmg_acc["melee_only"] = cur.accuracy + cur_plus end end end end -- Copy max_dmg from more restrictive categories to less restrictive enforce_dmg_floor("ranged_1", "ranged_1b") enforce_dmg_floor("ranged_2", "ranged_2b") enforce_dmg_floor("melee_1", "melee_1b") enforce_dmg_floor("melee_2", "melee_2b") enforce_dmg_floor("melee_1", "ranged_1") enforce_dmg_floor("melee_1b", "ranged_1b") enforce_dmg_floor("melee_2", "ranged_2") enforce_dmg_floor("melee_2b", "ranged_2b") enforce_dmg_floor("melee_2", "melee_1") enforce_dmg_floor("melee_2b", "melee_1b") end -- Alert strong weapons early local function alert_early_weapons(it) -- Alert really good usable ranged weapons if you.xl() <= 14 then if it.is_identified and it.is_ranged then if has_ego(it) and it.plus >= 5 or it.plus >= 7 then if get_hands(it) == 1 or not have_shield() or you.skill("shield") <= 8 then return pa_alert_item(it, "Ranged weapon") end end end end -- Skip items when we're clearly going another route if get_skill(top_school) - get_skill(it.weap_skill) > 1.5*you.xl()+3 then return end if you.xl() < 8 then if has_ego(it) or it.plus and it.plus >= 4 then -- Make sure we don't alert a pure downgrade to something in inventory for inv in iter.invent_iterator:new(inv_weap_data) do if inv.basename == it.name("base") then if inv.plus >= it.plus then if not has_ego(it) then return end if it.ego() == inv.ego then return end end end end return pa_alert_item(it, "Early weapon") end end end local function alert_first_ranged(it) if not it.is_ranged then return false end if get_hands(it) == 2 then if have_shield() then return false end if alerted_first_ranged_two_handed == 0 then alerted_first_ranged_two_handed = 1 for inv in iter.invent_iterator:new(inv_weap_data) do if inv.is_ranged and inv.hands == 2 then return true end end return pa_alert_item(it, "Ranged weapon") end else if alerted_first_ranged_one_handed == 0 then alerted_first_ranged_one_handed = 1 for inv in iter.invent_iterator:new(inv_weap_data) do if inv.is_ranged then return true end end return pa_alert_item(it, "Ranged weapon") end end return false end ---- pickup_weapons util ---- local function no_upgrade_possible(it, inv) if get_hands(it) > inv.hands then return true end if it.is_ranged ~= inv.is_ranged then return true end if inv.weap_skill == "Polearms" and it.weap_skill ~= "Polearms" then return true end return false end local function get_dmg_delta(it, cur, penalty) if not penalty then penalty = 1 end local delta local dmg_inv = inv_max_dmg[get_weap_tag(it)] if cur.dps >= dmg_inv then delta = get_weap_dps(it) - cur.dps else delta = get_weap_dps(it) - dmg_inv end if delta > 0 then return delta * penalty end return delta / penalty end local function need_first_weapon(it) if inv_max_dmg["melee_2"] ~= 0 then if inv_max_dmg["melee_only"] == 0 then -- Carrying ranged weapons only return get_weap_dps(it) > inv_max_dmg["melee_2"] end -- Carrying a melee weapon return false end if you.skill("Unarmed Combat") > 0 then return false end if get_mut("claws", true) > 0 then return false end if get_mut("demonic touch", true) > 0 then return false end return true end local function pickup_weapon(it, cur) if cur.subtype == it.subtype() then -- Exact weapon type match if it.artefact then return true end if cur.artefact then return false end if has_ego(it) and it.is_identified and not cur.branded then return get_weap_dps(it) > 0.85*cur.dps end if cur.branded and not has_ego(it) then return false end return it.ego() == cur.ego and get_weap_dps(it) > cur.dps + 0.001 --elseif get_skill(it.weap_skill) >= 0.5 * get_skill(cur.weap_skill) then elseif it.weap_skill == cur.weap_skill or you.race() == "Gnoll" then if no_upgrade_possible(it, cur) then return false end if it.artefact then return true end if cur.artefact then return false end if it.branded and not it.is_identified then return false end --if cur.branded and not it.branded then return false end if it.is_ranged then return get_weap_dps(it) > cur.dps + 0.001 end local it_plus = if_el(it.plus, it.plus, 0) local it_score = get_weap_dps(it) + (it.accuracy + it_plus)/3 local cur_score = cur.dps + cur.acc/3 return it_score > 1.1*cur_score end return false end function do_pa_weapon_pickup(it) if it.is_useless then return false end for cur in iter.invent_iterator:new(inv_weap_data) do if pickup_weapon(it, cur) then return true end end return need_first_weapon(it) end local function alert_interesting_weapon(it, cur) if it.artefact and it.is_identified then return pa_alert_item(it, "Artefact weapon") end if cur.subtype == it.subtype() then -- Exact weapon type match if not cur.artefact and has_ego(it) and it.ego() ~= cur.ego then return pa_alert_item(it, "New ego") end if get_weap_dps(it) > inv_max_dmg[get_weap_tag(it)] then return pa_alert_item(it, "Stronger weapon") end elseif get_skill(it.weap_skill) >= 0.5 * get_skill(cur.weap_skill) then -- A usable weapon school if it.is_ranged ~= cur.is_ranged then return false end --local penalty = 1 --if it.weap_skill == top_school then penalty = 0.5 end local penalty = (get_skill(it.weap_skill)+8) / (get_skill(top_school)+8) if get_hands(it) == 2 and cur.hands == 1 then -- Item requires an extra hand if has_ego(it) and not cur.branded then if get_weap_dps(it) > 0.8*cur.dps then return pa_alert_item(it, "2-handed weapon") end end if not have_shield() then if has_ego(it) and not (it.ego() == "heavy" or it.ego() == "speed") and not util.contains(egos, it.ego()) then return pa_alert_item(it, "New ego") end if not cur.branded and get_weap_dps(it) > inv_max_dmg[get_weap_tag(it)] then return pa_alert_item(it, "2-handed weapon") end if cur.branded and not has_ego(it) and get_weap_dps(it) > inv_max_dmg[get_weap_tag(it)] then return pa_alert_item(it, "2-handed weapon") end elseif you.skill("shields") <= 4 then -- Not really training shields; may be interested in big upgrades if penalty*get_weap_dps(it) >= inv_max_dmg["melee_2"] then return pa_alert_item(it, "2-handed weapon") end end else -- Item uses same number of hands or fewer if cur.artefact then return false end if has_ego(it) and not (it.ego() == "heavy" or it.ego() == "speed") then local dmg_delta = get_dmg_delta(it, cur, penalty) local dmg_delta_ratio = dmg_delta / get_weap_dps(it) if not cur.branded then if dmg_delta_ratio >= -0.2 then return pa_alert_item(it, "New ego") end elseif it.ego() == cur.ego then if dmg_delta_ratio >= 0 then return pa_alert_item(it, "Stronger weapon") end elseif not util.contains(egos, it.ego()) then if dmg_delta_ratio >= -0.2 then return pa_alert_item(it, "New ego") end end else -- Not branded -- Allowing lower-trained skills triggers too often after picking up an untrained weapon -- Only use it to trigger upgrades from a low-value branded weapon to unbranded if cur.branded and cur.weap_skill == it.weap_skill then if get_weap_dps(it, true) > get_weap_dps(it, true) then return pa_alert_item(it, "Stronger weapon") end else local dmg_delta, other_acc if cur.dps > inv_max_dmg[get_weap_tag(it)] then dmg_delta = get_weap_dps(it) - cur.dps other_acc = cur.acc else dmg_delta = get_weap_dps(it) - inv_max_dmg[get_weap_tag(it)] other_acc = inv_max_dmg_acc[get_weap_tag(it)] end if dmg_delta > 0 then return pa_alert_item(it, "Stronger weapon") end local it_plus = if_el(it.plus, it.plus, 0) if dmg_delta == 0 and (it.accuracy+it_plus) > other_acc then return pa_alert_item(it, "Higher accuracy") end end end end end end local function alert_interesting_weapons(it) local ranged_weap_in_inv = false for cur in iter.invent_iterator:new(inv_weap_data) do if alert_interesting_weapon(it, cur) then return true end if cur.is_ranged then ranged_weap_in_inv = true end end -- Alert for the first ranged weapon found (for 1 and 2 handed separately) if it.is_ranged and not ranged_weap_in_inv then if it.artefact or has_ego(it) and it.plus >= 4 then if get_hands(it) == 1 or not have_shield() then return pa_alert_item(it, "Ranged Weapon") end end end return false end local function alert_weap_high_scores(it) local category = update_high_scores(it) if category then pa_alert_item(it, category) end end function do_pa_weapon_alerts(it) if it.is_useless then return end if (it.artefact or has_ego(it)) and not it.is_identified then return end alert_first_ranged(it) alert_early_weapons(it) alert_interesting_weapons(it) -- Skip high score alerts if not using weapons if inv_max_dmg["melee_2"] > 0 then alert_weap_high_scores(it) end end } ############################### End lua/pickup-alert/pa-weapons.lua ############################### ########################################################################################## < function ready() OpenSkills() AnnounceDamage() end > ########## # Turn 0 # ########## < local need_skills_opened = true function OpenSkills() if you.turns() == 0 and need_skills_opened then crawl.sendkeys("!d10" .. string.char(13) .. "Lair D11-12 Orc D13-15 S-Runes V1-4 Depths" .. string.char(13)) need_skills_opened = false you.set_training_target("Fighting",18) you.set_training_target("Maces & Flails",18) you.set_training_target("Axes",18) you.set_training_target("Polearms",20) you.set_training_target("Unarmed Combat",18) you.set_training_target("Throwing",9) you.set_training_target("Short Blades",18) you.set_training_target("Long Blades",18) you.set_training_target("Ranged Weapons",18) you.set_training_target("Armour",9) you.set_training_target("Dodging",9) you.set_training_target("Shields",9) you.set_training_target("Stealth",4) you.set_training_target("Spellcasting",9) you.set_training_target("Conjurations",20) you.set_training_target("Hexes",6) you.set_training_target("Summonings",6) you.set_training_target("Necromancy",6) you.set_training_target("Forgecraft",6) you.set_training_target("Translocations",9) you.set_training_target("Alchemy",3) you.set_training_target("Fire Magic",18) you.set_training_target("Air Magic",6) you.set_training_target("Ice Magic",18) you.set_training_target("Earth Magic",18) you.set_training_target("Invocations",6) you.set_training_target("Evocations",6) you.set_training_target("Shapeshifting",7) crawl.sendkeys("m","!") end end > ############### # Damage Calc # ############### < local previous_hp = 0 local previous_mp = 0 local previous_form = "" local was_berserk_last_turn = false function AnnounceDamage() local current_hp, max_hp = you.hp() local current_mp, max_mp = you.mp() --Things that increase hp/mp temporarily really mess with this local current_form = you.transform() local you_are_berserk = you.berserk() local max_hp_increased = false local max_hp_decreased = false if (current_form ~= previous_form) then if (previous_form:find("dragon") or previous_form:find("statue") or previous_form:find("tree") or previous_form:find("ice")) or previous_form:find("hydra")then max_hp_decreased = true elseif (current_form:find("dragon") or current_form:find("statue") or current_form:find("tree") or previous_form:find("ice")) or previous_form:find("hydra")then max_hp_increased = true end end if (was_berserk_last_turn and not you_are_berserk) then max_hp_decreased = true elseif (you_are_berserk and not was_berserk_last_turn) then max_hp_increased = true end --crawl.mpr(string.format("previous_form is: %s", previous_form)) --crawl.mpr(string.format("current_form is: %s", current_form)) --crawl.mpr(string.format("max_hp_increased is: %s", max_hp_increased and "True" or "False")) --crawl.mpr(string.format("max_hp_decreased is: %s", max_hp_decreased and "True" or "False")) --crawl.mpr(string:format("you_are_berserk is: %s", you_are_berserk and "True" or "False")) --crawl.mpr(string:format("was_berserk_last_turn is: %s", was_berserk_last_turn and "True" or "False")) --Skips message on initializing game if previous_hp > 0 then local hp_difference = previous_hp - current_hp local mp_difference = previous_mp - current_mp if max_hp_increased or max_hp_decreased then if max_hp_increased then crawl.mpr("You now have [" .. current_hp .. "/" .. max_hp .. "] hp.") else crawl.mpr("You now have [" .. current_hp .. "/" .. max_hp .. "] hp.") end else --On losing health if (current_hp < previous_hp) then if hp_difference >= (max_hp * 0.30) then crawl.mpr("MASSIVE DAMAGE!!") elseif hp_difference >= (max_hp * 0.20) then crawl.mpr("You take " .. hp_difference .. " damage, and have [" .. current_hp .. "/" .. max_hp .. "] hp.") elseif hp_difference >= (max_hp * 0.10) then crawl.mpr("You take " .. hp_difference .. " damage, and have [" .. current_hp .. "/" .. max_hp .. "] hp.") elseif hp_difference >= (max_hp * 0.05) then crawl.mpr("You take " .. hp_difference .. " damage, and have [" .. current_hp .. "/" .. max_hp .. "] hp.") else crawl.mpr("You take " .. hp_difference .. " damage, and have [" .. current_hp .. "/" .. max_hp .. "] hp.") end end --On gaining health if (current_hp > previous_hp) then --Removes the negative sign local health_inturn = (0 - hp_difference) if (health_inturn > 1) and not (current_hp == max_hp) then if current_hp <= (max_hp * 0.30) then crawl.mpr('You gain ' .. health_inturn .. ' hp, and have [' .. current_hp .. '/' .. max_hp .. '] hp.') elseif current_hp <= (max_hp * 0.50) then crawl.mpr('You gain ' .. health_inturn .. ' hp, and have [' .. current_hp .. '/' .. max_hp .. '] hp.') elseif current_hp <= (max_hp * 0.70) then crawl.mpr('You gain ' .. health_inturn .. ' hp, and have [' .. current_hp .. '/' .. max_hp .. '] hp.') elseif current_hp <= (max_hp * 0.90) then crawl.mpr('You gain ' .. health_inturn .. ' hp, and have [' .. current_hp .. '/' .. max_hp ..'] hp.') else crawl.mpr('You gain ' .. health_inturn .. ' hp, and have [' .. current_hp .. '/' .. max_hp .. '] hp.') end end if (current_hp == max_hp) then crawl.mpr('HP Full. [' .. current_hp .. '/' .. max_hp .. '] hp.') end end --On losing magic if current_mp < previous_mp then if current_mp <= (max_mp / 4) then crawl.mpr("You now have [" .. current_mp .. "/" ..max_mp .."] mp.") elseif current_mp <= (max_mp / 2) then crawl.mpr("You now have [" .. current_mp .. "/" ..max_mp .."] mp.") else crawl.mpr("You now have [" .. current_mp .. "/" ..max_mp .."] mp.") end end end end --Set previous hp/mp and form at end of turn previous_hp = current_hp previous_mp = current_mp previous_form = current_form was_berserk_last_turn = you_are_berserk end > ####################### ### Mini Map Colors ### ####################### # reddit.com/r/dcss/comments/gpz245/custom_minimap_color_scheme_for_better_clarity/ # tile_portal_col = #ff4f1a # tile_downstairs_col = red tile_downstairs_col = #ff1a1a tile_branchstairs_col = yellow # tile_branchstairs_col = #ff006a tile_upstairs_col = green # tile_upstairs_col = #99ff33 tile_explore_horizon_col = #bfbfbf tile_floor_col = #262626 tile_water_col = #0086b3 tile_deep_water_col = #1f1fed tile_lava_col = #6f0b00 tile_wall_col = #595959 tile_door_col = #cb7d4d # tile_feature_col = #d4be21 tile_plant_col = #5c8745 tile_transporter_col = #ff80bf tile_transporter_landing_col = #59ff89 tile_trap_col = #d24dff ############### ### Display ### ############### # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/defaults/menu_colours.txt tile_font_crt_size = 21 tile_font_stat_size = 21 tile_font_msg_size = 21 tile_font_tip_size = 21 tile_font_lbl_size = 21 tile_font_ft_light = false tile_cell_pixels = 38 tile_font_crt_family = UD デジタル 教科書体 N-B tile_font_stat_family = UD デジタル 教科書体 N-B tile_font_msg_family = UD デジタル 教科書体 N-B tile_font_lbl_family = UD デジタル 教科書体 N-B tile_realtime_anim = true # Trunk 0.33 Crash caused by signal #6: Aborted tile_show_player_species = true tile_player_status_icons = slow, constr, fragile, petr, mark, will/2, haste, weak, corr, might, brill, -move action_panel_font_size = 19 action_panel_font_family = UD デジタル 教科書体 N-B action_panel_orientation = vertical action_panel_show = false menu := menu_colour # menu ^= lightgrey:potions? of (attraction|lignification|mutation) # menu ^= lightgrey:scrolls? of (poison|torment|immolation|vulnerability|noise) msc := message_colour msc ^= lightgrey:( miss | misses |no damage|not reach far enough) hp_colour = 100:green, 99:lightgray, 75:yellow, 50:lightred, 25:red mp_colour = 100:green, 99:lightgray, 75:yellow, 50:lightred, 25:red hp_warning = 50 mp_warning = 30 # enemy_hp_colour = lightgrey lightgreen brown yellow lightmagenta lightred tile_show_threat_levels = trivial, easy, tough, nasty, unusual tile_show_demon_tier = true always_show_zot = true always_show_gems = true more_gem_info = true ############# # Interface # ############# autofight_nomove_fires = false autofight_fire_stop = true autofight_caught = true autofight_wait = true autofight_stop = 50 rest_wait_both = true rest_wait_ancestor = true fire_order = spell, throwing, evokable fire_order_ability -= all fail_severity_to_quiver = 3 fail_severity_to_confirm = -1 spell_menu = true show_more = false easy_confirm = safe equip_unequip = true sort_menus = true:equipped,charged,art,ego,glowing,identified,basename stat_colour = 3:red, 7:lightred default_manual_training = true : if you.xl() <= 3 then skill_focus = true : end : if you.xl() >= 4 then skill_focus = false : end # orb run # travel_delay = 1 explore_delay = 15 view_delay = 550 # show_blood = false level_map_cursor_step = 8 warn_hatches = true travel_open_doors = approach explore_stop = greedy_pickup_smart explore_stop += stairs,shops,altars,portals,branches,runed_doors,glowing_items,artefacts,runes ########### # Prompts # ########### # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/defaults/messages.txt # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/defaults/runrest_messages.txt # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/defaults/misc.txt ignore := runrest_ignore_message stop := runrest_stop_message more := force_more_message flash := flash_screen_message # ignore += duration: ignore += recovery: ignore += contamination has completely ignore += your breath back ignore += engulfed in a cloud of smoke ignore += engulfed in white fluffiness ignore += safely over a trap # crawl.chaosforge.org/Portal # github.com/crawl/crawl/tree/master/crawl-ref/source/dat/des/portals # very nearby: 7–13, nearby: 14–20, distant: 21–27, very distant: 28+ stop += timed_portal: stop += You hear.*(nearby|distant) flash += You hear.*very (nearby|distant) flash += You hear.*(quick|urgent|loud (?!squeak)|rising multitudes|rapid|thunderous|frantic|ear-piercing|full choir) more += Found.*(bazaar|trove|phantasmal|sand-covered|glowing drain|flagged portal|gauntlet|frozen archway|dark tunnel|ruined gateway|magical portal|ziggurat) more += The walls and floor vibrate strangely for a moment # Expiring effects more += Your transformation is almost over more += back to life more += You feel yourself slow down more += less insulated more += You are starting to lose your buoyancy more += You lose control over your flight more += Your hearing returns more += You have a feeling this form more += You feel yourself come back to life more += uncertain more += time is quickly running out more += life is in your own hands more += shroud falls apart more += You start to feel a little slower more += You flicker more += You feel less protected from missiles # Interrupts more += You don't.*that spell more += You fail to use your ability more += You miscast.*(Blink|Borgnjor|Door|Invisibility) more += You can't (read|drink|do) more += You cannot.*while unable to breathe more += You cannot.*in your current state more += when.*silenced more += too confused more += There's something in the way more += There's nothing to (close|open) nearby more += not good enough to have a special ability more += You are too berserk more += no means to grasp more += That item cannot be evoked more += You are held in a net more += You don't have any such object more += You can't unwield more += enough magic points more += You don't have the energy to cast that spell more += You are unable to access your magic more += is a mimic more += You feel a bit more experienced # more += Reactivating autopickup more += You kill the orb of fire # more += There is a shaft here more += a shaft more += The shaft crumbles and collapses confirm_action += Potion Petition, Call Merchant, Blink, Silence, Maxwell's Capacitive Coupling # force_spell_targeter += Silence : if you.res_shock() <= 0 then confirm_action += conjure ball lightning, chain lightning : end # Bad things # github.com/crawl/crawl/blob/master/crawl-ref/source/mutation-data.h # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/database/monspell.txt # github.com/crawl/crawl/blob/master/crawl-ref/source/beam.cc flash += mutation: more += You feel vulnerable to more += hell_effect: flash += LOW HITPOINT WARNING flash += MASSIVE DAMAGE flash += LOW MAGIC WARNING more += You stop ascending the stairs flash += You stop ascending the stairs more += A malevolent force fills more += An alarm trap emits a blaring wail more += A sentinel's mark forms upon you more += Your surroundings flicker more += You cannot teleport right now more += A huge blade swings out and slices into you more += (blundered into a|invokes the power of) Zot more += That really hurt more += You convulse more += Your body is wracked with pain more += offers itself to Yredelemnul more += You are (blasted|electrocuted) more += You are.*confused more += wrath finds you more += god:(sends|finds|silent|anger) more += You feel a surge of divine spite more += disloyal to dabble more += lose consciousness more += You are too injured to fight blindly more += The blast of calcifying dust hits (?!your) more += Space warps horribly.*around you more += Space bends around you more += watched by something more += Your limbs have turned to stone more += lethally poison more += You are covered in intense liquid fire more += Strange energies course through your body more += breathes a rupture in space-time more += You feel strangely unstable more += (?= 26 then more += You add the spells?.*(Beckoning|Golubria|Vhi's Electric|Manifold Assault|Fugue of the|Animate Dead|Death Channel|Awaken Armour) : end # stop += Your spellspark servitor fades away # Skills stop += skill increases to level (9|18|26) stop += Your Shields skill increases to level (4|6|9|15|21|25) stop += Your Short Blades skill increases to level (10|12|14) stop += Your Long Blades skill increases to level (14|16|18|24) stop += Your Maces & Flails skill increases to level (12|16|20|22) stop += Your Axes skill increases to level (16|18|20|26) stop += Your Polearms skill increases to level (14|16|20|26) stop += Your Staves skill increases to level (12|14) stop += Your Throwing skill increases to level (6|10|16) stop += Your Evocations skill increases to level (6|10|13|15|18|21) more += Your Invocations skill increases to level (6|10|11|12|13) more += Your Shapeshifting skill increases to level (14|19|23|26) more += Training target.*reached more += You have finished (your manual|forgetting about) more += You pick up a manual of stop += You see here the stop += You see here.*(war axe|broad axe|whip|mace|flail|ningstar|trident|partisan).*holy stop += You see here.*scrolls? of acquirement : if you.xl() >= 22 then stop += You see here.*scrolls? of enchant armour : end : if you.xl() >= 14 then stop += You see here.*scrolls? of enchant weapon : end : if you.xl() <= 24 then stop += You see here.*(granite talisman|talisman of death|crystal plate armour|golden dragon scales|sacred scourge|trishula) # more += The golden dragon scales are intact enough to wear : end : if you.xl() <= 16 then stop += You see here.*(scrolls? of identify|shadow dragon scales|pearl dragon scales|storm dragon scales) : end : if you.xl() <= 12 then stop += You see here.*(ring of|the ring|amulet|shield|hat|cloak|scarf|gloves|boots|plate armour) more += Found.*(Elyvilon|The Shining One|Zin) : end : if you.xl() <= 10 then stop += You see here.*(quicksilver dragon scales|ice dragon scales|chain mail|fire dragon scales|swamp dragon scales) more += Found.*(Ashenzari|Cheibriados|Gozag|Jiyva|Makhleb|Okawaru|Qazlal|Ru|Trog|Uskayaw|Wu Jian|Yredelemnul|Zin) : end : if you.xl() > 18 then more += Found.*(Zin|The Shining One) : end # Uniques and baddies # github.com/crawl/crawl/blob/master/crawl-ref/source/mon-gear.cc more += BOSS more += is (wielding|wearing) the more += wielding.*of (distortion|chaos) more += quivering silver more += (torpor snail|nekomata|doom hound|acid blob|entropy weaver|ghost moth|death knight) (?!zombie|skeleton|simulacrum).*into view flash += changes into,Something shouts,BOSS # Dissolution (Slime:2-5) # github.com/crawl/crawl/blob/master/crawl-ref/source/mon-act.cc # flash += You hear a (sizzling sound|grinding noise) more += (? 4 then ae += stone : end : if you.xl() > 18 then ae += vulnerability, wand of (polymorph|charming|paralysis), (datura|atropa)-tipped dart : end : if you.xl() > 24 then ae += identify, wand of mindburst : end : if you.xl() <= 10 then drop_disables_autopickup = true : end : if you.xl() >= 11 then drop_disables_autopickup = false : end ################## ### Item Slots ### ################## # crawl.chaosforge.org/Inscriptions ai := autoinscribe ai += magical staff:!a ai += (large rock|silver javelin|throwing net|(curare|datura|atropa)-tipped dart|of disjunction):=f ai += potions? of heal wounds:@q1, 10-37HP ai += potions? of curing:@q2, 5-11HP ai += potions? of cancellation:@q3 ai += potions? of haste:@q4 ai += potions? of magic:@q5, 10-37MP ai += potions? of ambrosia:3-5HPMP/T ai += potions? of lignification:1.5xHP (20+XL/2)AC rPo Torm0 Ev0 -MoBlTe GearShie ai += scrolls? of identify:@r1 ai += scrolls? of teleportation:@r2, 3-5T, Zot8-14T ai += scrolls? of blinking:@r3 ai += enchant armour:@r4 ai += enchant weapon:@r5 ai += scrolls? of fear:Q*f, 40Will90% 60Will73% ++41-80 ai += scrolls? of silence:30Turns ai += scrolls? of noise:25 Alarm40 FireStor25 FulmPris20 Qaz16 Shout12 IMB10 ai += wand of (iceblast|roots|warping):@v1, \< ai += wand of (acid|light|quicksilver):@v2, \> ai += wand of digging:@v3 ai += poisoned dart:@f1@Q1, F1 ai += boomerang:@f2@Q2, F2 ai += (? 4 then ai += (? 8 then ai += (? 12 then ai += (? 14 then ai += (? 16 then ai += (? 20 then ai += (? 22 then ai += (?") end } macros += M N ===godownopen { function goupopen() crawl.setopt("travel_open_doors = open") crawl.sendkeys("X","<") end } macros += M U ===goupopen { function travelopen() crawl.setopt("travel_open_doors = open") crawl.sendkeys("G",{9}) end } macros += M T ===travelopen # Tab:\{9}, Enter:\{13}, Esc:\{27}, Space:\{32}, Ctrl:*, Shift:/ # x.com/tt5074/status/1788555362213539956 # x.com/tt5074/status/1788556096833245588 # github.com/crawl/crawl/blob/master/crawl-ref/source/dat/descript/features.txt macros += M _ *f<>\{32}&&\{32}!!one-\{13} macros += M n x+ macros += M l x+v macros += M L x-v macros += M C X*e macros += M Y tt macros += M I II macros += M R \\- macros += M y ff macros += M : vf macros += M O aa macros += M K ab macros += M B af macros += M , *f@\{32}&&\{32}!!transp\{32}&&\{32}!!stai\{32}&&\{32}!!hatc\{32}&&\{32}!!trap\{32}&&\{32}!!moons\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M P *fin_shop\{32}&&\{32}!!moons\{32}&&\{32}!!carri\{13} macros += M S *f<>\{32}&&\{32}!!moons\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M % *f<>\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M " *f<>\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M [ *f<>\{32}&&\{32}!!orb\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M ` *f<>\{32}&&\{32}!!jewell\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} # macros += M & *f<>\{32}&&\{32}!!magica\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} # macros += M & *f<>\{32}&&\{32}!!magica\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} macros += M & *f<>\{32}&&\{32}!!magica\{32}&&\{32}!!zz\{32}&&\{32}!!carri\{13} # F1:\{-265}:poisoned dart, F2:\{-266}:boomerang, H:javelin, ")":wand of flame, "(":mindburst, "<":iceblast|roots|warping, ">":acid|light|quicksilver macros += M \{-265} F15 macros += M \{-266} F25 macros += M H F3 macros += M ) V45 macros += M ( V55 macros += M < V15 macros += M > V25 macros += M E zaf macros += M 1 za macros += M 2 zb macros += M 3 zc macros += M 4 zd macros += M 5 ze macros += M 6 zf macros += M 7 zg macros += M 8 zh macros += M 9 zi macros += M 0 zj # Confirm targeting with same keys as spellcasting # github.com/brianfaires/crawl-rc/blob/main/rc/macros.rc macros += K2 1 \{13} macros += K2 2 \{13} macros += K2 4 \{13} macros += K2 6 \{13} macros += K2 7 \{13} macros += K2 8 \{13} macros += K2 9 \{13} macros += K2 0 \{13} # github.com/crawl/crawl/blob/master/crawl-ref/docs/keybind.txt bindkey = [NP5] CMD_WAIT bindkey = [NP5] CMD_TARGET_SELECT_ENDPOINT bindkey = [s] CMD_REST bindkey = [c] CMD_CLOSE_DOOR bindkey = [C] CMD_MAP_CLEAR_EXCLUDES bindkey = [W] CMD_WIELD_WEAPON bindkey = [w] CMD_WEAR_ARMOUR bindkey = [p] CMD_WEAR_JEWELLERY bindkey = [Tab] CMD_AUTOFIGHT_NOMOVE bindkey = [k] CMD_AUTOFIRE bindkey = [u] CMD_PREV_CMD_AGAIN bindkey = [i] CMD_RESISTS_SCREEN bindkey = [e] CMD_FULL_VIEW bindkey = [e] CMD_TARGET_FULL_DESCRIBE bindkey = [e] CMD_MAP_EXIT_MAP bindkey = [k] CMD_TARGET_EXCLUDE bindkey = [k] CMD_MAP_EXCLUDE_AREA bindkey = [\{13}] CMD_DISPLAY_INVENTORY bindkey = [NPenter] CMD_DISPLAY_INVENTORY bindkey = [\{NP+}] CMD_GO_DOWNSTAIRS bindkey = [\{NP-}] CMD_GO_UPSTAIRS bindkey = [\{NP+}] CMD_MAP_FIND_DOWNSTAIR bindkey = [\{NP-}] CMD_MAP_FIND_UPSTAIR bindkey = [\{NP*}] CMD_CYCLE_QUIVER_FORWARD bindkey = [\{NP/}] CMD_CYCLE_QUIVER_BACKWARD bindkey = [ ] CMD_TARGET_CANCEL bindkey = [ ] CMD_MAP_EXIT_MAP bindkey = [b] CMD_TARGET_CANCEL bindkey = [h] CMD_TARGET_CANCEL bindkey = [j] CMD_TARGET_CANCEL bindkey = [l] CMD_TARGET_CANCEL bindkey = [n] CMD_TARGET_CANCEL bindkey = [u] CMD_TARGET_CANCEL bindkey = [y] CMD_TARGET_CANCEL bindkey = [B] CMD_TARGET_CANCEL bindkey = [H] CMD_TARGET_CANCEL bindkey = [J] CMD_TARGET_CANCEL bindkey = [K] CMD_TARGET_CANCEL bindkey = [L] CMD_TARGET_CANCEL bindkey = [N] CMD_TARGET_CANCEL bindkey = [U] CMD_TARGET_CANCEL bindkey = [Y] CMD_TARGET_CANCEL bindkey = [b] CMD_MAP_EXIT_MAP bindkey = [h] CMD_MAP_EXIT_MAP bindkey = [j] CMD_MAP_EXIT_MAP bindkey = [l] CMD_MAP_EXIT_MAP bindkey = [n] CMD_MAP_EXIT_MAP bindkey = [u] CMD_MAP_EXIT_MAP bindkey = [y] CMD_MAP_EXIT_MAP bindkey = [B] CMD_MAP_EXIT_MAP bindkey = [H] CMD_MAP_EXIT_MAP bindkey = [J] CMD_MAP_EXIT_MAP bindkey = [K] CMD_MAP_EXIT_MAP bindkey = [L] CMD_MAP_EXIT_MAP bindkey = [N] CMD_MAP_EXIT_MAP bindkey = [U] CMD_MAP_EXIT_MAP bindkey = [Y] CMD_MAP_EXIT_MAP