Compare commits

...

5 commits

Author SHA1 Message Date
b87c15c586 fix:未成功进入干员选择界面
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-14 00:11:15 +08:00
17d1fd919f fix:mumuipc内存泄漏,提高内存利用率 2024-12-14 00:09:23 +08:00
13e84a09f0 活动ex关导航
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
2024-12-13 22:12:11 +08:00
f86d23fb99 fix:被进敌人策略误判 2024-12-13 22:11:21 +08:00
9632142cc9 干员再部署时删除原有位置 2024-12-13 22:10:30 +08:00
18 changed files with 109 additions and 36 deletions

View file

@ -411,6 +411,10 @@
"label": "RESTORE_ALL_SANITY", "label": "RESTORE_ALL_SANITY",
"comment": "首次失败返还全部理智" "comment": "首次失败返还全部理智"
}, },
"621": {
"label": "OPERATOR_BAN",
"comment": "禁止干员出战"
},
"701": { "701": {
"label": "SHOP_OTHERS", "label": "SHOP_OTHERS",
"comment": "商店其它界面" "comment": "商店其它界面"
@ -684,8 +688,12 @@
"comment": "活动主界面" "comment": "活动主界面"
}, },
"1402": { "1402": {
"label": "ACTIVITY_CHOOSE_LEVEL", "label": "ACTIVITY_NORMAL_CHOOSE_LEVEL",
"comment": "活动关选择" "comment": "活动普通关选择"
},
"1403": {
"label": "ACTIVITY_EX_CHOOSE_LEVEL",
"comment": "活动EX关选择"
}, },
"1501": { "1501": {
"label": "SIGN_IN_DAILY", "label": "SIGN_IN_DAILY",

BIN
mower/resources/fight/ban.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/navigation/activity/banner_ex.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
mower/resources/navigation/activity/entry_ex.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -2153,6 +2153,7 @@ class BaseSchedulerSolver(SceneGraphSolver, BaseMixin):
if error_count > 3: if error_count > 3:
raise Exception("未成功进入干员选择界面") raise Exception("未成功进入干员选择界面")
self.ctap((config.recog.w * 0.82, config.recog.h * 0.2)) self.ctap((config.recog.w * 0.82, config.recog.h * 0.2))
self.sleep(1)
error_count += 1 error_count += 1
plan[room] = self.move_free_to_end(plan[room]) plan[room] = self.move_free_to_end(plan[room])
logger.info(plan[room]) logger.info(plan[room])

View file

@ -70,8 +70,7 @@ class AutoFight(SceneGraphSolver, FightMixin):
self.tap((20, 20)) self.tap((20, 20))
return return
if self.find("fight/breach"): if self.find("fight/breach"):
if self.breach_solver(): return self.breach_solver()
return True
self.travel_watching_skills() self.travel_watching_skills()
self.execute_action() self.execute_action()
@ -92,5 +91,7 @@ class AutoFight(SceneGraphSolver, FightMixin):
self.ctap("story_skip", 3) self.ctap("story_skip", 3)
elif scene == Scene.STORY_SKIP: elif scene == Scene.STORY_SKIP:
self.tap("story_skip_confirm_dialog", x_rate=0.94) self.tap("story_skip_confirm_dialog", x_rate=0.94)
elif scene == Scene.OPERATOR_BAN:
self.tap((1400, 900))
else: else:
NavigationSolver().run(self.level_name, mode="copy") NavigationSolver().run(self.level_name, mode="copy")

View file

@ -496,6 +496,10 @@ class FightMixin:
self.clear_op() self.clear_op()
return False return False
self.clear_op() self.clear_op()
for loc in self.location: # 再部署干员后,删除原有位置的干员
if name == self.location[loc]:
self.location.pop(loc)
break
self.location[(x, y)] = name self.location[(x, y)] = name
return True return True
else: else:

View file

@ -450,7 +450,10 @@ class NavigationSolver(SceneGraphSolver):
if LastStageNavigation().run(name, mode): if LastStageNavigation().run(name, mode):
# 剿灭导航,LastStageNavigation.run一定返回False # 剿灭导航,LastStageNavigation.run一定返回False
return True return True
if name in ActivityNavigation.location: if (
name in ActivityNavigation.location["normal"]
or name in ActivityNavigation.location["ex"]
):
ActivityNavigation().run(name, mode) ActivityNavigation().run(name, mode)
return True return True
self.switch_to_ex = False self.switch_to_ex = False

View file

@ -28,14 +28,26 @@ class ActivityNavigation(SceneGraphSolver):
solver_name = "活动关卡导航" solver_name = "活动关卡导航"
_location = { _location = {
"EP-1": (0, 0), "normal": {
"EP-2": [302, -196], "EP-1": (0, 0),
"EP-3": [483, -383], "EP-2": [302, -196],
"EP-4": [791, -224], "EP-3": [483, -383],
"EP-5": [1101, -338], "EP-4": [791, -224],
"EP-6": [1385, -453], "EP-5": [1101, -338],
"EP-7": [2001, -116], "EP-6": [1385, -453],
"EP-8": [2279, -391], "EP-7": [2001, -116],
"EP-8": [2279, -391],
},
"ex": {
"EP-EX-1": (0, 0),
"EP-EX-2": [107, 198],
"EP-EX-3": [210, 384],
"EP-EX-4": [316, 579],
"EP-EX-5": [849, 579],
"EP-EX-6": [955, 384],
"EP-EX-7": [1057, 198],
"EP-EX-8": [1167, 0],
},
} }
@classproperty @classproperty
@ -46,16 +58,18 @@ class ActivityNavigation(SceneGraphSolver):
def generate_names(self): def generate_names(self):
names = {} names = {}
for name in self._location.keys(): font_size = 37 if self.difficulty == "ex" else 40
names[name] = generate_name(name, pad_right=10) for name in self._location[self.difficulty].keys():
names[name] = generate_name(name, font_size, pad_right=10)
self.names = names self.names = names
def run(self, name: str, mode: Literal["auto", "copy"] = "auto") -> None: def run(self, name: str, mode: Literal["auto", "copy"] = "auto") -> None:
logger.info("导航至活动关卡") logger.info("导航至活动关卡")
self.switch_to_ex = False self.switch_to_ex = False # 是否切换到突袭模式
if name.endswith("#"): if name.endswith("#"):
name = name[:-1] name = name[:-1]
self.switch_to_ex = True self.switch_to_ex = True
self.difficulty = "ex" if "-EX-" in name else "normal"
self.name = name self.name = name
self.mode = mode self.mode = mode
self.generate_names() self.generate_names()
@ -66,8 +80,11 @@ class ActivityNavigation(SceneGraphSolver):
if (scene := self.scene()) == Scene.TERMINAL_MAIN: if (scene := self.scene()) == Scene.TERMINAL_MAIN:
self.terminal_entry("navigation/activity/terminal.jpg") self.terminal_entry("navigation/activity/terminal.jpg")
elif scene == Scene.ACTIVITY_MAIN: elif scene == Scene.ACTIVITY_MAIN:
self.tap("navigation/activity/entry") self.tap(f"navigation/activity/entry_{self.difficulty}")
elif scene == Scene.ACTIVITY_CHOOSE_LEVEL: elif scene in [
Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL,
Scene.ACTIVITY_EX_CHOOSE_LEVEL,
]:
if ( if (
self.mode == "copy" self.mode == "copy"
and (result := config.recog.match("story_stage")) and (result := config.recog.match("story_stage"))
@ -86,7 +103,10 @@ class ActivityNavigation(SceneGraphSolver):
name = n name = n
logger.debug(f"{loc}找到关卡{name}") logger.debug(f"{loc}找到关卡{name}")
target = va(vs(loc, self.location[name]), self.location[self.name]) target = va(
vs(loc, self.location[self.difficulty][name]),
self.location[self.difficulty][self.name],
)
if target[0] + 200 > 1920: if target[0] + 200 > 1920:
self.swipe_noinertia((1400, 540), (-1000, 0)) self.swipe_noinertia((1400, 540), (-1000, 0))
elif target[0] < 0: elif target[0] < 0:

View file

@ -48,6 +48,7 @@ class MuMu12IPC:
self.instanse_index = int(config.conf.emulator.index) self.instanse_index = int(config.conf.emulator.index)
self.connection = 0 self.connection = 0
self.display_id = -1 self.display_id = -1
self.pixels = (ctypes.c_ubyte * 8294400)()
# 加载动态链接库 # 加载动态链接库
dll_path = os.path.join( dll_path = os.path.join(
self.emulator_folder, "sdk", "external_renderer_ipc.dll" self.emulator_folder, "sdk", "external_renderer_ipc.dll"
@ -170,22 +171,24 @@ class MuMu12IPC:
def capture_display(self) -> np.ndarray: def capture_display(self) -> np.ndarray:
self.check_status() self.check_status()
pixels = (ctypes.c_ubyte * 8294400)()
result = self.external_renderer.nemu_capture_display( result = self.external_renderer.nemu_capture_display(
self.connection, self.connection,
self.display_id, self.display_id,
8294400, 8294400,
ctypes.byref(ctypes.c_int(1920)), ctypes.byref(ctypes.c_int(1920)),
ctypes.byref(ctypes.c_int(1080)), ctypes.byref(ctypes.c_int(1080)),
pixels, self.pixels,
) )
if result != 0: if result != 0:
logger.error(f"获取截图失败: {result}")
self.connection = 0 self.connection = 0
self.display_id = -1 self.display_id = -1
config.device.exit() # 可能是游戏卡死 config.device.exit() # 可能是游戏卡死
return self.capture_display() return np.zeros((1080, 1920, 3), dtype=np.uint8)
image = np.frombuffer(pixels, dtype=np.uint8).reshape((1080, 1920, 4))[:, :, :3] image = np.frombuffer(self.pixels, dtype=np.uint8).reshape((1080, 1920, 4))[
:, :, :3
]
image = np.flipud(image) # 翻转 image = np.flipud(image) # 翻转
return image return image

View file

@ -48,7 +48,8 @@ from .utils import edge
@edge(Scene.SSS_MAIN, Scene.NAVIGATION_BAR) @edge(Scene.SSS_MAIN, Scene.NAVIGATION_BAR)
@edge(Scene.SSS_START, Scene.NAVIGATION_BAR) @edge(Scene.SSS_START, Scene.NAVIGATION_BAR)
@edge(Scene.ACTIVITY_MAIN, Scene.NAVIGATION_BAR) @edge(Scene.ACTIVITY_MAIN, Scene.NAVIGATION_BAR)
@edge(Scene.ACTIVITY_CHOOSE_LEVEL, Scene.NAVIGATION_BAR) @edge(Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL, Scene.NAVIGATION_BAR)
@edge(Scene.ACTIVITY_EX_CHOOSE_LEVEL, Scene.NAVIGATION_BAR)
@edge(Scene.OPERATOR_MANAGEMENT, Scene.NAVIGATION_BAR) @edge(Scene.OPERATOR_MANAGEMENT, Scene.NAVIGATION_BAR)
@edge(Scene.OPERATOR_DETAILS, Scene.NAVIGATION_BAR) @edge(Scene.OPERATOR_DETAILS, Scene.NAVIGATION_BAR)
@edge(Scene.ROGUE_INDEX, Scene.NAVIGATION_BAR) @edge(Scene.ROGUE_INDEX, Scene.NAVIGATION_BAR)

View file

@ -13,7 +13,7 @@ from .utils import edge
@edge(Scene.OPERATOR_CHOOSE_LEVEL, Scene.TERMINAL_BIOGRAPHY) @edge(Scene.OPERATOR_CHOOSE_LEVEL, Scene.TERMINAL_BIOGRAPHY)
@edge(Scene.OPERATOR_CHOOSE_LEVEL, Scene.TERMINAL_COLLECTION) @edge(Scene.OPERATOR_CHOOSE_LEVEL, Scene.TERMINAL_COLLECTION)
@edge(Scene.ACTIVITY_MAIN, Scene.TERMINAL_MAIN) @edge(Scene.ACTIVITY_MAIN, Scene.TERMINAL_MAIN)
@edge(Scene.ACTIVITY_CHOOSE_LEVEL, Scene.ACTIVITY_MAIN) @edge(Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL, Scene.ACTIVITY_MAIN)
@edge(Scene.OPERATOR_SUPPORT, Scene.OPERATOR_SELECT) @edge(Scene.OPERATOR_SUPPORT, Scene.OPERATOR_SELECT)
@edge(Scene.OPERATOR_AGENT_SELECT, Scene.OPERATOR_SELECT) @edge(Scene.OPERATOR_AGENT_SELECT, Scene.OPERATOR_SELECT)
@edge(Scene.OPERATOR_SUPPORT_AGENT, Scene.OPERATOR_SUPPORT) @edge(Scene.OPERATOR_SUPPORT_AGENT, Scene.OPERATOR_SUPPORT)
@ -22,6 +22,11 @@ def operation_back(solver: BaseSolver):
solver.back() solver.back()
@edge(Scene.OPERATOR_BAN, Scene.OPERATOR_SELECT)
def operation_ban(solver: BaseSolver):
solver.ctap((500, 900), 3)
@edge(Scene.OPERATOR_FIGHT, Scene.OPERATOR_GIVEUP) @edge(Scene.OPERATOR_FIGHT, Scene.OPERATOR_GIVEUP)
def operation_fight(solver: BaseSolver): def operation_fight(solver: BaseSolver):
solver.ctap("fight/gear", 3) solver.ctap("fight/gear", 3)

View file

@ -160,6 +160,8 @@ class Recognizer:
self.scene = Scene.ROGUE_SELECT self.scene = Scene.ROGUE_SELECT
elif self.find("choose_agent/fast_select"): elif self.find("choose_agent/fast_select"):
self.scene = Scene.OPERATOR_SELECT self.scene = Scene.OPERATOR_SELECT
elif self.find("fight/ban"):
self.scene = Scene.OPERATOR_BAN
elif self.find("ope_eliminate"): elif self.find("ope_eliminate"):
self.scene = Scene.OPERATOR_ELIMINATE self.scene = Scene.OPERATOR_ELIMINATE
elif self.find("ope_elimi_agency_panel"): elif self.find("ope_elimi_agency_panel"):
@ -316,10 +318,12 @@ class Recognizer:
self.scene = Scene.SIGN_IN_DAILY self.scene = Scene.SIGN_IN_DAILY
# elif self.find("sign_in/moon_festival/banner"): # elif self.find("sign_in/moon_festival/banner"):
# self.scene = Scene.MOON_FESTIVAL # self.scene = Scene.MOON_FESTIVAL
elif self.find("navigation/activity/entry"): elif self.find("navigation/activity/entry_normal"):
self.scene = Scene.ACTIVITY_MAIN self.scene = Scene.ACTIVITY_MAIN
elif self.find("navigation/activity/banner"): elif self.find("navigation/activity/banner_normal"):
self.scene = Scene.ACTIVITY_CHOOSE_LEVEL self.scene = Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL
elif self.find("navigation/activity/banner_ex"):
self.scene = Scene.ACTIVITY_EX_CHOOSE_LEVEL
elif self.find("rogue/theme_select"): elif self.find("rogue/theme_select"):
self.scene = Scene.ROGUE_THEME_SELECT self.scene = Scene.ROGUE_THEME_SELECT
elif ( elif (
@ -357,7 +361,9 @@ class Recognizer:
self.scene = Scene.LOADING self.scene = Scene.LOADING
elif self.find("loading4"): elif self.find("loading4"):
self.scene = Scene.LOADING self.scene = Scene.LOADING
elif self.find("ope_plan") and self.find("ope_start"): elif self.find("ope_plan") and (
self.find("ope_start") or self.find("ope_ex_start")
):
self.scene = Scene.OPERATOR_BEFORE self.scene = Scene.OPERATOR_BEFORE
elif self.find("navigation/episode"): elif self.find("navigation/episode"):
self.scene = Scene.OPERATOR_CHOOSE_LEVEL self.scene = Scene.OPERATOR_CHOOSE_LEVEL

View file

@ -41,6 +41,7 @@ color = {
"double_confirm/voice": (745, 435), "double_confirm/voice": (745, 435),
"drone": (274, 437), "drone": (274, 437),
"factory_collect": (1542, 886), "factory_collect": (1542, 886),
"fight/ban": (976, 268),
"fight/breach": (1246, 23), "fight/breach": (1246, 23),
"fight/collection": (1088, 25), "fight/collection": (1088, 25),
"fight/collection_on": (1084, 22), "fight/collection_on": (1084, 22),
@ -68,8 +69,10 @@ color = {
"mission_trainee_on": (690, 17), "mission_trainee_on": (690, 17),
"nav_bar": (655, 0), "nav_bar": (655, 0),
"nav_button": (26, 20), "nav_button": (26, 20),
"navigation/activity/banner": (1490, 935), "navigation/activity/banner_ex": (1691, 944),
"navigation/activity/entry": (1542, 700), "navigation/activity/banner_normal": (1490, 935),
"navigation/activity/entry_ex": (1486, 891),
"navigation/activity/entry_normal": (1542, 700),
"navigation/collection/AP-1": (203, 821), "navigation/collection/AP-1": (203, 821),
"navigation/collection/CA-1": (203, 821), "navigation/collection/CA-1": (203, 821),
"navigation/collection/CE-1": (243, 822), "navigation/collection/CE-1": (243, 822),

View file

@ -205,6 +205,8 @@ class Scene:
"代理失误确认" "代理失误确认"
RESTORE_ALL_SANITY = 620 RESTORE_ALL_SANITY = 620
"首次失败返还全部理智" "首次失败返还全部理智"
OPERATOR_BAN = 621
"禁止干员出战"
SHOP_OTHERS = 701 SHOP_OTHERS = 701
"商店其它界面" "商店其它界面"
SHOP_CREDIT = 702 SHOP_CREDIT = 702
@ -341,8 +343,10 @@ class Scene:
"仓库" "仓库"
ACTIVITY_MAIN = 1401 ACTIVITY_MAIN = 1401
"活动主界面" "活动主界面"
ACTIVITY_CHOOSE_LEVEL = 1402 ACTIVITY_NORMAL_CHOOSE_LEVEL = 1402
"活动关选择" "活动普通关选择"
ACTIVITY_EX_CHOOSE_LEVEL = 1403
"活动EX关选择"
SIGN_IN_DAILY = 1501 SIGN_IN_DAILY = 1501
"签到活动" "签到活动"
MOON_FESTIVAL = 1502 MOON_FESTIVAL = 1502
@ -473,6 +477,7 @@ SceneComment = {
618: "作战中", 618: "作战中",
619: "代理失误确认", 619: "代理失误确认",
620: "首次失败返还全部理智", 620: "首次失败返还全部理智",
621: "禁止干员出战",
701: "商店其它界面", 701: "商店其它界面",
702: "信用交易所", 702: "信用交易所",
703: "信用交易所兑换确认", 703: "信用交易所兑换确认",
@ -541,7 +546,8 @@ SceneComment = {
1203: "限定池单抽结果", 1203: "限定池单抽结果",
1301: "仓库", 1301: "仓库",
1401: "活动主界面", 1401: "活动主界面",
1402: "活动关选择", 1402: "活动普通关选择",
1403: "活动EX关选择",
1501: "签到活动", 1501: "签到活动",
1502: "月饼", 1502: "月饼",
1503: "幸运墙签到", 1503: "幸运墙签到",

View file

@ -95,6 +95,7 @@ Res = Literal[
"factory_accelerate", "factory_accelerate",
"factory_collect", "factory_collect",
"fight/attack", "fight/attack",
"fight/ban",
"fight/breach", "fight/breach",
"fight/c", "fight/c",
"fight/c_mask", "fight/c_mask",
@ -175,8 +176,10 @@ Res = Literal[
"navigation/act/0", "navigation/act/0",
"navigation/act/1", "navigation/act/1",
"navigation/act/2", "navigation/act/2",
"navigation/activity/banner", "navigation/activity/banner_ex",
"navigation/activity/entry", "navigation/activity/banner_normal",
"navigation/activity/entry_ex",
"navigation/activity/entry_normal",
"navigation/activity/terminal.jpg", "navigation/activity/terminal.jpg",
"navigation/biography/OF_banner", "navigation/biography/OF_banner",
"navigation/biography/OF_entry", "navigation/biography/OF_entry",