├── .gitignore ├── img ├── goods │ ├── box.png │ ├── btn.png │ ├── latch.png │ ├── logo1.png │ ├── logo2.png │ ├── option.png │ ├── get_btn.png │ ├── open_btn.png │ ├── card_btn1.png │ ├── card_btn2.png │ ├── card_btn3.png │ ├── resumption.png │ └── resumption_option.png └── monster │ ├── 10.png │ ├── 云闪之鳞.png │ ├── 哀声鸷.png │ ├── 无冠者.png │ ├── 无常凶鹭.png │ ├── 朔雷之鳞.png │ ├── 燎照之骑.png │ ├── 聚械机偶.png │ ├── 辉萤军势.png │ ├── 飞廉之猩.png │ └── 鸣钟之龟.png ├── requirements.txt ├── config.yaml ├── README.md ├── main.spec ├── LICENSE ├── akt.py ├── auto.py ├── keyInput.py ├── main.py └── localize.py /.gitignore: -------------------------------------------------------------------------------- 1 | /yolo 2 | record.py 3 | /build 4 | /dist 5 | __pycache__ 6 | .vscode 7 | /test -------------------------------------------------------------------------------- /img/goods/box.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/box.png -------------------------------------------------------------------------------- /img/goods/btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/btn.png -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/requirements.txt -------------------------------------------------------------------------------- /img/goods/latch.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/latch.png -------------------------------------------------------------------------------- /img/goods/logo1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/logo1.png -------------------------------------------------------------------------------- /img/goods/logo2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/logo2.png -------------------------------------------------------------------------------- /img/goods/option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/option.png -------------------------------------------------------------------------------- /img/monster/10.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/10.png -------------------------------------------------------------------------------- /img/monster/云闪之鳞.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/云闪之鳞.png -------------------------------------------------------------------------------- /img/monster/哀声鸷.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/哀声鸷.png -------------------------------------------------------------------------------- /img/monster/无冠者.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/无冠者.png -------------------------------------------------------------------------------- /img/monster/无常凶鹭.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/无常凶鹭.png -------------------------------------------------------------------------------- /img/monster/朔雷之鳞.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/朔雷之鳞.png -------------------------------------------------------------------------------- /img/monster/燎照之骑.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/燎照之骑.png -------------------------------------------------------------------------------- /img/monster/聚械机偶.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/聚械机偶.png -------------------------------------------------------------------------------- /img/monster/辉萤军势.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/辉萤军势.png -------------------------------------------------------------------------------- /img/monster/飞廉之猩.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/飞廉之猩.png -------------------------------------------------------------------------------- /img/monster/鸣钟之龟.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/monster/鸣钟之龟.png -------------------------------------------------------------------------------- /img/goods/get_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/get_btn.png -------------------------------------------------------------------------------- /img/goods/open_btn.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/open_btn.png -------------------------------------------------------------------------------- /img/goods/card_btn1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/card_btn1.png -------------------------------------------------------------------------------- /img/goods/card_btn2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/card_btn2.png -------------------------------------------------------------------------------- /img/goods/card_btn3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/card_btn3.png -------------------------------------------------------------------------------- /img/goods/resumption.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/resumption.png -------------------------------------------------------------------------------- /img/goods/resumption_option.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/linyys/Wuthering_Waves_Auto/HEAD/img/goods/resumption_option.png -------------------------------------------------------------------------------- /config.yaml: -------------------------------------------------------------------------------- 1 | boss: 2 | - 鸣钟之龟 3 | - 辉萤军势 4 | - 燎照之骑 5 | akt: 6 | - shift 7 | - r 8 | - e_akt 9 | - p 10 | - change -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Wuthering_Waves_Auto 2 | 3 | 开发中~~不稳定~~ 4 | 5 | #### 注意事项: 6 | 7 | 2、鼠标移动到左上角可以退出 8 | 9 | 3、目前只适配了2k分辨率 10 | 11 | ### python版本: 12 | 13 | `Python 3.8.19` 14 | 15 | ### 开始使用: 16 | 1、安装Anaconda 17 | 18 | 2、安装库 19 | 20 | `conda install --yes --file requirements.txt` 21 | 22 | 3、启动 23 | 24 | `python main.py` 25 | 26 | ### 正在解决的问题: 27 | 28 | - 适配1080p 29 | 30 | ### 正在做的: 31 | 32 | - 训练yolov8中,自动识别声骸拾取 33 | - 添加角色攻击配置 34 | -------------------------------------------------------------------------------- /main.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | 4 | a = Analysis( 5 | ['main.py', 'akt.py', 'auto.py', 'keyInput.py', 'localize.py'], 6 | pathex=[], 7 | binaries=[], 8 | datas=[], 9 | hiddenimports=[], 10 | hookspath=[], 11 | hooksconfig={}, 12 | runtime_hooks=[], 13 | excludes=[], 14 | noarchive=False, 15 | optimize=0, 16 | ) 17 | pyz = PYZ(a.pure) 18 | 19 | exe = EXE( 20 | pyz, 21 | a.scripts, 22 | a.binaries, 23 | a.datas, 24 | [], 25 | name='main', 26 | debug=False, 27 | bootloader_ignore_signals=False, 28 | strip=False, 29 | upx=True, 30 | upx_exclude=[], 31 | runtime_tmpdir=None, 32 | console=False, 33 | disable_windowed_traceback=False, 34 | argv_emulation=False, 35 | target_arch=None, 36 | codesign_identity=None, 37 | entitlements_file=None, 38 | ) 39 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 l_rain 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /akt.py: -------------------------------------------------------------------------------- 1 | import pyautogui as pg 2 | import time 3 | import yaml 4 | 5 | def p(): 6 | pg.click(clicks=6, interval=0.3, duration=0, button="left") 7 | 8 | 9 | def long_p(): 10 | pg.mouseDown(button="left") 11 | time.sleep(1) 12 | pg.mouseUp(button="left") 13 | 14 | 15 | def e_akt(): 16 | pg.press("e", presses=1, interval=0.3) 17 | 18 | 19 | def r(): 20 | pg.press("r", presses=1, interval=0.3) 21 | 22 | 23 | def shift(): 24 | pg.keyDown("w") 25 | pg.click(clicks=1, interval=0.2, duration=0, button="right") 26 | time.sleep(0.2) 27 | pg.keyUp("w") 28 | 29 | 30 | def q(): 31 | pg.keyDown("q") 32 | pg.keyUp("q") 33 | 34 | 35 | def latch(): 36 | pg.click(clicks=1, interval=0.3, duration=0, button="middle") 37 | 38 | 39 | who = 1 40 | def change(): 41 | global who 42 | if who >= 3: 43 | who = 1 44 | pg.press(str(who), presses=1, interval=0.3) 45 | who += 1 46 | 47 | 48 | def read_config(): 49 | print(akt_list) 50 | 51 | 52 | # with open('./config.yaml', 'r', encoding='utf-8') as f: 53 | # result = yaml.load(f.read(), Loader=yaml.FullLoader) 54 | akt_index = 0 55 | # akt_list = result['akt'] 56 | akt_list = [shift, e_akt, p, r, p, q,change] 57 | 58 | 59 | def akt_main(): 60 | global akt_index 61 | global akt_list 62 | if akt_index >= len(akt_list): 63 | akt_index = 0 64 | fn = akt_list[akt_index] 65 | fn() 66 | # exec("{}".format(fn)) 67 | akt_index += 1 68 | -------------------------------------------------------------------------------- /auto.py: -------------------------------------------------------------------------------- 1 | import keyInput as ki 2 | import akt 3 | import localize 4 | import time 5 | 6 | 7 | def change_map(): 8 | ki.open_map() 9 | ki.scroll(-60) 10 | ki.scroll(15) 11 | ki.open_map() 12 | 13 | def search_resumption(): 14 | while True: 15 | tl, br, res = localize.resumption() 16 | if res > 0.98: 17 | ki.move_mouse_and_click(tl, br) 18 | break 19 | else: 20 | ki.open_map() 21 | ki.open_map() 22 | 23 | timeout = 90 24 | def go(monster_uid): 25 | time.sleep(6) 26 | ki.open_card() 27 | if monster_uid == "鸣钟之龟": 28 | localize.monster_list2() 29 | else: 30 | localize.monster_list1() 31 | tl, br = localize.monster(monster_uid) 32 | ki.move_mouse_and_click(tl, br) 33 | time.sleep(2) 34 | ki.esc() 35 | ki.move_mouse_and_click(localize.screen_width / 2, localize.screen_height / 2) 36 | tl, br, _ = localize.option() 37 | ki.move_mouse_and_click(tl, br) 38 | tl, br, _ = localize.btn() 39 | ki.move_mouse_and_click(tl, br) 40 | return 41 | if monster_uid == "鸣钟之龟": 42 | time.sleep(10) 43 | elif monster_uid == "无冠者": 44 | ki.search(localize.is_open) 45 | time.sleep(9) 46 | akt.p() 47 | time.sleep(0.6) 48 | akt.latch() 49 | now_time = time.time() 50 | print(localize.is_dead()) 51 | while localize.is_dead(): 52 | if time.time() - now_time > timeout: 53 | break 54 | akt.akt_main() 55 | time.sleep(1) 56 | if localize.is_get(): 57 | ki.f() 58 | else: 59 | ki.search(localize.is_get) 60 | ki.open_map() 61 | search_resumption() 62 | tl, br, res = localize.resumption_option() 63 | if res > 0.95: 64 | ki.move_mouse_and_click(tl, br) 65 | tl, br, _ = localize.btn() 66 | ki.move_mouse_and_click(tl, br) 67 | -------------------------------------------------------------------------------- /keyInput.py: -------------------------------------------------------------------------------- 1 | import pyautogui as pg 2 | import time 3 | # from pynput import keyboard 4 | 5 | def scroll(num): 6 | scroll_count = 0 7 | while scroll_count < 67: 8 | pg.scroll(num) 9 | scroll_count += 1 10 | time.sleep(0.3) 11 | 12 | 13 | def mouse_down(): 14 | pg.moveTo(1200, 1000, duration=0.55) 15 | scroll(-50) 16 | 17 | def move_mouse_and_click(top_left, bottom_right): 18 | print(top_left, bottom_right) 19 | pg.moveTo(top_left, bottom_right, duration=0.5) 20 | click() 21 | time.sleep(0.4) 22 | 23 | def click(): 24 | pg.click(clicks=1, interval=0, duration=0, button="left") 25 | time.sleep(0.4) 26 | 27 | 28 | def open_card(): 29 | pg.press(keys="F2", presses=1, interval=0.3) 30 | time.sleep(0.4) 31 | 32 | 33 | def esc(): 34 | pg.press(keys="esc", presses=1, interval=0.3) 35 | time.sleep(0.4) 36 | 37 | def f(): 38 | pg.press(keys="f", presses=1, interval=0.3) 39 | time.sleep(0.4) 40 | 41 | def open_map(): 42 | pg.press(keys="m", presses=1, interval=0.3) 43 | time.sleep(0.4) 44 | 45 | def w(s): 46 | pg.keyDown('w') 47 | time.sleep(s) 48 | pg.keyUp('w') 49 | time.sleep(0.4) 50 | 51 | def d(s): 52 | pg.keyDown('d') 53 | time.sleep(s) 54 | pg.keyUp('d') 55 | time.sleep(0.4) 56 | 57 | def s(s): 58 | pg.keyDown('s') 59 | time.sleep(s) 60 | pg.keyUp('s') 61 | time.sleep(0.4) 62 | 63 | def a(s): 64 | pg.keyDown('a') 65 | time.sleep(s) 66 | pg.keyUp('a') 67 | time.sleep(0.4) 68 | 69 | 70 | def search(fn): 71 | s(1) 72 | if (fn()): 73 | f() 74 | return 75 | d(1) 76 | if (fn()): 77 | f() 78 | return 79 | for item in [1,2]: 80 | w(item) 81 | if (fn()): 82 | f() 83 | return 84 | a(item) 85 | if (fn()): 86 | f() 87 | return 88 | s(item) 89 | if (fn()): 90 | f() 91 | return 92 | d(item) 93 | if (fn()): 94 | f() 95 | return 96 | 97 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import time 2 | import auto 3 | import sys 4 | import multiprocessing 5 | from PyQt5.QtWidgets import QApplication, QCheckBox,QHBoxLayout, QWidget,QListWidgetItem,QListWidget, QPushButton 6 | checked_monster = [] 7 | def start(args): 8 | time.sleep(5) 9 | # time.sleep(3) 10 | auto.change_map() 11 | while True: 12 | for item in args: 13 | auto.go(item) 14 | 15 | monster_list1 = ['鸣钟之龟', '辉萤军势', '燎照之骑', '哀声鸷', '无冠者','无常凶鹭', '飞廉之猩', '聚械机偶', '朔雷之鳞', '云闪之鳞'] 16 | class Winform(QWidget): 17 | def __init__(self,parent=None): 18 | super(Winform,self).__init__(parent) 19 | self.setWindowTitle("mc-script") 20 | self.resize(330, 150) 21 | # 垂直布局按照从上到下的顺序进行添加按钮部件。 22 | hlayout = QHBoxLayout() 23 | list_widget = QListWidget() 24 | for item in monster_list1: 25 | checkBox = QCheckBox(str(item)) 26 | checkBox.stateChanged.connect(lambda checked, cb=checkBox: btnState(checked,cb)) 27 | list_item = QListWidgetItem() 28 | list_widget.addItem(list_item) 29 | list_widget.setItemWidget(list_item, checkBox) 30 | hlayout.addWidget(list_widget) 31 | button1 = QPushButton('开始', self) 32 | button1.clicked.connect(clickButton) 33 | hlayout.addWidget(button1) 34 | self.setLayout(hlayout) 35 | 36 | def closeEvent(self,event): 37 | p.terminate() 38 | p.join() 39 | sys.exit(app.exec_()) 40 | 41 | def btnState(checked, cb): 42 | if (cb.isChecked()): 43 | if(len(checked_monster) >= 3): 44 | cb.setChecked(False) 45 | return 46 | else: 47 | checked_monster.append(cb.text()) 48 | else: 49 | if cb.text() in checked_monster: 50 | checked_monster.remove(cb.text()) 51 | 52 | p = multiprocessing.Process(target=start, args=[checked_monster]) 53 | def clickButton(): 54 | p.start() 55 | 56 | def close(): 57 | p.terminate() 58 | p.join() 59 | 60 | 61 | if __name__ == '__main__': 62 | # ------window------ 63 | multiprocessing.freeze_support() 64 | app = QApplication(sys.argv) 65 | form = Winform() 66 | form.show() 67 | sys.exit(app.exec_()) 68 | # start() -------------------------------------------------------------------------------- /localize.py: -------------------------------------------------------------------------------- 1 | import cv2 2 | import numpy as np 3 | import pyautogui as pg 4 | import keyInput as ki 5 | screen_width, screen_height = pg.size() 6 | def read_img(src): 7 | img = cv2.imdecode(np.fromfile(src, dtype=np.uint8), cv2.IMREAD_UNCHANGED) 8 | # img = cv2.imread(src, cv2.IMREAD_UNCHANGED) 9 | # tmpl = cv2.cvtColor(img, cv2.IMREAD_UNCHANGED) 10 | alpha = img[:, :, 3] 11 | tmpl = cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY) 12 | return img, alpha, tmpl 13 | 14 | 15 | def get_local(img, alpha, tmpl): 16 | screenshot = pg.screenshot() 17 | s_img = np.array(screenshot) 18 | gray = cv2.cvtColor(s_img, cv2.COLOR_BGR2GRAY) 19 | result = cv2.matchTemplate(gray, tmpl, cv2.TM_CCORR_NORMED, mask=alpha) 20 | print(result.max()) 21 | min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result) 22 | top_left = max_loc 23 | h, w = img.shape[:2] 24 | bottom_right = top_left[0] + w, top_left[1] + h 25 | return top_left[0] + 7, bottom_right[1] - 7, result.max() 26 | 27 | tp_img, tp_alpha, tp_tmpl = read_img("./img/goods/logo2.png") 28 | def tp(): 29 | return get_local(tp_img, tp_alpha, tp_tmpl) 30 | 31 | 32 | btn_img, btn_alpha, btn_tmpl = read_img("./img/goods/btn.png") 33 | def btn(): 34 | return get_local(btn_img, btn_alpha, btn_tmpl) 35 | 36 | 37 | option_img, option_alpha, option_tmpl = read_img("./img/goods/option.png") 38 | def option(): 39 | return get_local(option_img, option_alpha, option_tmpl) 40 | 41 | 42 | card_btn_l_img, card_btn_l_alpha, card_btn_l_tmpl = read_img("./img/goods/card_btn1.png") 43 | card_btn_m_img, card_btn_m_alpha, card_btn_m_tmpl = read_img("./img/goods/card_btn2.png") 44 | def monster_list1(): 45 | l_tl, l_br, _ = get_local(card_btn_l_img, card_btn_l_alpha, card_btn_l_tmpl) 46 | ki.move_mouse_and_click(l_tl, l_br) 47 | m_tl, m_br, _ = get_local(card_btn_m_img, card_btn_m_alpha, card_btn_m_tmpl) 48 | ki.move_mouse_and_click(m_tl, m_br) 49 | 50 | 51 | card_btn_b_img, card_btn_b_alpha, card_btn_b_tmpl = read_img("./img/goods/card_btn3.png") 52 | def monster_list2(): 53 | l_tl, l_br, _ = get_local(card_btn_l_img, card_btn_l_alpha, card_btn_l_tmpl) 54 | ki.move_mouse_and_click(l_tl, l_br) 55 | b_tl, b_br, _ = get_local(card_btn_b_img, card_btn_b_alpha, card_btn_b_tmpl) 56 | ki.move_mouse_and_click(b_tl, b_br) 57 | 58 | def monster(name): 59 | print("./img/monster/" + name + ".png") 60 | gw_img, gw_alpha, gw_tmpl = read_img("./img/monster/" + name + ".png") 61 | tl, br, res = get_local(gw_img, gw_alpha, gw_tmpl) 62 | if res < 0.98: 63 | ki.mouse_down() 64 | return monster(name) 65 | # if(screen_width == 1920): 66 | # return tl + (1200 * 0.75), br - (100 * 0.75) 67 | # else: 68 | return tl + 1200, br - 100 69 | 70 | resumption_img, resumption__alpha, resumption_tmpl = read_img("./img/goods/resumption.png") 71 | def resumption(): 72 | return get_local(resumption_img, resumption__alpha, resumption_tmpl) 73 | 74 | 75 | resumption_p_img, resumption_p__alpha, resumption_p_tmpl = read_img( 76 | "./img/goods/resumption_option.png" 77 | ) 78 | def resumption_option(): 79 | return get_local(resumption_p_img, resumption_p__alpha, resumption_p_tmpl) 80 | 81 | get_img, get__alpha, get_tmpl = read_img("./img/goods/get_btn.png") 82 | def is_get(): 83 | tl, br, res = get_local(get_img, get__alpha, get_tmpl) 84 | return (res > 0.95) 85 | 86 | open_img, open_alpha, open_tmpl = read_img("./img/goods/open_btn.png") 87 | def is_open(): 88 | tl, br, res = get_local(open_img, open_alpha, open_tmpl) 89 | return res > 0.95 90 | 91 | box_img, box__alpha, box_tmpl = read_img("./img/goods/box.png") 92 | def is_dead(): 93 | tl, br, res = get_local(box_img, box__alpha, box_tmpl) 94 | return not(res > 0.95) --------------------------------------------------------------------------------