mower-ng/mower/solvers/navigation/activity.py
zhbaor 7a38c245a8
All checks were successful
ci/woodpecker/push/check_format Pipeline was successful
生路复刻关卡导航+奖励领取+活动商店
2025-06-19 16:54:17 +08:00

146 lines
4.7 KiB
Python

from datetime import datetime
from typing import Literal
import cv2
from mower.utils import config
from mower.utils.log import logger
from mower.utils.scene import Scene
from mower.utils.solver import BaseSolver
from mower.utils.vector import va, vs
from .utils import generate_name
class classproperty:
def __init__(self, method=None):
self.fget = method
def __get__(self, instance, cls=None):
return self.fget(cls)
def getter(self, method):
self.fget = method
return self
class ActivityNavigation(BaseSolver):
solver_name = "活动关卡导航"
_location = {
"normal": {
"BP-1": (0, 0),
"BP-2": (428, 76),
"BP-3": (690, -67),
"BP-4": (956, 48),
"BP-5": (1221, 160),
"BP-6": (1550, 1),
"BP-7": (1791, 471),
"BP-8": (2001, 341),
},
"ex": {},
}
@classproperty
def location(cls):
result = {"normal": {}, "ex": {}}
if (now := datetime.now()) < datetime(2025, 6, 29, 4):
result["normal"] = cls._location["normal"]
if now > datetime(2025, 6, 12, 16):
result["ex"] = cls._location["ex"]
return result
def generate_names(self):
names = {}
font_size = 37 if self.difficulty == "ex" else 40
for name in self._location[self.difficulty].keys():
style = "dark" if "TR-" in self.name else "light"
names[name] = generate_name(name, font_size, pad_right=10, style=style)
self.names = names
def run(
self,
name: str,
mode: Literal["auto", "copy"] = "auto",
switch_to_ex: bool = False,
) -> None:
logger.info("导航至活动关卡")
self.switch_to_ex = switch_to_ex # 是否切换到突袭模式
self.difficulty = "ex" if "-EX-" in name else "normal"
self.name = name
self.mode = mode
self.generate_names()
super().run()
return True
def transition(self) -> bool:
if (scene := self.scene()) == Scene.TERMINAL_MAIN:
self.terminal_entry("navigation/activity/terminal.jpg")
elif scene == Scene.ACTIVITY_MAIN:
self.ctap(f"navigation/activity/entry_{self.difficulty}", 5)
elif scene in [
Scene.ACTIVITY_NORMAL_CHOOSE_LEVEL,
Scene.ACTIVITY_EX_CHOOSE_LEVEL,
]:
if (
self.mode == "copy"
and (result := config.recog.match("story_stage"))
and result[0] > 0.8
):
self.ctap(result[1], 3)
return
name, val, loc = None, 1, None
for n, img in self.names.items():
result = cv2.matchTemplate(config.recog.gray, img, cv2.TM_SQDIFF_NORMED)
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
if min_val < val:
val = min_val
loc = min_loc
name = n
logger.debug(f"{loc}找到关卡{name}")
target = va(
vs(loc, self.location[self.difficulty][name]),
self.location[self.difficulty][self.name],
)
if target[0] > 1920:
self.swipe_ext(
[(1400, 540), (400, 540), (400, 800)], [200, 300], 0, 0.1
)
elif target[0] < 0:
self.swipe_ext(
[(400, 540), (1400, 540), (1400, 800)], [200, 300], 0, 0.1
)
else:
self.ctap(va(target, (60, 20)), 6)
elif scene == Scene.OPERATOR_BEFORE:
if self.find("ope_ex_mode") and self.switch_to_ex:
self.ctap("ope_ex_mode", 3)
return
if self.mode == "auto":
return True
elif self.mode == "copy":
if not self.switch_to_ex:
if config.recog.gray[65][1333] < 200:
self.sleep()
return
# 取消代理作战
if config.recog.gray[907][1600] > 127 and not self.find(
"ope_agency_lock"
):
self.ctap((1776, 908), 3)
return
self.ctap("ope_start", 3)
else:
self.ctap("ope_ex_start", 3)
elif scene == Scene.OPERATOR_SELECT and self.mode == "copy":
return True
elif scene in [Scene.OPERATOR_RECOVER_ORIGINITE, Scene.OPERATOR_RECOVER_POTION]:
return True
elif scene == Scene.STORY_STAGE:
self.tap("start_story")
else:
self.scene_graph_step(Scene.TERMINAL_MAIN)