164 lines
5.7 KiB
Python
164 lines
5.7 KiB
Python
from datetime import datetime, timedelta
|
|
|
|
import cv2
|
|
|
|
from mower.data import agent_list
|
|
from mower.utils import config
|
|
from mower.utils import typealias as tp
|
|
from mower.utils.character_recognize import match_portrait
|
|
from mower.utils.graph import SceneGraphSolver
|
|
from mower.utils.image import cropimg, loadres, thres2
|
|
from mower.utils.log import logger
|
|
from mower.utils.recognize import Scene
|
|
from mower.utils.vector import ss, va
|
|
|
|
from .utils import generate_image
|
|
|
|
agent = [
|
|
"无需增调干员",
|
|
"PIONEER",
|
|
"WARRIOR",
|
|
"TANK",
|
|
"CASTER",
|
|
"SNIPER",
|
|
"MEDIC",
|
|
"SUPPORT",
|
|
"SPECIAL",
|
|
]
|
|
|
|
|
|
class SSSDROPSolver(SceneGraphSolver):
|
|
solver_name = "保全增调干员或仪器"
|
|
|
|
def run(self) -> bool:
|
|
copilot = config.works["sss"]
|
|
self.drops = copilot.drops
|
|
self.choose = False
|
|
self.blacklist = set(copilot.blacklist)
|
|
self.success = True
|
|
self.start_time = datetime.now()
|
|
super().run()
|
|
return self.success
|
|
|
|
def timeout(self) -> bool:
|
|
return datetime.now() > self.start_time + timedelta(seconds=20)
|
|
|
|
def find_EC(self, drop: str, fs: int, scope: tp.Scope):
|
|
img = cropimg(config.recog.gray, scope)
|
|
res = generate_image(drop, fs)
|
|
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED)
|
|
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
|
h, w = res.shape
|
|
logger.debug(f"drop:{drop},max_val:{max_val}")
|
|
if max_val > 0.8:
|
|
return va((max_loc[0], max_loc[1]), scope[0])
|
|
|
|
def find_PR_in_fight(self, drop: str, scope: tp.Scope):
|
|
img = cropimg(config.recog.img, scope)
|
|
res = loadres(f"sss/drop/{drop}")
|
|
res = cv2.resize(res, (61, 61), interpolation=cv2.INTER_LINEAR)
|
|
result = cv2.matchTemplate(img, res, cv2.TM_CCOEFF_NORMED)
|
|
min_val, max_val, min_loc, max_loc = cv2.minMaxLoc(result)
|
|
h, w, _ = res.shape
|
|
logger.debug(f"drop:{drop},max_val:{max_val}")
|
|
if max_val > 0.8:
|
|
return va((max_loc[0], max_loc[1]), scope[0])
|
|
|
|
def match_operators(self):
|
|
img = cropimg(config.recog.gray, ((50, 231), (1900, 850)))
|
|
img = thres2(img, 38)
|
|
contours, _ = cv2.findContours(img, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
|
|
rect = filter(
|
|
lambda x: x[2] > 200, map(lambda c: cv2.boundingRect(c), contours)
|
|
)
|
|
segment = []
|
|
for x, y, w, h in rect:
|
|
top_left = va((x, y), (50, 350))
|
|
bottom_right = va((x + w + 50, y + h + 231), (0, -230))
|
|
segment.append(ss(2 / 3, 2 / 3, (top_left, bottom_right)))
|
|
match_opers = dict(
|
|
match_portrait(
|
|
cv2.resize(config.recog.gray, (int(1920 / 1.5), int(1080 / 1.5))),
|
|
segment=segment,
|
|
)
|
|
)
|
|
logger.info(match_opers.keys())
|
|
res = {}
|
|
for name, scope in match_opers.items():
|
|
if name and name not in self.blacklist:
|
|
res[agent_list[name]["profession"]] = self.get_pos(ss(1.5, 1.5, scope))
|
|
logger.info(f"不在黑名单的干员:{res}")
|
|
return res
|
|
|
|
def transition(self):
|
|
if (scene := self.scene()) == Scene.SSS_DROP_AGENT_BEFORE_FIGHT:
|
|
if self.timeout():
|
|
self.success = False
|
|
return True
|
|
if self.choose and (
|
|
self.find("sss/drop_check") or self.find("sss/no_drop_check")
|
|
):
|
|
self.tap((1794, 900))
|
|
self.choose = False
|
|
self.sleep(2)
|
|
return
|
|
else:
|
|
opers = self.match_operators()
|
|
if pos := self.find("sss/drop/无需增调干员"):
|
|
opers["无需增调干员"] = pos
|
|
|
|
for drop in self.drops:
|
|
if drop in opers:
|
|
self.tap(opers[drop])
|
|
self.sleep(0.5)
|
|
self.choose = True
|
|
return
|
|
if len(opers):
|
|
self.tap(opers.popitem()[1])
|
|
self.sleep(0.5)
|
|
self.choose = True
|
|
return
|
|
|
|
elif scene == Scene.SSS_DROP_IN_FIGHT:
|
|
for drop in self.drops:
|
|
if drop not in agent:
|
|
if pos := self.find_EC(drop, 29, ((510, 700), (1480, 770))):
|
|
self.tap(pos)
|
|
self.sleep(0.5)
|
|
self.tap((1750, 550))
|
|
return
|
|
else:
|
|
if pos := self.find_PR_in_fight(drop, ((468, 735), (1321, 797))):
|
|
self.tap(pos)
|
|
self.sleep(0.5)
|
|
self.tap((1750, 550))
|
|
return
|
|
self.tap("sss/abandon")
|
|
|
|
elif scene == Scene.SSS_DROP_EC_BEFORE_FIGHT:
|
|
if self.timeout():
|
|
self.success = False
|
|
return True
|
|
if self.choose and self.find("sss/drop_check"):
|
|
self.tap((1794, 900))
|
|
return
|
|
else:
|
|
for drop in self.drops:
|
|
if drop not in agent:
|
|
if pos := self.find_EC(drop, 30, ((640, 630), (1280, 700))):
|
|
self.tap(pos)
|
|
self.sleep(0.5)
|
|
self.choose = True
|
|
return
|
|
|
|
elif scene == Scene.SSS_ABANDON_DROP_IN_FIGHT:
|
|
self.scene_graph_step(Scene.OPERATOR_FIGHT)
|
|
|
|
elif scene in [Scene.OPERATOR_FIGHT, Scene.SSS_ACTION]:
|
|
return True
|
|
|
|
elif scene in self.waiting_scene:
|
|
self.waiting_solver()
|
|
|
|
else:
|
|
return True
|