diff --git a/README.md b/README.md index 34e2a54..481f832 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ 环境:python 3.7, 32 bit;yys PC端 默认分辨率 (1136x640);win 10系统,屏幕(1920x1080),显示设置100%。 -1、该脚本可以用于阴阳师御魂、业原火、御灵等单刷或双人组队,适用于PC端; +1、该脚本可以用于阴阳师御魂、业原火、御灵、探索等单刷或双人组队,适用于PC端; 2、窗口现在可以完全后台,可以被遮挡,但是不能最小化,不能最小化,不能最小化; @@ -17,17 +17,17 @@ 4、在战斗过程中,该脚本会自动拒绝所有悬赏封印的邀请; -5、本人只测试过魂十,其他请自测; +5、本人只测试过魂十、探索,其他请自测; 6、如果60s程序没有任何操作,视为体力用光,为了保护加成,自动关闭YYS; 7、该脚本仅使用了画面找色,鼠标后台点击的函数,完全模拟人类玩家行为,没有使用任何内存读写函数。在敏感位置添加了均匀分布的随机时间漂移,和随机坐标漂移; # 目前进展 -目前已经完成了单刷、单人司机和单人打手的工作,其他工作待完成。 +目前已经完成了御魂的单刷、单人司机和单人打手、单人探索的工作,其他工作待完成。 # 注意事项 -1、点怪目前不可用,因为大蛇模型太大,挡住了点怪图标; +1、点怪目前不可用,因为有的模型太大,挡住了点怪图标; 2、当使用 Windows 7 系统时,需要调整系统的画面设置:把主题调为最丑最挫的那个。在 Windows 10 系统中,不需要调整系统画面设置; @@ -39,25 +39,25 @@ 第一步,准备yys -1、如果单刷,则进入御魂/业原火/御灵,备好式神,锁定阵容即可; +1、如果御魂单刷,则进入御魂/业原火/御灵主界面(就是有“挑战”按钮的页面),备好式神,锁定阵容; -2、如果单人司机,则进入组队页面,锁定阵容; +2、如果单人司机御魂,则进入组队页面,锁定阵容; -3、如果单人打手,则进入组队页面,锁定阵容。 +3、如果单人打手御魂,则进入组队页面,锁定阵容; + +4、如果单人探索,则进入需要的章节主界面(就是有“探索”按钮的页面),备好式神,锁定阵容; 第二步,开打 1、双击运行run.bat,会弹出设置界面,点击确认后再根据个人情况选择参数; -2、如果不想安装环境,可以访问下载最新已[编译](https://github.com/AcademicDog/onmyoji_bot/releases)版本,同时注意.exe文件和/img文件夹应该放在同一目录后再运行。 +2、如果不想安装环境,可以访问下载最新已[编译](https://github.com/AcademicDog/onmyoji_bot/releases)版本,该版本有图形界面,同时注意.exe文件和/img文件夹应该放在同一目录后再运行。 # 下一步计划 1、更新探索部分; 2、完善点怪操作; -3、正在考虑是否恢复原来的watchdog模块,便于程序出错时自动修正。 - # 更新说明 v1.0.0.0619--抛弃dll插件,用win32api,同时用图像识别替代简单找色。 @@ -73,6 +73,8 @@ v1.0.0.0625--增加了UI,目前在ui分支中。 v1.0.0.0707--根据[#4](https://github.com/AcademicDog/onmyoji_bot/issues/4),调整了UI设计。 +v1.0.0.0710--增加了单人探索的代码 + # 协议 (License) 该源代码使用了 [GPLv3](https://www.gnu.org/licenses/gpl-3.0.html) 开源协议。 diff --git a/Ui_onmyoji.py b/Ui_onmyoji.py index 980e5be..f6a8dc7 100644 --- a/Ui_onmyoji.py +++ b/Ui_onmyoji.py @@ -144,9 +144,10 @@ def retranslateUi(self, MainWindow): self.radioButton_2.setText(_translate("MainWindow", "单人司机")) self.radioButton_3.setText(_translate("MainWindow", "单人乘客")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("MainWindow", "御魂/御灵")) - self.plainTextEdit_2.setPlainText(_translate("MainWindow", "把狗粮队长放在最左边,然后开始。\n" + self.plainTextEdit_2.setPlainText(_translate("MainWindow", "把狗粮队长放在最左边,点开需要打的章节,然后开始。\n" "支持自动换狗粮,只打经验怪。\n" -"目前尚未完成调试!!!!!")) +"\n" +"目前尚未彻底完成调试!!!!!")) self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("MainWindow", "探索")) self.plainTextEdit.setPlainText(_translate("MainWindow", "网址:https://github.com/AcademicDog/onmyoji_bot\n" "作者:两情相悦--山城")) diff --git a/explore.py b/explore.py new file mode 100644 index 0000000..ad90890 --- /dev/null +++ b/explore.py @@ -0,0 +1,142 @@ +from fighter import * +from game_pos import * + + +class ExploreFight(Fighter): + def __init__(self): + # 初始化 + Fighter.__init__(self) + + def next_scene(self): + self.yys.mouse_drag_bg((1130, 118), (20, 118)) + # self.yys.mouse_drag_bg((1130,118),(20,118)) + + def check_exp_full(self): + ''' + 检查狗粮经验,并自动换狗粮 + ''' + # 狗粮经验判断 + gouliang1 = self.yys.find_game_img( + 'img\\MAN1.png', 1, (397, 287), (461, 349)) + gouliang2 = self.yys.find_game_img( + 'img\\MAN2.png', 1, (628, 333), (693, 394)) + + print(gouliang1) + print(gouliang2) + + # 如果都没满则退出 + if not gouliang1 and not gouliang2: + return + + # 开始换狗粮 + while True: + # 点击狗粮位置 + self.yys.mouse_click_bg( + TansuoPos.change_monster.pos, TansuoPos.change_monster.pos_end) + if self.yys.wait_game_img('img\\QUAN-BU.png', 3, False): + break + time.sleep(1) + + # 点击“全部”选项 + self.yys.mouse_click_bg(TansuoPos.quanbu_btn.pos, + TansuoPos.quanbu_btn.pos_end) + time.sleep(1) + + # 点击“N”卡 + self.yys.mouse_click_bg(TansuoPos.n_tab_btn.pos, + TansuoPos.n_tab_btn.pos_end) + time.sleep(1) + + # 更换狗粮 + if gouliang1: + self.yys.mouse_drag_bg((309, 520), (554, 315)) + if gouliang2: + time.sleep(1) + self.yys.mouse_drag_bg((191, 520), (187, 315)) + + def find_exp_moster(self): + ''' + 寻找经验怪 + return: 成功返回经验怪的攻打图标位置;失败返回-1 + ''' + # 查找经验图标 + exp_pos = self.yys.find_color( + ((2, 205), (1127, 545)), (140, 122, 44), 2) + if exp_pos == -1: + return -1 + + # 查找经验怪攻打图标位置 + find_pos = self.yys.find_game_img( + 'img\\FIGHT.png', 1, (exp_pos[0]-150, exp_pos[1]-250), (exp_pos[0]+150, exp_pos[1]-50)) + if not find_pos: + return -1 + + # 返回经验怪攻打图标位置 + fight_pos = ((find_pos[0]+exp_pos[0]-150),(find_pos[1]+exp_pos[1]-250)) + return fight_pos + + def fight_moster(self, mood1, mood2): + '''打经验怪''' + while True: + mood1.moodsleep() + # 查看是否进入探索界面 + self.yys.wait_game_img('img\\YING-BING.png') + self.log.writeinfo('In field') + + # 寻找经验怪,未找到则退出 + fight_pos = self.find_exp_moster() + if fight_pos == -1: + self.log.writeinfo('Back') + break + + # 攻击经验怪 + self.yys.mouse_click_bg(fight_pos) + if not self.yys.wait_game_img('img\\ZHUN-BEI.png', 3, False): + break + self.log.writeinfo('Already in battle') + time.sleep(1) + + # 检查狗粮经验 + self.check_exp_full() + + # 点击准备 + self.yys.mouse_click_bg( + TansuoPos.ready_btn.pos, TansuoPos.ready_btn.pos_end) + self.log.writeinfo('Clicked ready') + + # 检查是否打完 + self.check_end() + mood1.moodsleep() + + # 在战斗结算页面 + self.yys.mouse_click_bg(utilities.firstposition()) + start_time = time.time() + while time.time() - start_time <= 10: + if(self.yys.wait_game_img('img\\YING-BING.png', mood2.get1mood()/1000, False)): + break + + # 点击结算 + self.yys.mouse_click_bg(utilities.secondposition()) + + # 如果没有成功结算,切到主界面提醒玩家 + if time.time() - start_time > 10: + self.yys.activate_window() + + def start(self): + '''单人探索主循环''' + mood1 = utilities.Mood(1) + mood2 = utilities.Mood() + while True: + # 点击挑战按钮 + self.yys.wait_game_img('img\\TAN-SUO.png') + self.yys.mouse_click_bg((785, 456), (894, 502)) + self.fight_moster(mood1, mood2) + self.next_scene() + self.fight_moster(mood1, mood2) + while True: + self.yys.mouse_click_bg( + TansuoPos.quit_btn.pos, TansuoPos.quit_btn.pos_end) + if self.yys.wait_game_img('img\\QUE-REN.png', 3, False): + break + self.yys.mouse_click_bg( + TansuoPos.confirm_btn.pos, TansuoPos.confirm_btn.pos_end) diff --git a/fighter.py b/fighter.py index cf0b44b..b38c917 100644 --- a/fighter.py +++ b/fighter.py @@ -1,7 +1,7 @@ import game_ctl import utilities import logsystem - +import time class Fighter: diff --git a/game_ctl.py b/game_ctl.py index 1a3a3e1..b6309b8 100644 --- a/game_ctl.py +++ b/game_ctl.py @@ -85,7 +85,9 @@ def window_part_shot(self,pos1,pos2,file_name=None): memdc.DeleteDC() win32gui.ReleaseDC(self.hwnd, hwindc) win32gui.DeleteObject(bmp.GetHandle()) - return cv2.cvtColor(img, cv2.COLOR_BGRA2GRAY) + #cv2.imshow("image", cv2.cvtColor(img, cv2.COLOR_BGRA2BGR)) + #cv2.waitKey(0) + return cv2.cvtColor(img, cv2.COLOR_BGRA2BGR) def find_color(self,region,color,tolerance=0): """ @@ -125,13 +127,19 @@ def check_color(self,pos,color,tolerance=0): else: return False - def find_img(self,img_template_path): + def find_img(self, img_template_path, part=0, pos1=None, pos2=None): """ 查找图片 :param img_template_path: 欲查找的图片路径 + :param part=0: 是否全屏查找,0为否,其他为是 + :param pos1=None: 欲查找范围的左上角坐标 + :param pos2=None: 欲查找范围的右下角坐标 :return: (maxVal,maxLoc) maxVal为相关性,越接近1越好,maxLoc为得到的坐标 """ - img_src = self.window_full_shot() + if part == 1: + img_src = self.window_part_shot(pos1, pos2) + else: + img_src = self.window_full_shot() img_template=cv2.imread(img_template_path, cv2.IMREAD_COLOR) res = cv2.matchTemplate(img_src, img_template, cv2.TM_CCOEFF_NORMED) minVal, maxVal, minLoc, maxLoc = cv2.minMaxLoc(res) @@ -296,16 +304,19 @@ def rejectbounty(self): return True return False - def find_game_img(self, img_path): + def find_game_img(self, img_path, part=0, pos1=None, pos2=None): ''' 查找图片 :param img_path: 查找路径 + :param part=0: 是否全屏查找,0为否,其他为是 + :param pos1=None: 欲查找范围的左上角坐标 + :param pos2=None: 欲查找范围的右下角坐标 :param return: 查找成功返回True,否则返回False ''' self.rejectbounty() - maxVal, maxLoc = self.find_img(img_path) + maxVal, maxLoc = self.find_img(img_path, part, pos1, pos2) if maxVal>0.97: - return True + return maxLoc else: return False diff --git a/game_pos.py b/game_pos.py new file mode 100644 index 0000000..850d2bb --- /dev/null +++ b/game_pos.py @@ -0,0 +1,16 @@ +class GamePos(): + def __init__(self,pos,pos_end=None): + self.pos=pos + self.pos_end=pos_end + +class TansuoPos(): + last_chapter=GamePos((934,493),(1108,572)) #列表最后一章 + tansuo_btn=GamePos((787,458),(890,500)) #探索按钮 + ready_btn=GamePos((1000,460),(1069,513)) #准备按钮 + fight_quit=GamePos((1055,462),(1121,518)) #退出战斗 + quit_btn=GamePos((32,45),(58,64)) #退出副本 + confirm_btn=GamePos((636,350),(739,370)) #退出确认按钮 + change_monster=GamePos((427,419),(457,452)) #切换狗粮点击区域 + quanbu_btn=GamePos((37,574),(80,604)) #“全部”按钮 + n_tab_btn=GamePos((142,288),(164,312)) #n卡标签 + quit_change_monster=GamePos((19,17),(43,38)) #退出换狗粮界面 \ No newline at end of file diff --git a/img/FIGHT.png b/img/FIGHT.png new file mode 100644 index 0000000..ff1cd6d Binary files /dev/null and b/img/FIGHT.png differ diff --git a/img/MAN1.png b/img/MAN1.png new file mode 100644 index 0000000..163f46d Binary files /dev/null and b/img/MAN1.png differ diff --git a/img/MAN2.png b/img/MAN2.png new file mode 100644 index 0000000..9f1c109 Binary files /dev/null and b/img/MAN2.png differ diff --git a/img/QUAN-BU.png b/img/QUAN-BU.png new file mode 100644 index 0000000..979562e Binary files /dev/null and b/img/QUAN-BU.png differ diff --git a/img/QUE-REN.png b/img/QUE-REN.png new file mode 100644 index 0000000..aea0a1e Binary files /dev/null and b/img/QUE-REN.png differ diff --git a/img/TAN-SUO.png b/img/TAN-SUO.png new file mode 100644 index 0000000..151c1e5 Binary files /dev/null and b/img/TAN-SUO.png differ diff --git a/img/YING-BING.png b/img/YING-BING.png new file mode 100644 index 0000000..e4eac90 Binary files /dev/null and b/img/YING-BING.png differ diff --git a/img/ZHUN-BEI.png b/img/ZHUN-BEI.png new file mode 100644 index 0000000..432af2f Binary files /dev/null and b/img/ZHUN-BEI.png differ diff --git a/onmyoji.py b/onmyoji.py index a02a5f1..4b27831 100644 --- a/onmyoji.py +++ b/onmyoji.py @@ -4,6 +4,7 @@ import ctypes import threading +import explore import fighter_driver import fighter_passenger import logsystem @@ -18,18 +19,23 @@ log = logsystem.WriteLog() def init(): + global section global mode global emyc global done try: - # 模式选择 - mode=int(input('\n选择游戏模式(Ctrl-C跳过并单刷):\n0-单刷\n2-组队司机\n3-组队打手\n')) - if(mode==1): - log.writewarning('未开发,告辞!') - os._exit(0) - elif(mode != 2 and mode != 0 and mode != 3): - mode=0 + # 选择打什么 + section = int(input('\n选择刷什么(Ctrl-C跳过并单刷御魂:\n0-御魂\n1-探索\n')) + log.writeinfo('Section = %d', section) + if section == 0: + # 御魂模式选择 + mode=int(input('\n选择游戏模式(Ctrl-C跳过并单刷):\n0-单刷\n2-组队司机\n3-组队打手\n')) + if(mode==1): + log.writewarning('未开发,告辞!') + os._exit(0) + elif(mode != 2 and mode != 0 and mode != 3): + mode=0 # 点怪设置 # emyc=int(input('\n是否点怪?\n0-不点怪\n1-点中间怪\n2-点右边怪\n')) @@ -40,10 +46,11 @@ def init(): # done=int(input('\n结束后如何处理?\n0-退出\n1-关机\n')) # if not ((done == 0) or (done == 1)): # done = 0 - log.writeinfo('Mode = %d',mode) + log.writeinfo('Mode = %d',mode) # log.writeinfo('Emyc = %d',emyc) # log.writeinfo('Postoperation = %d',done) except: + section = 0 mode=0 emyc=0 done=1 @@ -72,6 +79,12 @@ def yuhun(): # 乘客 fight = fighter_passenger.FighterPassenger() fight.start() + +def tansuo(): + '''探索战斗''' + fight = explore.ExploreFight() + print(1) + fight.start() if __name__ == "__main__": log.writeinfo('python version: %s', sys.version) @@ -85,8 +98,13 @@ def yuhun(): # 设置战斗参数 init() - # 开始战斗 - yuhun() + # 开始战斗 + print('da') + print(section) + if section == 0: + yuhun() + elif section == 1: + tansuo() else: ctypes.windll.shell32.ShellExecuteW(None, "runas", sys.executable, __file__, None, 1) diff --git a/ui.py b/ui.py index 849a176..653c889 100644 --- a/ui.py +++ b/ui.py @@ -25,17 +25,24 @@ def __init__(self, parent = None): logger.addHandler(h) def start_onmyoji(self): - if mode == 0: - # 单刷 - fight = single_fight.SingleFight() + section = self.ui.tabWidget.currentIndex() + if section == 0: + # 御魂 + if mode == 0: + # 单刷 + fight = single_fight.SingleFight() - if mode == 2: - # 司机 - fight = fighter_driver.DriverFighter() + if mode == 2: + # 司机 + fight = fighter_driver.DriverFighter() - if mode == 3: - # 乘客 - fight = fighter_passenger.FighterPassenger() + if mode == 3: + # 乘客 + fight = fighter_passenger.FighterPassenger() + + elif section == 1: + # 探索 + fight = explore.ExploreFight() self.task = threading.Thread(target = fight.start) self.task.start() @@ -56,6 +63,8 @@ def stop_onmyoji(self): logging.info('Quitting!') os._exit(0) + print(self.ui.tabWidget.currentIndex()) + if __name__=="__main__": try: @@ -63,6 +72,8 @@ def stop_onmyoji(self): if is_admin(): global mode mode = 0 + global section + section = 0 # 设置战斗参数 app = QApplication(sys.argv)