diff --git a/CHANGELOG.MD b/CHANGELOG.MD index c3d14bb..03e6004 100644 --- a/CHANGELOG.MD +++ b/CHANGELOG.MD @@ -2,6 +2,10 @@ ## 最近更新 +### 新功能 + +- 新增觉醒副本 + ### 优化 - 移除更新升级过程中的`任意键` diff --git a/src/package/__init__.py b/src/package/__init__.py index d0b4633..4eb4f20 100644 --- a/src/package/__init__.py +++ b/src/package/__init__.py @@ -1,15 +1,61 @@ -from . import ( - yuhun, # 1 - yongshengzhihai, # 2 - yeyuanhuo, # 3 - yuling, # 4 - jiejietupo, # 5&6 - daoguantupo, # 7 - zhaohuan, # 8 - baiguiyexing, # 9 - huodong, # 10 - rilun, # 11 - tansuo, # 12 - qiling, #13 - xuanshangfengyin -) +from .baiguiyexing import BaiGuiYeXing +from .daoguantupo import DaoGuanTuPo +from .huodong import HuoDong +from .jiejietupo import JieJieTuPo, JieJieTuPoGeRen, JieJieTuPoYinYangLiao +from .juexing import JueXing +from .qiling import QiLing +from .rilun import RiLun +from .tansuo import TanSuo +from .xuanshangfengyin import XuanShangFengYin, task_xuanshangfengyin +from .yeyuanhuo import YeYuanHuo +from .yongshengzhihai import YongShengZhiHai, YongShengZhiHaiTeam +from .yuhun import YuHun, YuHunSingle, YuHunTeam +from .yuling import YuLing +from .zhaohuan import ZhaoHuan +from .utils import FightResource + +__all__ = [ + "FightResource", + "BaiGuiYeXing", + "DaoGuanTuPo", + "HuoDong", + # "JieJieTuPo", + "JieJieTuPoGeRen", + "JieJieTuPoYinYangLiao", + "JueXing", + "QiLing", + "RiLun", + "TanSuo", + # "XuanShangFengYin", + "task_xuanshangfengyin", + "YeYuanHuo", + "YuLing", + "YongShengZhiHai", + "YongShengZhiHaiTeam", + "YuHun", + "YuHunSingle", + "YuHunTeam", + "ZhaoHuan", + "get_package_resource_list", +] + + +def get_package_resource_list(): + print("get_package_resource_list") + return [ + FightResource, + BaiGuiYeXing, + DaoGuanTuPo, + HuoDong, + JieJieTuPo, + JueXing, + QiLing, + RiLun, + TanSuo, + XuanShangFengYin, + YeYuanHuo, + YongShengZhiHai, + YuHun, + YuLing, + ZhaoHuan + ] diff --git a/src/package/baiguiyexing.py b/src/package/baiguiyexing.py index f3e1707..04c3af0 100644 --- a/src/package/baiguiyexing.py +++ b/src/package/baiguiyexing.py @@ -28,6 +28,7 @@ class BaiGuiYeXing(Package): "kaishi", # 开始 "baiguiqiyueshu", # 百鬼契约书 ] + description = "仅适用于清票,无法指定鬼王" @log_function_call def __init__(self, n: int = 0) -> None: diff --git a/src/package/daoguantupo.py b/src/package/daoguantupo.py index 2610244..9797718 100644 --- a/src/package/daoguantupo.py +++ b/src/package/daoguantupo.py @@ -34,6 +34,7 @@ class DaoGuanTuPo(Package): "title", # 标题 "zhanbao", # 战报 ] + description = "目前仅支持正在进行中的道馆突破,无法实现跳转道馆场景" @log_function_call def __init__(self, flag_guanzhan: bool = False) -> None: @@ -180,7 +181,7 @@ def run(self): f"{RESOURCE_FIGHT_PATH}/ready_new", f"{RESOURCE_FIGHT_PATH}/victory", f"{RESOURCE_FIGHT_PATH}/fail", - f"{RESOURCE_FIGHT_PATH}/finish" + f"{RESOURCE_FIGHT_PATH}/finish", ] scene, coor = self.check_scene_multiple_once() if scene is None: @@ -194,11 +195,12 @@ def run(self): click(coor) self.n += 1 logger.num(str(self.n)) - random_sleep(1, 2) + random_sleep() case "victory": - random_sleep(1, 2) + random_sleep() case "finish": - self.ensure_finish() + finish_random_left_right() + break case "fail": logger.ui("失败,需要手动处理", "warn") break diff --git a/src/package/huodong.py b/src/package/huodong.py index 89743db..28bc3da 100644 --- a/src/package/huodong.py +++ b/src/package/huodong.py @@ -29,8 +29,8 @@ class HuoDong(Package): "title", "start", ] - description = """适配活动「演武练习」 -可替换 resource/huodong 下的素材""" + description = "未适配活动「超鬼王」\ + 可自行替换 resource/huodong 下的素材" @log_function_call def __init__(self, n: int = 0) -> None: diff --git a/src/package/jiejietupo.py b/src/package/jiejietupo.py index ad3e4d5..43cfef8 100644 --- a/src/package/jiejietupo.py +++ b/src/package/jiejietupo.py @@ -177,6 +177,7 @@ class JieJieTuPoGeRen(JieJieTuPo): 间隔高30 """ scene_name = "个人突破" + description = "默认3胜刷新,上限30" tupo_geren_x = { 1: 215, 2: 515, diff --git a/src/package/juexing.py b/src/package/juexing.py new file mode 100644 index 0000000..1e5eb8b --- /dev/null +++ b/src/package/juexing.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +# juexing.py +"""觉醒副本""" + +from ..utils.decorator import log_function_call +from ..utils.event import event_thread +from ..utils.function import ( + RESOURCE_FIGHT_PATH, + check_click, + check_scene_multiple_once, + click, + finish_random_left_right, + random_sleep +) +from ..utils.log import logger +from .utils import Package + + +class JueXing(Package): + """觉醒副本""" + scene_name = "觉醒副本" + resource_path = "juexing" + resource_list = [ + "title", # 标题 + ] + description = "单人觉醒副本" + + @log_function_call + def __init__(self, n: int = 0) -> None: + super().__init__(n) + + @log_function_call + def start(self): + """挑战开始""" + check_click(f"{RESOURCE_FIGHT_PATH}/start_single") + + def run(self): + self.current_resource_list = [ + f"{self.resource_path}/title", + f"{RESOURCE_FIGHT_PATH}/start_single", + f"{RESOURCE_FIGHT_PATH}/finish", + f"{RESOURCE_FIGHT_PATH}/fail", + f"{RESOURCE_FIGHT_PATH}/victory", + ] + _flag_title_msg: bool = True + logger.num(f"0/{self.max}") + self.log_current_scene_list() + + while self.n < self.max: + if event_thread.is_set(): + return + scene, coor = check_scene_multiple_once(self.current_resource_list) + if scene is None: + continue + scene = self.scene_handle(scene) + + match scene: + case "title": + logger.scene(self.scene_name) + _flag_title_msg = False + self.start() + case "start_single": + click(coor) + case "fail": + logger.ui("失败,需要手动处理", "warn") + break + case "victory": + logger.ui("胜利") + case "finish": + finish_random_left_right() + self.done() + case _: + if _flag_title_msg: + logger.ui("请检查游戏场景", "warn") + _flag_title_msg = False + random_sleep() diff --git a/src/package/tansuo.py b/src/package/tansuo.py index 79cf149..0d1abcf 100644 --- a/src/package/tansuo.py +++ b/src/package/tansuo.py @@ -5,10 +5,10 @@ import pyautogui -from src.utils.event import event_thread from ..utils.application import RESOURCE_DIR_PATH from ..utils.coordinate import Coor -from ..utils.decorator import log_function_call, run_in_thread, time_count +from ..utils.decorator import log_function_call +from ..utils.event import event_thread from ..utils.function import ( check_click, check_finish_once, @@ -27,10 +27,9 @@ class TanSuo(Package): """探索""" - scene_name = "探索" resource_path = "tansuo" - resource_list: list = [ + resource_list = [ # "boss_finish", "chuzhanxiaohao", "fighting", @@ -49,10 +48,10 @@ class TanSuo(Package): "treasure_box", # "zidonglunhuan", ] + description = "提前准备好自动轮换和加成,仅单人探索" def __init__(self, n: int = 0) -> None: - self.n = 0 # 当前次数 - self.max = n # 总次数 + super().__init__(n) self.flag_boss_done: bool = False # boss战结束 def get_all_coor_info_tansuo_center(self, file: str): @@ -105,9 +104,7 @@ def title(self) -> bool: scene, coor = check_scene_multiple_once(scene_list, self.resource_path) if scene is None: continue - if "/" in scene: - scene = scene.split("/")[-1] - logger.scene(scene) + scene = self.scene_handle(scene) match scene: case "chuzhanxiaohao" | "tansuo_28" | "tansuo_28_0" | "tansuo_28_title": @@ -165,9 +162,6 @@ def finish(self): # 妖气封印 return - @run_in_thread - @time_count - @log_function_call def run(self): _scene_list = [ "tansuo_28_0", @@ -176,7 +170,6 @@ def run(self): "tansuo", "chuzhanxiaohao", ] - logger.ui("单人探索,测试功能", "warn") while self.n < self.max and self.title(): if event_thread.is_set(): @@ -191,16 +184,16 @@ def run(self): case "tansuo_28_0": # 右侧列表按钮 # function.judge_click(f"{self.resource_path}/tansuo") click(coor) - random_sleep(1, 2) + random_sleep() # self.n += 1 case "tansuo_28_title": - check_click(f"{self.resource_path}/tansuo") + self.check_click("tansuo") # self.n += 1 - random_sleep(2, 3) + random_sleep(2) case "chuzhanxiaohao": random_sleep(0.5, 1) # 先判断boss面灵气 - coor = get_coor_info(f"{self.resource_path}/fighting_boss") + coor = self.get_coor_info("fighting_boss") if coor.is_effective: logger.scene("BOSS") click(coor) @@ -212,9 +205,8 @@ def run(self): self.fighting() else: drag_in_window(-400, 0) - random_sleep(1, 2) + random_sleep() if self.flag_boss_done: self.flag_boss_done = False self.finish() self.done() - logger.ui(f"已完成 {self.scene_name} {self.n}次") diff --git a/src/package/utils.py b/src/package/utils.py index 447f865..5076f55 100644 --- a/src/package/utils.py +++ b/src/package/utils.py @@ -1,6 +1,6 @@ import time -from ..utils.decorator import run_in_thread +from ..utils.decorator import log_function_call, run_in_thread from ..utils.event import event_thread from ..utils.function import ( RESOURCE_FIGHT_PATH, @@ -18,6 +18,27 @@ from ..utils.toast import toast +class FightResource: + """通用战斗资源""" + resource_path: str = "fight" # 路径 + resource_list: list = [ # 资源列表 + "accept_invitation", # 接受邀请 + "fail", # 失败 + "finish", # 结束 + "fighting_friend_default", # 战斗中好友图标-怀旧/简约 + "fighting_friend_linshuanghanxue", # 战斗中好友图标-凛霜寒雪 + "fighting_friend_chunlvhanqing", # 战斗中好友图标-春缕含青 + "passenger_2", # 队员2 + "passenger_3", # 队员3 + "start_single", # 单人挑战 + "start_team", # 组队挑战 + "tanchigui", # 贪吃鬼 + "victory", # 成功 + "ready_old", # 准备-怀旧主题 + "ready_new", # 准备-简约主题 + ] + + class Package: scene_name: str = None @@ -28,7 +49,10 @@ class Package: """资源列表""" description: str = None """功能描述""" + fast_time: int = 0 + """最快通关速度,用于中途等待""" + @log_function_call def __init__(self, n: int = 0) -> None: self.n: int = 0 """当前次数""" @@ -36,9 +60,11 @@ def __init__(self, n: int = 0) -> None: """总次数""" self.current_resource_list: list = None """当前使用的资源列表""" + self.current_scene: str = None + """当前场景""" - def get_coor_info(self, file): - return get_coor_info(f"{self.resource_path}/{file}") + def get_coor_info(self, file, *args, **kwargs): + return get_coor_info(f"{self.resource_path}/{file}", *args, **kwargs) def check_click(self, file, *args, **kwargs): return check_click(f"{self.resource_path}/{file}", *args, **kwargs) @@ -53,9 +79,12 @@ def scene_print(self, scene: str = None) -> None: # FIXME remove logger.scene(scene) def scene_handle(self, scene: str = None) -> str: + if scene == None: + scene = self.current_scene logger.info(f"current scene: {scene}") if "/" in scene: scene = scene.split("/")[-1] + self.current_scene = scene return scene def log_current_scene_list(self) -> None: diff --git a/src/package/xuanshangfengyin.py b/src/package/xuanshangfengyin.py index 365863b..3489057 100644 --- a/src/package/xuanshangfengyin.py +++ b/src/package/xuanshangfengyin.py @@ -6,28 +6,29 @@ import time from ..utils.config import config -from ..utils.decorator import log_function_call, run_in_thread +from ..utils.decorator import run_in_thread from ..utils.event import event_thread, event_xuanshang, event_xuanshang_enable from ..utils.function import click, get_coor_info_center from ..utils.log import logger from ..utils.toast import toast +from .utils import Package -class XuanShangFengYin: +class XuanShangFengYin(Package): """悬赏封印""" + scene_name = "悬赏封印" + resource_path = "xuanshangfengyin" + resource_list: list = [ + "title", # 特征图像 + "xuanshang_accept", # 接受 + "xuanshang_refuse", # 拒绝 + "xuanshang_ignore", # 忽略 + ] def __init__(self): - self.scene_name: str = "悬赏封印" - self.resource_path: str = "xuanshangfengyin" # 图片路径 self._flag_is_first: bool = True self._flag: bool = False event_xuanshang_enable.set() # 启用 - self.resource_list: list = [ - "title", # 特征图像 - "xuanshang_accept", # 接受 - "xuanshang_refuse", # 拒绝 - "xuanshang_ignore" # 忽略 - ] def check_click(self, file: str, timeout: int = None) -> None: """图像识别,并点击 @@ -51,8 +52,6 @@ def check_click(self, file: str, timeout: int = None) -> None: click(coor) return - @log_function_call - @run_in_thread def run(self) -> None: logger.info("悬赏封印进行中...") # 第一次进入,确保不会阻塞function.get_coor_info() @@ -63,7 +62,7 @@ def run(self) -> None: while True: coor = get_coor_info_center(f"{self.resource_path}/title.png", is_log=False) if coor.is_effective: - logger.scene("悬赏封印") + logger.scene(self.scene_name) event_xuanshang.clear() self._flag = True logger.ui("已暂停后台线程,等待处理", "warn") @@ -87,7 +86,10 @@ def run(self) -> None: if self._flag: self._flag = False logger.ui("悬赏封印已消失,恢复线程") - time.sleep(1) + time.sleep(0.1) + @run_in_thread + def task_start(self): + self.run() -xuanshangfengyin = XuanShangFengYin() +task_xuanshangfengyin = XuanShangFengYin() diff --git a/src/package/yeyuanhuo.py b/src/package/yeyuanhuo.py index 1505104..ad75813 100644 --- a/src/package/yeyuanhuo.py +++ b/src/package/yeyuanhuo.py @@ -3,6 +3,7 @@ # yeyuanhuo.py """业原火副本""" +import time from ..utils.decorator import log_function_call from ..utils.event import event_thread from ..utils.function import ( @@ -10,6 +11,7 @@ check_click, check_scene_multiple_once, click, + finish_random_left_right, random_sleep ) from ..utils.log import logger @@ -22,9 +24,10 @@ class YeYuanHuo(Package): resource_path = "yeyuanhuo" resource_list = [ "title", # 标题 - "start" # 挑战 + "start", # 挑战 ] - fast_time: int = 13 # 最快通关速度,用于中途等待 + description = "默认为“痴”,可替换resource/yeyuanhuo路径下start.png" + fast_time = 13 @log_function_call def __init__(self, n: int = 0) -> None: @@ -42,6 +45,7 @@ def run(self): f"{RESOURCE_FIGHT_PATH}/finish", f"{RESOURCE_FIGHT_PATH}/fail", f"{RESOURCE_FIGHT_PATH}/victory", + # f"{RESOURCE_FIGHT_PATH}/soul_overflow", ] _flag_title_msg: bool = True logger.num(f"0/{self.max}") @@ -69,9 +73,15 @@ def run(self): break case "victory": logger.ui("胜利") + # if _timer == None: + # _timer = time.perf_counter() random_sleep() + # case "soul_overflow": + # logger.ui("御魂上限", "warn") + # click(coor) case "finish": - self.ensure_finish() + finish_random_left_right() + self.done() case _: if _flag_title_msg: logger.ui("请检查游戏场景", "warn") diff --git a/src/package/yongshengzhihai.py b/src/package/yongshengzhihai.py index 122a060..6e3d91f 100644 --- a/src/package/yongshengzhihai.py +++ b/src/package/yongshengzhihai.py @@ -5,7 +5,7 @@ import pyautogui -from ..utils.decorator import log_function_call, run_in_thread, time_count +from ..utils.decorator import log_function_call from ..utils.event import event_thread from ..utils.function import ( RESOURCE_FIGHT_PATH, @@ -13,7 +13,6 @@ check_scene_multiple_once, click, finish_random_left_right, - get_coor_info, random_sleep, result ) @@ -24,35 +23,38 @@ class YongShengZhiHai(Package): """永生之海副本""" + scene_name = "永生之海副本" + resource_path = "yongshengzhihai" + resource_list = [ + "title_team", # 组队界面 + "passenger", # 队员 + "start_team", # 组队挑战 + # "start_single", # 单人挑战 + "fighting", # 进行中 + # "accept_invitation", # 接受邀请 + ] + description = "默认打手30次" + fast_time = 13 - 2 @log_function_call - def __init__(self): - """永生之海副本""" - self.scene_name: str = "永生之海副本" - self.n: int = 0 # 当前次数 - self.max: int = 0 # 总次数 - self.fast_time: int = 13 - 2 # 最快通关速度,用于中途等待 - self.resource_path: str = "yongshengzhihai" # 路径 - self.resource_list: list = [ # 资源列表 - "title_team", # 组队界面 - "passenger", # 队员 - "start_team", # 组队挑战 - # "start_single", # 单人挑战 - "fighting", # 进行中 - # "accept_invitation", # 接受邀请 - ] - - @log_function_call - def start(self, mode: str = None) -> None: + def start(self) -> None: """挑战""" - if mode == "team": + if isinstance(self, YongShengZhiHaiTeam): check_click(f"{self.resource_path}/start_team") - elif mode == "single": + else: check_click(f"{RESOURCE_FIGHT_PATH}/start_single") class YongShengZhiHaiTeam(YongShengZhiHai): """组队永生之海副本""" + scene_name = "组队永生之海副本" + resource_list = [ + "title_team", # 组队界面 + "passenger_2", # 队员2 + "start_team", # 组队挑战 + "fighting", # 进行中 + "accept_invitation", # 接受邀请 + ] @log_function_call def __init__( @@ -71,17 +73,7 @@ def __init__( flag_drop_statistics (bool): 是否开启掉落统计,默认否 """ - super().__init__() - self.scene_name: str = "组队永生之海副本" - self.n: int = 0 # 当前次数 - self.max: int = n # 总次数 - self.resource_list: list = [ # 资源列表 - "title_team", # 组队界面 - "passenger_2", # 队员2 - "start_team", # 组队挑战 - "fighting", # 进行中 - "accept_invitation", # 接受邀请 - ] + super().__init__(n) self.flag_driver: bool = flag_driver # 是否为司机(默认否) self.flag_drop_statistics: bool = flag_drop_statistics # 是否开启掉落统计 @@ -92,7 +84,7 @@ def is_passengers_on_position(self): while True: if event_thread.is_set(): return - coor = get_coor_info(f"{self.resource_path}/passenger") + coor = self.get_coor_info("passenger") if coor.is_zero: logger.ui("队员就位") return @@ -139,9 +131,6 @@ def finish(self): logger.ui("结束") return - @run_in_thread - @time_count - @log_function_call def run(self): # 保留必需图像,提高识别效率 _g_resource_list: list = [ @@ -152,35 +141,32 @@ def run(self): ] if self.flag_driver: _g_resource_list.append(f"{RESOURCE_FIGHT_PATH}/start_team") - _resource_list: list = None _flag_title_msg: bool = True logger.num(f"0/{self.max}") while self.n < self.max: if event_thread.is_set(): return - _resource_list = _g_resource_list if _resource_list is None else _resource_list - scene, coor = check_scene_multiple_once(_resource_list) + self.current_resource_list = _g_resource_list + scene, coor = self.check_scene_multiple_once() if scene is None: continue - if "/" in scene: - scene = scene.split("/")[-1] - logger.scene(scene) - match scene: + self.scene_handle(scene) + + match self.current_scene: case "title_team": logger.ui("组队界面准备中") if self.flag_driver: self.is_passengers_on_position() - self.start("team") + self.start() # self.start() - random_sleep(1, 2) + random_sleep() _flag_title_msg = False case "fighting": logger.ui("对局进行中") self.finish() - self.n += 1 - logger.num(f"{self.n}/{self.max}") - random_sleep(1, 2) + self.done() + random_sleep() _flag_title_msg = False case "accept_invitation": # TODO 新设备第一次接受邀请会有弹窗,需手动勾选“不再提醒” diff --git a/src/package/yuhun.py b/src/package/yuhun.py index b40d186..39a1d2d 100644 --- a/src/package/yuhun.py +++ b/src/package/yuhun.py @@ -5,12 +5,10 @@ import pyautogui -from src.utils.event import event_thread - -from ..utils.decorator import log_function_call, run_in_thread, time_count +from ..utils.decorator import log_function_call +from ..utils.event import event_thread from ..utils.function import ( RESOURCE_FIGHT_PATH, - check_click, check_scene_multiple_once, click, finish, @@ -26,44 +24,54 @@ class YuHun(Package): """御魂副本""" + scene_name = "御魂副本" + resource_path = "yuhun" + resource_list = [ + "title_10", # 魂十 + "title_11", # 魂土 + "title_12", # 神罚 + "xiezhanduiwu", # 组队界面 + "passenger_2", # 队员2 + "passenger_3", # 队员3 + "start_team", # 组队挑战 + "start_single", # 单人挑战 + "fighting", # 魂土进行中 + "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 + "fighting_shenfa", # 神罚战斗场景 + "finish_damage", # 结束特征图像 + "finish_damage_2000", # 结束特征图像-鎏金圣域 + "finish_damage_shenfa", # 结束特征图像-神罚 + "accept_invitation", # 接受邀请 + ] + description = "已适配组队/单人 魂十、魂土、神罚副本\ + 新设备第一次接受邀请会有弹窗,需手动勾选“不再提醒”" + fast_time = 13 - 2 @log_function_call - def __init__(self): - """御魂副本""" - self.scene_name: str = "御魂副本" - self.n: int = 0 # 当前次数 - self.max: int = 0 # 总次数 - self.fast_time: int = 13 - 2 # 最快通关速度,用于中途等待 - self.resource_path: str = "yuhun" # 路径 - self.resource_list: list = [ # 资源列表 - "title_10", # 魂十 - "title_11", # 魂土 - "title_12", # 神罚 - "xiezhanduiwu", # 组队界面 - "passenger_2", # 队员2 - "passenger_3", # 队员3 - "start_team", # 组队挑战 - "start_single", # 单人挑战 - "fighting", # 魂土进行中 - "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 - "fighting_shenfa", # 神罚战斗场景 - "finish_damage", # 结束特征图像 - "finish_damage_2000", # 结束特征图像-鎏金圣域 - "finish_damage_shenfa", # 结束特征图像-神罚 - "accept_invitation", # 接受邀请 - ] - - @log_function_call - def start(self, mode: str = None) -> None: + def start(self) -> None: """挑战""" - if mode == "team": - check_click(f"{self.resource_path}/start_team") - elif mode == "single": - check_click(f"{self.resource_path}/start_single") + if isinstance(self, YuHunTeam): + self.check_click("start_team") + elif isinstance(self, YuHunSingle): + self.check_click("start_single") class YuHunTeam(YuHun): """组队御魂副本""" + scene_name = "组队御魂副本" + resource_list = [ # 资源列表 + "xiezhanduiwu", # 组队界面 + "passenger_2", # 队员2 + "passenger_3", # 队员3 + "start_team", # 组队挑战 + "fighting", # 魂土进行中 + "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 + "fighting_shenfa", # 神罚战斗场景 + "finish_damage", # 结束特征图像 + "finish_damage_2000", # 结束特征图像-鎏金圣域 + "finish_damage_shenfa", # 结束特征图像-神罚 + "accept_invitation", # 接受邀请 + ] @log_function_call def __init__( @@ -73,7 +81,7 @@ def __init__( flag_passengers: int = 2, flag_drop_statistics: bool = False ) -> None: - super().__init__() + super().__init__(n) """组队御魂副本 参数: @@ -82,23 +90,6 @@ def __init__( flag_passengers (int): 组队人数,默认2人 flag_drop_statistics (bool): 是否开启掉落统计,默认否 """ - self.scene_name: str = "组队御魂副本" - self.n: int = 0 # 当前次数 - self.max: int = n # 总次数 - self.resource_list: list = [ # 资源列表 - "xiezhanduiwu", # 组队界面 - "passenger_2", # 队员2 - "passenger_3", # 队员3 - "start_team", # 组队挑战 - "fighting", # 魂土进行中 - "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 - "fighting_shenfa", # 神罚战斗场景 - "finish_damage", # 结束特征图像 - "finish_damage_2000", # 结束特征图像-鎏金圣域 - "finish_damage_shenfa", # 结束特征图像-神罚 - "accept_invitation", # 接受邀请 - ] - self.flag_driver: bool = flag_driver # 是否为司机(默认否) self.flag_passengers: int = flag_passengers # 组队人数 self.flag_drop_statistics: bool = flag_drop_statistics # 是否开启掉落统计 @@ -145,9 +136,6 @@ def finish(self): logger.ui("结束") return - @run_in_thread - @time_count - @log_function_call def run(self): # 保留必需图像,提高识别效率 _g_resource_list: list = [ @@ -171,22 +159,20 @@ def run(self): scene, coor = check_scene_multiple_once(_resource_list) if scene is None: continue - if "/" in scene: - scene = scene.split("/")[-1] - logger.scene(scene) - match scene: + self.scene_handle(scene) + + match self.current_scene: case "xiezhanduiwu": logger.ui('组队界面准备中') if self.flag_driver: is_passengers_on_position(self.flag_passengers) - self.start("team") - random_sleep(1, 2) + self.start() + random_sleep() _flag_title_msg = False case "fighting_friend_default" | "fighting_friend_linshuanghanxue" | "fighting_friend_chunlvhanqing": logger.ui("对局进行中") self.finish() - self.n += 1 - logger.num(f"{self.n}/{self.max}") + self.done() _resource_list = None _flag_title_msg = False random_sleep() @@ -202,31 +188,29 @@ def run(self): class YuHunSingle(YuHun): """单人御魂副本""" + scene_name = "单人御魂副本" + resource_list = [ + "title_10", # 魂十 + "title_11", # 魂土 + "title_12", # 神罚 + "start_single", # 单人挑战 + "fighting", # 魂土进行中 + "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 + "fighting_shenfa", # 神罚战斗场景 + # "finish_damage", # 结束特征图像 + # "finish_damage_2000", # 结束特征图像-鎏金圣域 + # "finish_damage_shenfa", # 结束特征图像-神罚 + ] @log_function_call def __init__(self, n: int = 0, flag_drop_statistics: bool = False): - super().__init__() + super().__init__(n) """单人御魂副本 参数: n (int): 次数,默认0次 flag_drop_statistics (bool): 是否开启掉落统计,默认否 """ - self.scene_name: str = "御魂副本" - self.n: int = 0 # 当前次数 - self.max: int = n # 总次数 - self.resource_list: list = [ # 资源列表 - "title_10", # 魂十 - "title_11", # 魂土 - "title_12", # 神罚 - "start_single", # 单人挑战 - "fighting", # 魂土进行中 - "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 - "fighting_shenfa", # 神罚战斗场景 - # "finish_damage", # 结束特征图像 - # "finish_damage_2000", # 结束特征图像-鎏金圣域 - # "finish_damage_shenfa", # 结束特征图像-神罚 - ] self.flag_drop_statistics: bool = flag_drop_statistics # 是否开启掉落统计 @log_function_call @@ -292,11 +276,7 @@ def finish_slow(self): logger.ui("结束") return - @run_in_thread - @time_count - @log_function_call def run(self): - """单人""" _g_resource_list: list = [ "title_10", # 魂十 "title_11", # 魂土 @@ -304,7 +284,7 @@ def run(self): "start_single", # 单人挑战 "fighting", # 魂土进行中 "fighting_linshuanghanxue", # 凛霜寒雪战斗主题 - "fighting_shenfa" # 神罚战斗场景 + "fighting_shenfa", # 神罚战斗场景 ] _resource_list: list = None _flag_title_msg: bool = True @@ -313,32 +293,27 @@ def run(self): while self.n < self.max: if event_thread.is_set(): return - _resource_list = _g_resource_list if _resource_list is None else _resource_list scene, coor = check_scene_multiple_once(_resource_list, self.resource_path) if scene is None: continue - # if "/" in scene: - # scene = scene.split("/")[-1] - # logger.scene(scene) - self.scene_print(scene) + self.scene_handle(scene) - match scene: + match self.current_scene: case "title_10" | "title_11" | "title_12": - self.start("single") - random_sleep(self.fast_time, self.fast_time+1) + self.start() + random_sleep(self.fast_time) _flag_title_msg = False case "start_single": click(coor) - random_sleep(self.fast_time, self.fast_time+1) + random_sleep(self.fast_time) # 只判断下列图像,提高效率 _resource_list = ["fighting", "fighting_linshuanghanxue", "fighting_shenfa"] _flag_title_msg = False case "fighting" | "fighting_linshuanghanxue" | "fighting_shenfa": logger.ui("对局进行中") self.finish_slow() - self.n += 1 - logger.num(f"{self.n}/{self.max}") + self.done() _resource_list = None _flag_title_msg = False case _: diff --git a/src/package/yuling.py b/src/package/yuling.py index 6eda82e..46b631a 100644 --- a/src/package/yuling.py +++ b/src/package/yuling.py @@ -3,32 +3,35 @@ # yuling.py """御灵副本""" -from src.utils.event import event_thread - -from ..utils.decorator import log_function_call, run_in_thread, time_count +from ..utils.decorator import log_function_call +from ..utils.event import event_thread from ..utils.function import ( - check_click, check_scene, finish, finish_random_left_right, random_sleep ) from ..utils.log import logger +from .utils import Package -class YuLing: +class YuLing(Package): """御灵副本""" + scene_name = "御灵副本" + resource_path = "yuling" + resource_list = [ + "title", # 限时活动特征图像 + "start", # 挑战 + ] + description = """暗神龙-周二六日 + 暗白藏主-周三六日 + 暗黑豹-周四六 + 暗孔雀-周五六日 + 绘卷期间请减少使用""" @log_function_call def __init__(self, n: int = 0) -> None: - self.scene_name: str = "御灵副本" - self.n: int = 0 # 当前次数 - self.max: int = n # 总次数 - self.resource_path: str = "yuling" # 路径 - self.resource_list: list = [ # 资源列表 - "title", # 限时活动特征图像 - "start" # 挑战 - ] + super().__init__(n) def title(self) -> bool: """场景""" @@ -44,30 +47,24 @@ def title(self) -> bool: def start(self) -> None: """开始""" - check_click(f"{self.resource_path}/start") + self.check_click("start") - @run_in_thread - @time_count - @log_function_call def run(self) -> None: - if self.title(): - logger.num(f"0/{self.max}") - while self.n < self.max: - if event_thread.is_set(): - return - - random_sleep(1, 2) - # 开始 - self.start() - # 结束 - finish() - random_sleep(1, 2) - # 结算 - finish_random_left_right(is_multiple_drops_y=True) - random_sleep(1, 3) - self.n += 1 - logger.num(f"{self.n}/{self.max}") - # TODO 强制等待,后续优化 - if self.n in {12, 25, 39, 59, 73}: - random_sleep(10, 20) - logger.ui(f"已完成 {self.scene_name} {self.n}次") + self.title() + logger.num(f"0/{self.max}") + while self.n < self.max: + if event_thread.is_set(): + return + random_sleep() + # 开始 + self.start() + # 结束 + finish() + random_sleep() + # 结算 + finish_random_left_right(is_multiple_drops_y=True) + random_sleep() + self.done() + # TODO 强制等待,后续优化 + if self.n in {12, 25, 39, 59, 73}: + random_sleep(10, 20) diff --git a/src/package/zhaohuan.py b/src/package/zhaohuan.py index a9593b7..ccf2bf5 100644 --- a/src/package/zhaohuan.py +++ b/src/package/zhaohuan.py @@ -3,30 +3,28 @@ # zhaohuan.py """普通召唤""" -from src.utils.event import event_thread - -from ..utils.decorator import log_function_call, run_in_thread, time_count -from ..utils.function import check_click, check_scene, random_sleep +from ..utils.decorator import log_function_call +from ..utils.event import event_thread +from ..utils.function import check_scene, random_sleep from ..utils.log import logger from .utils import Package class ZhaoHuan(Package): """普通召唤""" + scene_name = "普通召唤" + resource_path = "zhaohuan" + resource_list = [ + "putongzhaohuan", # 普通召唤 + "queding", # 确定 + "title", # 标题 + "zaicizhaohuan", # 再次召唤 + ] + description = "普通召唤,请选择十连次数,仅适配默认召唤屋" @log_function_call def __init__(self, n: int = 0) -> None: super().__init__(n) - self.scene_name: str = "普通召唤" - self.n: int = 0 # 当前次数 - self.max: int = n # 总次数 - self.resource_path: str = "zhaohuan" # 路径 - self.resource_list: list = [ # 资源列表 - "putongzhaohuan", # 普通召唤 - "queding", # 确定 - "title", # 标题 - "zaicizhaohuan" # 再次召唤 - ] def title(self) -> bool: """场景""" @@ -42,21 +40,17 @@ def title(self) -> bool: def first(self) -> None: """第一次召唤""" - check_click(f"{self.resource_path}/putongzhaohuan") + self.check_click("putongzhaohuan") def again(self) -> None: """非第一次召唤""" - check_click(f"{self.resource_path}/zaicizhaohuan") + self.check_click("zaicizhaohuan") - @run_in_thread - @time_count - @log_function_call def run(self) -> None: _flag_first = True # 是否第一次 logger.num(f"0/{self.max}") random_sleep(0.4, 0.8) self.title() - while self.n < self.max: if event_thread.is_set(): return @@ -67,6 +61,4 @@ def run(self) -> None: self.again() random_sleep(4, 6) self.done() - - check_click(f"{self.resource_path}/queding") - logger.ui(f"已完成 普通召唤十连 {self.n}次") + self.check_click("queding") diff --git a/src/resource/juexing/title.png b/src/resource/juexing/title.png new file mode 100644 index 0000000..c5d2f10 Binary files /dev/null and b/src/resource/juexing/title.png differ diff --git a/src/utils/function.py b/src/utils/function.py index 9e89f98..a646ec1 100644 --- a/src/utils/function.py +++ b/src/utils/function.py @@ -27,27 +27,6 @@ """重启脚本路径""" -class FightResource: - """通用战斗资源""" - resource_path: str = "fight" # 路径 - resource_list: list = [ # 资源列表 - "accept_invitation", # 接受邀请 - "fail", # 失败 - "finish", # 结束 - "fighting_friend_default", # 战斗中好友图标-怀旧/简约 - "fighting_friend_linshuanghanxue", # 战斗中好友图标-凛霜寒雪 - "fighting_friend_chunlvhanqing", # 战斗中好友图标-春缕含青 - "passenger_2", # 队员2 - "passenger_3", # 队员3 - "start_single", # 单人挑战 - "start_team", # 组队挑战 - "tanchigui", # 贪吃鬼 - "victory", # 成功 - "ready_old", # 准备-怀旧主题 - "ready_new", # 准备-简约主题 - ] - - @log_function_call def random_normal(min: int | float, max: int | float) -> int: """正态分布""" @@ -138,38 +117,44 @@ def image_file_format(file: Path | str) -> str: logger.warn(f"no such file {_file}") -def get_coor_info(file: Path | str) -> AbsoluteCoor: +def get_coor_info(file: Path | str, region: tuple[int, int, int, int] = (0, 0, 0, 0)) -> AbsoluteCoor: """图像识别,返回图像的全屏随机坐标 参数: file (Path | str): 图像名称 + region (tuple[int, int, int, int]): 识别区域(相对),默认(0,0,0,0) + 用法: `self.resource_path / filename` 返回: Coor: 成功,返回图像的全屏随机坐标;失败,返回(0,0) """ - _file_name = image_file_format(RESOURCE_DIR_PATH / file) - logger.debug(f"looking for file: {_file_name}") if event_thread.is_set(): return Coor(0, 0) # 等待悬赏封印判定 if event_xuanshang_enable.is_set(): event_xuanshang.wait() + _file_name = image_file_format(RESOURCE_DIR_PATH / file) + logger.debug(f"looking for file: {_file_name}") + if region != (0, 0, 0, 0): + logger.debug(_region) + _region = ( # TODO need test + region[0] + window.window_left, + region[1] + window.window_top, + region[2] + window.absolute_window_width, + region[3] + window.absolute_window_height + ) + try: button_location = pyautogui.locateOnScreen( - _file_name, - region=( - window.window_left, - window.window_top, - window.absolute_window_width, - window.absolute_window_height - ), + image=_file_name, + region=_region, confidence=0.8 ) - logger.debug(f"button_location: {button_location}") + # logger.debug(f"button_location: {button_location}") if button_location: logger.info(f"button_location: {button_location}") coor: AbsoluteCoor = random_coor( @@ -486,7 +471,6 @@ def click(coor: Coor = None, dura: float = 0.5, sleeptime: float = 0) -> None: else: _x, _y = coor.coor - # x, y = pyautogui.position() if coor is None else (coor.x, coor.y) pyautogui.moveTo(_x, _y, duration=dura, tween=random.choice(list_tween)) logger.info(f"click at ({_x},{_y})") try: diff --git a/src/utils/gui.py b/src/utils/gui.py index bbf1efe..2fad70b 100644 --- a/src/utils/gui.py +++ b/src/utils/gui.py @@ -19,7 +19,6 @@ from .config import config, is_Chinese_Path from .decorator import log_function_call, run_in_thread from .event import event_thread, event_xuanshang_enable -from .function import FightResource from .log import log_clean_up, logger from .mysignal import global_ms as ms from .mythread import WorkThread @@ -52,6 +51,7 @@ class MainWindow(QMainWindow): "11.组队日轮副本", "12.单人探索", "13.契灵", + "14.觉醒副本", ] _choice: int # 功能 @@ -179,7 +179,7 @@ def application_init(self) -> None: if config.config_user.xuanshangfengyin == "关闭": event_xuanshang_enable.clear() else: - xuanshangfengyin.xuanshangfengyin.run() + task_xuanshangfengyin.task_start() def qmessagbox_update_func(self, level: str, msg: str) -> None: match level: @@ -274,34 +274,11 @@ def is_resource_directory_complete(self) -> bool: 返回: bool: 是否完整 """ - class Package: - def __init__(self, n: int = 0) -> None: - self.scene_name = "tests" - self.n: int = 0 - self.max: int = n - self.resource_path = "tests" - self.resource_list: list = [] - logger.info("开始检查资源") if not Path(RESOURCE_DIR_PATH).exists(): return False - P: Package - for P in [ - FightResource(), - baiguiyexing.BaiGuiYeXing(), - daoguantupo.DaoGuanTuPo(), - huodong.HuoDong(), - jiejietupo.JieJieTuPo(), - qiling.QiLing(), - rilun.RiLun(), - tansuo.TanSuo(), - xuanshangfengyin.XuanShangFengYin(), - yeyuanhuo.YeYuanHuo(), - yongshengzhihai.YongShengZhiHai(), - yuhun.YuHun(), - yuling.YuLing(), - zhaohuan.ZhaoHuan() - ]: + _package_resource_list = get_package_resource_list() + for P in _package_resource_list: # 检查子文件夹 if not Path(RESOURCE_DIR_PATH/P.resource_path).exists(): logger.ui("资源文件夹不存在!", "error") @@ -399,8 +376,7 @@ def choice_description(self): match self._choice: case 1: # 御魂副本 - logger.ui("请确保阵容稳定,已适配组队/单人 魂土、神罚副本\ - 新设备第一次接受邀请会有弹窗,需手动勾选“不再提醒”") + logger.ui(YuHun.description) self.ui.stackedWidget.setCurrentIndex(1) # 索引1,御魂 self.ui.button_mode_team.setEnabled(True) @@ -413,7 +389,7 @@ def choice_description(self): self.ui.button_passengers_3.setEnabled(True) self.ui.button_passengers_2.setChecked(True) case 2: # 组队永生之海副本 - logger.ui("默认打手30次\n阴阳师技能自行选择,如晴明灭\n待开发:手动第一次锁定阵容") + logger.ui(YongShengZhiHai.description) self.ui.stackedWidget.setCurrentIndex(1) # 索引1,御魂 self.ui_spin_times_set_value_func(30) self.ui.button_mode_team.setChecked(True) @@ -425,12 +401,12 @@ def choice_description(self): self.ui.button_passengers_2.setEnabled(False) self.ui.button_passengers_3.setEnabled(False) case 3: # 业原火副本 - logger.ui("默认为“痴”,有“贪”“嗔”需求的,可替换resource/yeyuanhuo路径下start.png") + logger.ui(YeYuanHuo.description) case 4: # 御灵副本 - logger.ui("暗神龙-周二六日\n暗白藏主-周三六日\n暗黑豹-周四六\n暗孔雀-周五六日\n绘卷期间请减少使用") + logger.ui(YuLing.description) self.ui_spin_times_set_value_func(1, 1, 400) # 桌面版上限300 case 5: # 个人突破 - logger.ui("默认3胜刷新,上限30") + logger.ui(JieJieTuPoGeRen.description) # self.ui.stackedWidget.setCurrentIndex(2) # 索引2,结界突破 self.ui_spin_times_set_value_func(1, 1, 30) case 6: # 寮突破 @@ -445,17 +421,16 @@ def choice_description(self): _current = 6 self.ui_spin_times_set_value_func(_current, 1, 200) case 7: # 道馆突破 - logger.ui("目前仅支持正在进行中的道馆突破,无法实现跳转道馆场景\n待开发:冷却时间、观战助威") + logger.ui(DaoGuanTuPo.description) self.ui.stackedWidget.setCurrentIndex(3) # 索引3,道馆突破 self.ui.spin_times.setEnabled(False) case 8: # 普通召唤 - logger.ui("普通召唤,请选择十连次数") + logger.ui(ZhaoHuan.description) case 9: # 百鬼夜行 - logger.ui("仅适用于清票,且无法指定鬼王") + logger.ui(BaiGuiYeXing.description) case 10: # 限时活动 - logger.ui(huodong.HuoDong().description) + logger.ui(HuoDong.description) case 11: # 组队日轮副本 - logger.ui("请确保阵容稳定,仅适用于队友挂饼,不适用于极限卡速,默认打手\n待开发:手动第一次锁定阵容") self.ui.stackedWidget.setCurrentIndex(1) # 索引1,御魂 self.ui_spin_times_set_value_func(50) @@ -469,11 +444,13 @@ def choice_description(self): self.ui.button_passengers_3.setEnabled(True) self.ui.button_passengers_2.setChecked(True) case 12: # 单人探索 - logger.ui("提前准备好自动轮换和加成,仅单人探索") + logger.ui(TanSuo.description) case 13: # 契灵 - logger.ui(qiling.QiLing().description) + logger.ui(QiLing.description) self.ui.stackedWidget.setCurrentIndex(4) # 索引4,契灵 self.ui.button_qiling_tancha.setChecked(True) + case 14: #觉醒副本 + logger.ui(JueXing.description) def start_stop(self) -> None: """开始&停止按钮""" @@ -497,16 +474,16 @@ def start() -> None: _flag_passengers = int( self.ui.buttonGroup_passengers.checkedButton().text() ) - yuhun.YuHunTeam( + YuHunTeam( n=_n, flag_driver=_flag_driver, flag_passengers=_flag_passengers, flag_drop_statistics=_flag_drop_statistics, - ).run() + ).task_start() case "单人": - yuhun.YuHunSingle( + YuHunSingle( n=_n, flag_drop_statistics=_flag_drop_statistics - ).run() + ).task_start() case 2: # 永生之海副本 _flag_drop_statistics = ( self.ui.button_yuhun_drop_statistics.isChecked() @@ -517,30 +494,30 @@ def start() -> None: self.ui.buttonGroup_driver.checkedButton().text() != "否" ) - yongshengzhihai.YongShengZhiHaiTeam( + YongShengZhiHaiTeam( n=_n, flag_driver=_flag_driver, flag_drop_statistics=_flag_drop_statistics, - ).run() + ).task_start() case "单人": pass case 3: # 业原火 - yeyuanhuo.YeYuanHuo(n=_n).task_start() + YeYuanHuo(n=_n).task_start() case 4: # 御灵 - yuling.YuLing(n=_n).run() + YuLing(n=_n).task_start() case 5: # 个人突破 - jiejietupo.JieJieTuPoGeRen(n=_n).task_start() + JieJieTuPoGeRen(n=_n).task_start() case 6: # 寮突破 - jiejietupo.JieJieTuPoYinYangLiao(n=_n).task_start() + JieJieTuPoYinYangLiao(n=_n).task_start() case 7: # 道馆突破 flag_guanzhan = self.ui.button_guanzhan.isChecked() - daoguantupo.DaoGuanTuPo(flag_guanzhan=flag_guanzhan).task_start() + DaoGuanTuPo(flag_guanzhan=flag_guanzhan).task_start() case 8: # 普通召唤 - zhaohuan.ZhaoHuan(n=_n).run() + ZhaoHuan(n=_n).task_start() case 9: # 百鬼夜行 - baiguiyexing.BaiGuiYeXing(n=_n).task_start() + BaiGuiYeXing(n=_n).task_start() case 10: # 限时活动 - huodong.HuoDong(n=_n).task_start() + HuoDong(n=_n).task_start() case 11: # 组队日轮副本 # 是否司机(默认否) # 组队人数(默认2人) @@ -549,21 +526,23 @@ def start() -> None: _flag_passengers = int( self.ui.buttonGroup_passengers.checkedButton().text() ) - rilun.RiLun( + RiLun( n=_n, flag_driver=_flag_driver, flag_passengers=_flag_passengers, ).task_start() case 12: # 单人探索 - tansuo.TanSuo(n=_n).run() + TanSuo(n=_n).task_start() case 13: # 契灵 _flag_tancha = self.ui.button_qiling_tancha.isChecked() _flag_jieqi = self.ui.button_qiling_jieqi.isChecked() - qiling.QiLing( + QiLing( n=_n, _flag_tancha=_flag_tancha, _flag_jieqi=_flag_jieqi ).task_start() + case 14:#觉醒副本 + JueXing(n=_n).task_start() def stop() -> None: """停止函数"""