############################################################################################### ## ## 원본 : https://github.com/HilariousDeathArtist/DCSSConfigFile/blob/master/HDAtravel.txt ## 제작자 : HilariousDeathArtist ## ############################################################################################### ## ## -참조- ## 돌죽 옵션 가이드 http://crawl.akrasiac.org/docs/options_guide.txt ## 돌죽 lua api http://doc.dcss.io/modules/you.html ## 돌죽 봇 https://github.com/elliptic/qw ## ############################################################################################### ## ## -기능- ## 1. 자동 휴식 ## 2. 자동 채널링 ## 3. 자동 시체 일으키기 ## 4. 자동 소모품 감정 ## 5. 헬멧, 장갑, 부츠, 망토 슬롯이 비어있으면 자동으로 착용 ## 6. 스피드런 휴식 연동 ## ############################################################################################### ## ## -주의사항- ## ## 1. '#' 표시를 지우고 아래 옵션을 그대로 rc에 넣어야 사용이 가능합니다. ## ex) https://webzook.net/soup/rcfiles/trunk/test12345.rc ## ## 2. 좀비, 해골 일으키기 슬롯은 "x", "z" 로 기본값을 지정하였고 ## 알파벳을 바꾸는 것으로 변경할 수 있습니다. ## 마법 슬롯을 지정하는 옵션이 이미 들어가 있을 경우 오류가 나기 때문에 ## 알파벳을 통일시켜 주어야 합니다. ## ## 3. 휴식을 시작할 기준 HP, MP를 지정할 수 있습니다. ## 자동 휴식을 사용하지 않으려면 숫자를 0으로 변경하면 됩니다. ## ## 4. 자동 아이템 감정 시 돌연변이 포션, 블링크 스크롤을 사용하게 될 수도 있습니다. ## ## 5. 이 rc를 적용할 경우 강제로 o키의 기능을 바꿔버리며 ## rc를 지우더라도 그 영향이 남습니다. ## 지우고 나서 macros += M o o 옵션을 넣고 게임을 실행하세요. ## ## 6. 테스트한 조합은 미노타 이레데, 머포크 강령술사, 펠리드 인챈터이며 ## 다른 조합에서 에러가 날 수도 있습니다. ## ############################################################################################### ## ## include += HDATravel1.rc ## ## :if is_included_HDATravel1 then ## : autorest_hp_percent = 80 ## : autorest_mp_percent = 70 ## : spell_slot_Animate_Dead = "x" ## : spell_slot_Animate_Skeleton = "z" ## : crawl.setopt("spell_slot ^= Animate Dead:+" .. spell_slot_Animate_Dead) ## : crawl.setopt("spell_slot ^= Animate Skeleton:+" .. spell_slot_Animate_Skeleton) ## :else ## : crawl.setopt("macros += M o o") ## :end ## ############################################################################################### --에너지 스태프 슬롯에 관계 없이 w1만 누르면 착용이 가능하도록 하기 autoinscribe += staff of energy:@w1 : --다른 rc에서 이 rc를 사용중인지 확인하기 위한 값 : is_included_HDATravel1 = true : : --해당 rc를 사용할 경우 메시지 로그를 남긴다. : crawl.mpr("HDATravel1.rc is included.") : : --기본으로 제공되는 탐색 시 자동휴식하는 기능을 비활성화 : crawl.setopt("explore_auto_rest = false") : : --매크로로 o키를 HDAtravel() 함수를 불러오게 변경 : crawl.setopt("macros += M o ===HDAtravel") : : --사용자가 슬롯을 지정하지 않으면 좀비 일으키기 슬롯을 x로 설정 : if (spell_slot_Animate_Dead == nil) then : spell_slot_Animate_Dead = "x" : crawl.setopt("spell_slot ^= Animate Dead:+" .. spell_slot_Animate_Dead) : end : : --사용자가 슬롯을 지정하지 않으면 해골 일으키기 슬롯을 z로 설정 : if (spell_slot_Animate_Skeleton == nil) then : spell_slot_Animate_Skeleton = "z" : crawl.setopt("spell_slot ^= Animate Skeleton:+" .. spell_slot_Animate_Skeleton) : end : : if (autorest_hp_percent == nil) then : autorest_hp_percent = 80 : end : : if (autorest_mp_percent == nil) then : autorest_mp_percent = 70 : end : --o키를 누를 때마다 호출되는 함수 : function HDAtravel() : hp, max_hp = you.hp() : mp, max_mp = you.mp() : local first_monster = next(getMonsterList()) : local is_safe = (first_monster == nil) : local should_rest_hp = (hp/max_hp < tonumber(autorest_hp_percent) / 100) and (you.race() ~= "Deep Dwarf") : local should_rest_mp = (mp/max_mp < tonumber(autorest_mp_percent) / 100) and (not do_not_rest_mp) : local you_are_barbed = have_barbs() and (not removed_barbs) : local you_are_good_god = string.find(you.god(), "Shining") or string.find(you.god(), "Elyvilon") or string.find(you.god(), "Zin") : local you_are_yredelemnul = string.find(you.god(), "Yredelemnul") : local you_have_staff_of_energy = is_in_inventory("staff of energy") and (you.base_skill("Evocations") >= 5) : local staff_of_energy_is_equipped = is_weapon("staff of energy") : local should_animate = (item_in_view("corpse") or item_in_view("skeleton")) and (stop_animate() == nil) and (not you_are_good_god) : local invoke_animate_dead = (you_are_yredelemnul) and (you.piety_rank() >= 3) and (mp>=2) and should_animate and can_cast : local invoke_animate_skeleton = (you_are_yredelemnul) and (you.piety_rank() >= 1 and you.piety_rank() < 3) and (mp>=2) and on_corpses() and can_cast : local known_spells = init_spells() : local can_cast = can_read() : local cast_animate_dead = known_spells["Animate Dead"] and (spells.fail("Animate Dead") < 40) and (mp>=4) and should_animate and can_cast : local cast_animate_skeleton = known_spells["Animate Skeleton"] and (spells.fail("Animate Skeleton") < 30) and (mp>=1) and should_animate and can_cast : : --근처에 몬스터가 없을 때 o키를 누른 경우 : if (is_safe) then : --가시 박혔으면 휴식 : if (you_are_barbed) then : crawl.mpr("You are Barbed. Start Resting.") : rest() : --자동 MP 휴식 : elseif (should_rest_mp) then : crawl.mpr("Your MP is lower than " .. autorest_mp_percent .. "%.") : --에너지 스태프 있으면 자동 채널링 : if you_have_staff_of_energy and weapon_can_swap_HDA() then : if not staff_of_energy_is_equipped then : save_weapon_info_HDA() : crawl.mpr("Switching to staff of energy.") : sendkeys('w1') : end : crawl.mpr("Autochanneling using staff of energy.") : sendkeys('vv') : end : rest() : --채널링 이후에 다시 무기 착용 : elseif staff_of_energy_is_equipped and weapon_slot ~= nil then : crawl.mpr("Switching to weapon") : if (weapon_slot == nil) then : sendkeys("w-") : else : sendkeys("w*" .. weapon_slot) : weapon_slot = nil : end : --자동 HP 휴식 : elseif (should_rest_hp) then : crawl.mpr("Your HP is lower than " .. autorest_hp_percent .. "%.") : rest() : --자동 시체 일으키기 (이레데 3성 권능) : elseif (invoke_animate_dead) then : crawl.mpr("Autocasting Mass Animate Remains.") : sendkeys('aa') : --자동 시체 일으키기 (강령 4렙 스펠) : elseif (cast_animate_dead) then : crawl.mpr("Autocasting Animate Dead.") : --좀비를 소환하고 MP를 채우기 위해 휴식하면 그 시간동안 좀비가 사라지므로 MP 휴식을 막는다. : do_not_rest_mp = true : sendkeys('z' .. spell_slot_Animate_Dead) : --자동 시체 일으키기 (이레데 1성 권능) : elseif (invoke_animate_skeleton) then : crawl.mpr("Autocasting Animate Remains.") : sendkeys('aa') : --자동 시체 일으키기 (강령 1렙 스펠) : elseif (cast_animate_skeleton) then : crawl.mpr("Autocasting Animate Skeleton.") : do_not_rest_mp = true : sendkeys('z' .. spell_slot_Animate_Skeleton) : --층 탐색이 끝나면 아이템 감정하고 부속 갑옷 착용함 : else : if string.find(crawl.messages(20), escape("Done exploring")) or string.find(crawl.messages(20), escape("Partly explored")) then : identify_item() : drop_useless_item() : equip_sub_armour() : end : do_not_rest_mp = false : explore() : end -- end if (you_are_barbed) : --근처에 몬스터가 있을 때 o키를 누른 경우 : else : explore() : end -- end if (is_safe) : end -- end function < --자신이 시체 위에 서 있는지 확인 function on_corpses() local fl = you.floor_items() for it in iter.invent_iterator:new(fl) do if (string.find(it.name(), "corpse") or string.find(it.name(), "skeleton")) and not string.find(it.name(), "rotting") and not string.find(it.name(), "shifter") and not string.find(it.name(), "plague") then return true end end return false end --필요없는 아이템을 버린다 function drop_useless_item() --버릴 아이템 목록은 수동으로 넣어줘야 함 local useless_item_list = {"noise", "useless", "degeneration"} for it in inventory() do for _, useless_item in ipairs(useless_item_list) do if it.name():find(useless_item) then sendkeys("d" .. letter(it) .. string.char(13)) return end end -- end for end -- end for end -- end function --부속 갑옷 슬롯이 비어있으면 인벤토리에 있는 부속 갑옷 착용 --qw 봇 plan_upgrade_armour() 참조 function equip_sub_armour() --나무폼 등 변이 상태가 아니어야 동작함 if you.transform() ~= "" then return end for it in inventory() do if (it.class(true) == "armour") then --인벤토리에 있는 헬멧, 신발, 장갑, 망토를 발견하면 --변이 때문에 착용이 불가능한지 확인 local can_equip = false if (it.subtype() == "helmet" and it.ac == 1) and (you.mutation("horns") == 0 and you.mutation("beak") == 0 and you.mutation("antennae") == 0) then can_equip = true end if (it.subtype() == "helmet" and it.ac == 0) and (you.mutation("horns") < 3 and you.mutation("antennae") < 3) then can_equip = true end if (it.subtype() == "boots") and (you.mutation("talons") < 3 and you.mutation("hooves") < 3) then can_equip = true end if (it.subtype() == "boots") and (you.race() == "Merfolk" and view.feature_at(0,0) ~= "shallow_water" and view.feature_at(0,0) ~= "deep_water") then can_equip = true end if (it.subtype() == "gloves") and (you.mutation("claws") < 3) then can_equip = true end if (it.subtype() == "cloak") then can_equip = true end --부속 갑옷 슬롯이 비어있는지 확인 if (can_equip) and (items.equipped_at(it.subtype()) == nil) then crawl.mpr("Auto equipping " .. it.name() .. ".") sendkeys("W" .. letter(it)) end end -- end if end -- end for end -- end function --감정 스크롤을 사용해서 아이템 감정 --qw 봇 plan_use_id_scrolls() 참조 function identify_item() --인벤토리의 감정 스크롤 정보를 찾는다 local id_scroll for it in inventory() do if it.class(true) == "scroll" and it.name():find("identify") then id_scroll = it end end --감정 스크롤이 없으면 아이템을 직접 사용해서 감정 if (not id_scroll) then identify_by_using_item() return end --스크롤을 읽을 수 없으면 동작하지 않음 if (not can_read()) then return end --미감정 포션, 스크롤을 대상으로 감정 스크롤 사용 for it in inventory() do if ((it.class(true) == "potion") or (it.class(true) == "scroll")) and (not it.fully_identified) then sendkeys("r" .. letter(id_scroll) .. letter(it)) return end end -- end for end -- end function --아이템을 직접 사용해서 감정 function identify_by_using_item() for it in inventory() do --2개 이상 소지한 미감정 포션, 스크롤을 사용 if (not it.fully_identified) and (it.quantity >= 2) then if (it.class(true) == "potion") and (can_drink()) then sendkeys("q" .. letter(it)) return elseif (it.class(true) == "scroll") and (can_read()) then sendkeys("r" .. letter(it)) return end end end -- end for end -- end function --아이템 정보를 받아 해당 아이템의 슬롯이 뭔지 알아낸다 function letter(input) if type(input) == "userdata" then return items.index_to_letter(input.slot) elseif type(input) == "number" then return items.index_to_letter(input) else return input end end --스크롤을 읽을 수 있는 상황인지 확인 function can_read() local int, _ = you.intelligence() if you.berserk() or you.confused() or you.silenced() or you.status("engulfed (cannot breathe)") or (int <= 0) then return false end return true end --포션을 마실 수 있는 상황인지 확인 function can_drink() if you.berserk() or you.race() == "Mummy" or you.transform() == "bat" or you.transform() == "lich" or you.status("no potions") then return false end return true end --스피드런 rc 적용했으면 빵 휘둘러서 휴식하고 아니면 5키로 휴식 function rest() if is_included_SpeedrunRest1 then start_resting() else sendkeys('5') end end --자동 탐색 function explore() sendkeys('o') end --키 입력 전송 function sendkeys(command) crawl.flush_input() crawl.sendkeys(command) coroutine.yield(true) crawl.flush_input() end --인벤토리에 해당 아이템이 있는지 확인 --에너지, 위자드리 스태프가 있는지 확인하는데 씀 function is_in_inventory(str) for it in inventory() do if string.find(it.name(), str) then return true end end return false end --무기 슬롯에 해당 아이템을 착용하고 있는지 확인 --에너지, 위자드리 스태프 착용 여부 확인하는데 씀 function is_weapon(str) local weapon = items.equipped_at("Weapon") if weapon then return string.find(weapon.name(), str) else return false end end --시야 전체에 특정 아이템이 있는지 찾는다 --시체 찾는 용도로 사용 function item_in_view(str) local los_range = 7 if you.race() == "Barachi" then los_range = 8 end for x = -los_range, los_range do for y = -los_range, los_range do local pile = items.get_items_at(x,y) if pile ~= nil then for it in iter.invent_iterator:new(pile) do if string.find(it.name(), str) and you.see_cell_no_trans(x,y) then return true end end end end end return false end --시야 전체에 있는 몬스터 리스트를 가져옴 --휴식을 위해 몬스터가 없는지 확인하기 위해 사용 function getMonsterList() local los_range = 7 if you.race() == "Barachi" then los_range = 8 end local monsters = {} for x = -los_range, los_range do for y = -los_range, los_range do m = monster.get_monster_at(x, y) local attitude_hostile = 0 if m and (m:attitude() == attitude_hostile) and not (m:is_firewood()) then desc = m:desc() if (monsters[desc] == nil) then monsters[desc] = 1 else monsters[desc] = monsters[desc] + 1 end end end end return monsters end --메모라이즈 해놓은 마법 목록을 불러온다 function init_spells() local spell_list = {} for _, spell_name in ipairs(you.spells()) do spell_list[spell_name] = true end return spell_list end function have_barbs() return string.find(crawl.messages(10), escape("The barbed spikes become lodged in your body")) or string.find(crawl.messages(10), escape("The barbed spikes dig painfully into your body as you move")) end function removed_barbs() return string.find(crawl.messages(10), escape("You carefully extract the manticore spikes from your body")) or string.find(crawl.messages(10), escape("The manticore spikes snap loose")) end --시체 일으키기 시전 시 나오는 메시지를 이용해 1번만 시전하도록 함 function stop_animate() return string.find(crawl.messages(10), escape("There is nothing here that can be animated")) or string.find(crawl.messages(10), escape("There is nothing nearby to animate!")) or string.find(crawl.messages(10), escape("but the skeleton had no space to rise!")) or string.find(crawl.messages(10), escape("You call on the dead to rise...")) or string.find(crawl.messages(10), escape("You see a puff of smoke.")) or string.find(crawl.messages(10), escape("There are no remains here to animate!")) end --Escapes the special characters in a string for pattern matching function escape(str) --Escapes parens and dash "()-" local escaped = str:gsub('[%(%)%-]','%\%1') --Removes any coloration parts of the string return (escaped:gsub('<[^<]*>','')) end function inventory() return iter.invent_iterator:new(items.inventory()) end --무기를 바꿀 수 있는지 확인 function weapon_can_swap_HDA() --무기를 못 끼는 변이상태임 if not (you.transform() == nil or you.transform() == "" or you.transform() == "statue" or you.transform() == "lich" or you.transform() == "tree") then return false end local weapon = items.equipped_at("Weapon") --무기를 안 끼고 있음 if not weapon then return true end --저주받은 무기를 착용중 if weapon.cursed then return false end --왜곡 브랜드 무기를 착용중 local ego = weapon.ego() if ego and (ego == "distortion" and you.god() ~= "Lugonu") then return false end --마법오염, 저주, 드레인 붙은 아티팩트 무기를 착용중 if weapon.artefact then local artp = weapon.artprops return not (artp["*Contam"] or artp["*Curse"] or artp["*Drain"]) end return true end --에너지 스태프로 바꿔 끼기 전에 이전에 착용한 무기 슬롯을 저장 function save_weapon_info_HDA() weapon = items.equipped_at("Weapon") if weapon ~= nil then weapon_slot = letter(weapon.slot) crawl.mpr("Your weapon is " .. weapon.name() .. "") end end >