##### 기본 설정 ##################################################### # 인터페이스 언어 # 메시지 more 강제 사용 안 함 (Ctrl+P로 로그 확인) show_more = false # 스킬 자동배분 끄기 (항상 수동) default_manual_training = true # 캐릭터 시작 시 자동으로 스킬창 열기 (Lua에서 처리, 아래 ready() 참고) # 타일 폰트 (Consolas 권장) tile_font_crt_family = Consolas tile_font_stat_family = Consolas tile_font_msg_family = Consolas tile_font_lbl_family = Consolas # 플레이어 도트는 종족 스프라이트로 표시 tile_show_player_species = true # 위협도 색 표시 (노랑/빨강) tile_show_threat_levels = tough nasty # 애니메이션 속도 (기본 600 → 200으로 빠르게) view_delay = 200 # 휴식/탐험 관련 딜레이 rest_delay = -1 travel_delay = 10 explore_delay = -1 show_travel_trail = 1 # 완전 회복까지 자동 휴식 rest_wait_both = true rest_wait_percent = 100 # 자동전투(탭) HP 제한 # 캐스터/소환사 기준: 50% 아래로 떨어지면 탭 금지 autofight_stop = 50 ##### 유니크 & 위험 몬스터 경고 #################################### # 유니크 몬스터 등장 시 more 강제 force_more_message += .*(Agnes|Aizul|Amaemon|Antaeus|Arachne|Asmodeus|Azrael|Bai suzhen|Blork the orc|Boris|Cerebov|Crazy Yiuf|Dispater|Dissolution|Donald|Dowan|Duvessa|Edmund|the Enchantress|Ereshkigal|Erica|Erolcha|Eustachio|Fannar|Frances|Frederick|Gastronok|Geryon|Gloorx Vloq|Grinder|Grum|Grunn|Harold|Ignacio|Ijyb|Ilsuiw|Jessica|Jorgrun|Jory|Joseph|Josephina|Josephine|Khufu|Kirke|the Lernaean hydra|Lodul|Lom Lobon|Louise|Maggie|Mara|Margery|Maurice|Menkaure|Mlioglotl|Mennas|Mnoleg|Murray|Nergalle|Natasha|Nessos|Nikola|Pan|Parghit|Pikel|Polyphemus|Prince Ribbit|Psyche|Purgy|Robin|Roxanne|the royal jelly|Rupert|Saint Roka|the Serpent of Hell|Sigmund|Snorg|Sojobo|Sonja|Terence|Tiamat|Urug|Vashnia|Vv|Xtahua|Zenata).*comes? into view # 중후반 위험 몹 force_more_message += ((giant|floating|shining) eye|eye of draining).*into view force_more_message += (moth of wrath|ghost moth|torpor snail).*into view force_more_message += (guardian serpent|draconian shifter|convoker).*into view force_more_message += (flayed ghost|royal mummy|mummy priest|fiend|tzitzimitl).*into view force_more_message += (tormentor|curse toe|curse skull).*into view force_more_message += (hellion|hell sentinel|deep elf sorcerer).*into view force_more_message += (deep elf high priest|scorcher).*into view force_more_message += (ancient lich|orb of fire|executioner|juggernaut|shrike).*into view force_more_message += (wretched star|lurking horror).*into view force_more_message += (neqoxec|cacodemon|doom hound).*into view force_more_message += 27-headed.*comes? into view force_more_message += (radroach|entropy weaver|meliai).*into view force_more_message += (salamander tyrant|ironbound frostheart).*into view force_more_message += (walking crystal tome|walking divine tome|walking earthen tome|walking frostbound tome).*into view # 변신해서 위험 몹이 된 경우 force_more_message += changes into.*((giant|floating|shining) eye|eye of draining) force_more_message += changes into.*(moth of wrath|ghost moth|torpor snail) force_more_message += changes into.*(guardian serpent|draconian shifter|convoker) force_more_message += changes into.*(flayed ghost|royal mummy|mummy priest|fiend|tzitzimitl) force_more_message += changes into.*(tormentor|curse toe|curse skull) force_more_message += changes into.*(hellion|hell sentinel|deep elf sorcerer) force_more_message += changes into.*(deep elf high priest|scorcher) force_more_message += changes into.*(ancient lich|orb of fire|executioner|juggernaut|shrike) force_more_message += changes into.*(wretched star|lurking horror) force_more_message += changes into.*(neqoxec|cacodemon|doom hound) force_more_message += changes into.*(radroach|entropy weaver|meliai) force_more_message += changes into.*(salamander tyrant|ironbound frostheart) force_more_message += changes into.*(walking crystal tome|walking divine tome|walking earthen tome|walking frostbound tome) # 초반에 진짜 위험한 몬스터들 (오늘 널 죽인 애들 포함) force_more_message += (adder|worker ant|gnoll|ogre|two-headed ogre|iguana).*comes? into view force_more_message += (orc priest|orc wizard).*comes? into view force_more_message += (killer bee|hornet).*comes? into view force_more_message += (Duvessa|Dowan|Sigmund|Grinder|Crazy Yiuf|Robin|Ijyb).*comes? into view # 왜곡 무기 경고 + 화면 번쩍임 force_more_message += It is wielding.*of distortion force_more_message += She is wielding.*of distortion force_more_message += He is wielding.*of distortion force_more_message += wielding.* distortion.*comes? into view flash_screen_message += It is wielding.*of distortion flash_screen_message += She is wielding.*of distortion flash_screen_message += He is wielding.*of distortion flash_screen_message += wielding.* distortion.*comes? into view flash_screen_message += distortion.*comes? into view ##### 자동 줍기 설정 ################################################ # 기본 자동줍기: 골드, 스크롤, 포션, 책, 장신구, 완드, 지팡이, 기타 유물 autopickup = $?!:"/|} # 그물, 쿠라레는 항상 줍기 autopickup_exceptions += (atropa|dispersal) # 쓸모 없는 아이템은 줍지 않기 autopickup_exceptions ^= >useless_item # ===== 레어템 / 반지 / 부적 / 오브 자동 줍기 ===== { add_autopickup_func(function(it, name) local class = it.class(true) -- 1) 반지/아뮬렛 등 장신구는 전부 줍기 if class == "jewellery" then return true end -- 2) talisman(부적) 전부 줍기 if class == "talisman" then return true end -- 3) 완드 전부 줍기 if class == "wand" then return true end -- 4) 오브(armour 취급) + 레어 방어구만 줍기 if class == "armour" then local lname = string.lower(name or "") if string.find(lname, "orb of") then return true -- 예: orb of stardust 같은 것들 end if it.artefact or it.branded or it.ego then return true -- 브랜드/유물 방어구만 end return nil -- 나머지 갑옷은 기본 규칙(안 줍기) end } # ===== 여기까지 ===== ##### run/rest 중 쓸데없이 멈추지 않게 하는 설정 ################### # Jiyva 관련 메시지 runrest_ignore_message += Jiyva appreciates your sacrifice runrest_ignore_message += Jiyva gurgles merrily runrest_ignore_message += Jiyva says: Divide and consume runrest_ignore_message += You hear.*splatter runrest_ignore_message += You feel better runrest_ignore_message += You feel your power returning # Qazlal 보호 감소 메시지 runrest_ignore_message += Your protection from.*is fading runrest_ignore_message += You feel less protected from # Wereblood, Death Channel, 화폭 볼텍스 등 runrest_ignore_message += the wereblood boils in your veins runrest_ignore_message += A nearby plant withers and dies runrest_ignore_message += Your fire (vortex|vortices).*something runrest_ignore_message += something .* fire (vortex|vortices) runrest_ignore_message += Your primal bloodlust is almost over runrest_ignore_message += Your unholy channel expires # 아이템 더미로 이동 시 멈추지 않기 explore_stop -= greedy_visited_item_stack ##### Lua: 스펠 안정화 체크 + 첫 턴 자동 스킬창 #################### { -- 실패율 safe% 이하로 떨어지면 "스펠 안정화 끝!" 메시지 출력 local safe = 10 -- 10 → 실패율 10% 이하일 때 알림 local spellTable = {} local need_skills_opened = true local function checkSpellFailRate() for _, spellName in pairs(you.spells()) do local fail = spells.fail(spellName) if spellTable[spellName] == nil then spellTable[spellName] = 0 end if spellTable[spellName] == 0 and fail < safe then crawl.mpr(string.format("%s 스펠 안정화 끝!", spellName)) spellTable[spellName] = 1 end end end function ready() -- 새 게임 시작 첫 턴에 자동으로 m키 눌러서 스킬창 열기 if you.turns() == 0 and need_skills_opened then need_skills_opened = false crawl.sendkeys("m") end -- 매 턴 스펠 실패율 체크 checkSpellFailRate() end } ##### (선택) 한국 웹죽 전용 옵션들 ################################# # 웹죽이 lab_* 옵션을 지원할 때만 의미 있음. 필요하면 앞의 # 제거. $ lab_interface_translate = true # 인터페이스 한글화 $ lab_skill_window_translate = true # 기술창 한글화 $ lab_magic_window_translate = true # 마법창 한글화 $ lab_ability_window_translate = true # 능력창 한글화 $ lab_apply_font = true # 한글 고정폭 폰트 $ lab_sound_on = true # 사운드 자동 켜기 $ lab_transfer_chat_ingame = true # 채팅 리디렉트 $ lab_hide_chat_control = true # 채팅 컨트롤 숨기기 $ lab_maintain_session = true # 세션 유지 $ lab_disable_chat_clear = true # 방 이동 시 채팅 유지 export default class ConvenienceModule { static name = 'ConvenienceModule'; static version = '0.1'; static dependencies = ['IOHook', 'RCManager', 'CommandManager']; static description = '(Beta) This module provides convenience features.'; getRCConfig(rcfile) { const {RCManager} = DWEM.Modules; const showGoldStatus = RCManager.getRCOption(rcfile, 'show_gold_status', 'boolean', false); const disableClearChat = RCManager.getRCOption(rcfile, 'disable_clear_chat', 'boolean', false); const redirectChat = RCManager.getRCOption(rcfile, 'redirect_chat', 'boolean', false); const inputTimeoutMS = RCManager.getRCOption(rcfile, 'input_timeout_ms', 'float', 0); return { showGoldStatus, disableClearChat, redirectChat, inputTimeoutMS }; } onLoad() { const {IOHook, RCManager, CommandManager} = DWEM.Modules; /* const {SourceMapperRegistry: SMR} = DWEM; const {IOHook, RCManager} = DWEM.Modules; IOHook.send_message.before.addHandler('convenience-module', (msg, data) => { console.log(msg, data) this.lastSendTime = Date.now(); }); function injectSendKey() { send_keycode = function (code) { if(DWEM.Modules.ConvenienceModule.lastReceiveTime - DWEM.Modules.ConvenienceModule.lastSendTime > 15){ return; } DWEM.Modules.ConvenienceModule.lastSendTime = Date.now(); socket.send('{"msg":"key","keycode":' + code + '}'); } } const injectSendKeyMapper = SMR.getSourceMapper('BeforeReturnInjection', `!${injectSendKey.toString()}()`); SMR.add('client', injectSendKeyMapper); IOHook.handle_message.before.addHandler('convenience-module', (data) => { this.lastReceiveTime = Date.now(); console.log(this.lastReceiveTime - this.lastSendTime); }); */ RCManager.addHandlers('convenience-module', async (msg, data) => { if (msg === 'play') { let { showGoldStatus, disableClearChat, redirectChat } = this.getRCConfig(data.contents); this.disableClearChat = disableClearChat; this.showGoldStatus = showGoldStatus; this.redirectChat = redirectChat; if (this.showGoldStatus) { IOHook.handle_message.before.addHandler('convenience-module-show-gold-status', (data) => { if (data.msg === 'player') { if (this?.player?.god !== 'Gozag' && this?.player?.gold !== undefined && data.status) { data.status = [...data.status.filter(s => !s.isCustomStatus), { light: `Gold (${this.player.gold})`, text: 'gold', desc: 'The amount of gold you own.', col: 14, isCustomStatus: true }]; } } }); IOHook.handle_message.after.addHandler('convenience-module-show-gold-status', (data) => { if (data.gold !== undefined && this?.player?.status) { IOHook.handle_message({msg: 'player', status: this.player.status}); } }); } if (this.redirectChat) { IOHook.handle_message.after.addHandler('convenience-module-chat-redirect', (data) => { if (data.msg === 'chat' && data.content) { const container = document.createElement('div'); container.innerHTML = data.content; const sender = container.querySelector('.chat_sender').textContent; const message = container.querySelector('.chat_msg').textContent; IOHook.handle_message({ msg: 'msgs', messages: [{ 'text': ('' + sender + ': ' + '' + message + '') }] }); } }); } } else if (msg === 'go_lobby') { // TODO setTimeout(_ => { this.disableClearChat = this.showGoldStatus = this.redirectChat = false; },100); IOHook.handle_message.before.removeHandler('convenience-module-show-gold-status'); IOHook.handle_message.after.removeHandler('convenience-module-show-gold-status'); IOHook.handle_message.after.removeHandler('convenience-module-chat-redirect'); } }); const {SourceMapperRegistry: SMR} = DWEM; function injectDisableChatClear() { originalClear = clear const {ConvenienceModule} = DWEM.Modules; clear = function () { if (!ConvenienceModule.disableClearChat) { originalClear(); } } } const disableClearChatMapper = SMR.getSourceMapper('BeforeReturnInjection', `!${injectDisableChatClear.toString()}()`); SMR.add('chat', disableClearChatMapper, -1); function injectShowGoldStatus() { DWEM.Modules.ConvenienceModule.player = player; } const showGoldStatusMapper = SMR.getSourceMapper('BeforeReturnInjection', `!${injectShowGoldStatus.toString()}()`); SMR.add('./player', showGoldStatusMapper); IOHook.handle_message.after.addHandler('convenience-module', (data) => { if (!(this.autoReconnect && this.lastSessionData)) { return; } if (data.msg === 'go_lobby') { if (this.lastSessionData.msg === 'play') { location.hash = `play-${this.lastSessionData.game_id}`; } } else if (data.msg === 'lobby_entry' && data.username === this.lastSessionData.username) { location.hash = `watch-${this.lastSessionData.username}`; } }); IOHook.handle_message.before.addHandler('convenience-module', (data) => { if (data.msg === 'game_ended' && this.autoReconnect && this.lastSessionData) { return true; } }); IOHook.send_message.after.addHandler('convenience-module', (msg, data) => { if (msg === 'play') { this.lastSessionData = data; } else if (msg === 'watch') { this.lastSessionData = data; } }); CommandManager.addCommand('/arc', [], () => { this.autoReconnect = !this.autoReconnect; IOHook.handle_message({ msg: 'chat', content: `Auto reconnect mode is ${this.autoReconnect ? 'enabled' : 'disabled'}.` }); }, { module: ConvenienceModule.name, description: 'Toggle auto reconnect mode' }); } }