mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-16 06:25:24 +00:00
commit
ae55e91a92
@ -273,7 +273,7 @@ class ModuleBase:
|
|||||||
Returns:
|
Returns:
|
||||||
Button: Or None if nothing matched.
|
Button: Or None if nothing matched.
|
||||||
"""
|
"""
|
||||||
image = color_similarity_2d(self.image_crop(area), color=color)
|
image = color_similarity_2d(self.image_crop(area, copy=False), color=color)
|
||||||
points = np.array(np.where(image > color_threshold)).T[:, ::-1]
|
points = np.array(np.where(image > color_threshold)).T[:, ::-1]
|
||||||
if points.shape[0] < encourage ** 2:
|
if points.shape[0] < encourage ** 2:
|
||||||
# Not having enough pixels to match
|
# Not having enough pixels to match
|
||||||
|
@ -385,15 +385,21 @@ class Connection(ConnectionAttr):
|
|||||||
Returns:
|
Returns:
|
||||||
list[str]: ['nc'] or ['busybox', 'nc']
|
list[str]: ['nc'] or ['busybox', 'nc']
|
||||||
"""
|
"""
|
||||||
sdk = self.sdk_ver
|
if self.is_emulator:
|
||||||
logger.info(f'sdk_ver: {sdk}')
|
sdk = self.sdk_ver
|
||||||
if sdk >= 28:
|
logger.info(f'sdk_ver: {sdk}')
|
||||||
# Android 9 emulators does not have `nc`, try `busybox nc`
|
if sdk >= 28:
|
||||||
# BlueStacks Pie (Android 9) has `nc` but cannot send data, try `busybox nc` first
|
# LD Player 9 does not have `nc`, try `busybox nc`
|
||||||
trial = [
|
# BlueStacks Pie (Android 9) has `nc` but cannot send data, try `busybox nc` first
|
||||||
['busybox', 'nc'],
|
trial = [
|
||||||
['nc'],
|
['busybox', 'nc'],
|
||||||
]
|
['nc'],
|
||||||
|
]
|
||||||
|
else:
|
||||||
|
trial = [
|
||||||
|
['nc'],
|
||||||
|
['busybox', 'nc'],
|
||||||
|
]
|
||||||
else:
|
else:
|
||||||
trial = [
|
trial = [
|
||||||
['nc'],
|
['nc'],
|
||||||
@ -401,8 +407,9 @@ class Connection(ConnectionAttr):
|
|||||||
]
|
]
|
||||||
for command in trial:
|
for command in trial:
|
||||||
# About 3ms
|
# About 3ms
|
||||||
result = self.adb_shell(command)
|
|
||||||
# Result should be command help if success
|
# Result should be command help if success
|
||||||
|
# nc: bad argument count (see "nc --help")
|
||||||
|
result = self.adb_shell(command)
|
||||||
# `/system/bin/sh: nc: not found`
|
# `/system/bin/sh: nc: not found`
|
||||||
if 'not found' in result:
|
if 'not found' in result:
|
||||||
continue
|
continue
|
||||||
|
@ -68,6 +68,10 @@ class ConnectionAttr:
|
|||||||
res = re.search(r'(127\.\d+\.\d+\.\d+:\d+)', serial)
|
res = re.search(r'(127\.\d+\.\d+\.\d+:\d+)', serial)
|
||||||
if res:
|
if res:
|
||||||
serial = res.group(1)
|
serial = res.group(1)
|
||||||
|
# 12127.0.0.1:16384
|
||||||
|
serial = serial.replace('12127.0.0.1', '127.0.0.1')
|
||||||
|
# auto127.0.0.1:16384
|
||||||
|
serial = serial.replace('auto127.0.0.1', '127.0.0.1').replace('autoemulator', 'emulator')
|
||||||
return str(serial)
|
return str(serial)
|
||||||
|
|
||||||
def serial_check(self):
|
def serial_check(self):
|
||||||
|
@ -228,7 +228,7 @@ class AssignmentUI(UI):
|
|||||||
logger.info('Event completed')
|
logger.info('Event completed')
|
||||||
break
|
break
|
||||||
if self.appear(ASSIGNMENT_CHECK) and \
|
if self.appear(ASSIGNMENT_CHECK) and \
|
||||||
self.image_color_count(ENTRY_LOADED, (35, 35, 35), count=800):
|
self.image_color_count(ENTRY_LOADED, (35, 35, 35), count=400):
|
||||||
logger.info('Entry loaded')
|
logger.info('Entry loaded')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -122,7 +122,7 @@ class CharacterSwitch(UI):
|
|||||||
expected_peaks = np.array([201, 279, 357, 435])
|
expected_peaks = np.array([201, 279, 357, 435])
|
||||||
expected_peaks_in_area = expected_peaks - area[1]
|
expected_peaks_in_area = expected_peaks - area[1]
|
||||||
# Use Luminance to fit H264 video stream
|
# Use Luminance to fit H264 video stream
|
||||||
image = rgb2luma(crop(self.device.image, area))
|
image = rgb2luma(crop(self.device.image, area, copy=False))
|
||||||
# Remove character names
|
# Remove character names
|
||||||
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
|
||||||
image = cv2.erode(image, kernel)
|
image = cv2.erode(image, kernel)
|
||||||
|
@ -2,6 +2,7 @@ from module.base.decorator import run_once
|
|||||||
from module.exception import RequestHumanTakeover
|
from module.exception import RequestHumanTakeover
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
|
from tasks.combat.assets.assets_combat_finish import COMBAT_AGAIN, COMBAT_EXIT
|
||||||
|
from tasks.combat.assets.assets_combat_interact import DUNGEON_COMBAT_INTERACT
|
||||||
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
|
from tasks.combat.assets.assets_combat_prepare import COMBAT_PREPARE
|
||||||
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT
|
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_PREPARE, COMBAT_TEAM_SUPPORT
|
||||||
from tasks.combat.interact import CombatInteract
|
from tasks.combat.interact import CombatInteract
|
||||||
@ -126,7 +127,7 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
|||||||
self.interval_reset(COMBAT_PREPARE)
|
self.interval_reset(COMBAT_PREPARE)
|
||||||
self.map_A_timer.reset()
|
self.map_A_timer.reset()
|
||||||
if self.appear(COMBAT_PREPARE, interval=2):
|
if self.appear(COMBAT_PREPARE, interval=2):
|
||||||
if self.obtained_is_full(self.dungeon, wave_done=self.combat_wave_done):
|
if self.is_doing_planner and self.obtained_is_full(self.dungeon, wave_done=self.combat_wave_done):
|
||||||
# Update stamina so task can be delayed if both obtained_is_full and stamina exhausted
|
# Update stamina so task can be delayed if both obtained_is_full and stamina exhausted
|
||||||
self.combat_get_trailblaze_power()
|
self.combat_get_trailblaze_power()
|
||||||
return False
|
return False
|
||||||
@ -136,11 +137,13 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
|||||||
self.interval_reset(COMBAT_PREPARE)
|
self.interval_reset(COMBAT_PREPARE)
|
||||||
trial += 1
|
trial += 1
|
||||||
continue
|
continue
|
||||||
if self.handle_combat_interact():
|
if self.appear(DUNGEON_COMBAT_INTERACT):
|
||||||
self.map_A_timer.reset()
|
if self.handle_combat_interact():
|
||||||
continue
|
self.map_A_timer.reset()
|
||||||
if self.handle_ascension_dungeon_prepare():
|
continue
|
||||||
continue
|
else:
|
||||||
|
if self.handle_ascension_dungeon_prepare():
|
||||||
|
continue
|
||||||
if self.handle_popup_confirm():
|
if self.handle_popup_confirm():
|
||||||
continue
|
continue
|
||||||
|
|
||||||
@ -303,7 +306,8 @@ class Combat(CombatInteract, CombatPrepare, CombatState, CombatTeam, CombatSuppo
|
|||||||
if self.appear(COMBAT_AGAIN, interval=5):
|
if self.appear(COMBAT_AGAIN, interval=5):
|
||||||
add_wave_done()
|
add_wave_done()
|
||||||
# Update obtain_frequent_check
|
# Update obtain_frequent_check
|
||||||
self.obtained_is_full(dungeon=self.dungeon, wave_done=self.combat_wave_done, obtain_get=False)
|
if self.is_doing_planner:
|
||||||
|
self.obtained_is_full(dungeon=self.dungeon, wave_done=self.combat_wave_done, obtain_get=False)
|
||||||
# Cache the result of _combat_can_again() as no expected stamina reduce during retry
|
# Cache the result of _combat_can_again() as no expected stamina reduce during retry
|
||||||
if combat_can_again is None:
|
if combat_can_again is None:
|
||||||
combat_can_again = self._combat_can_again()
|
combat_can_again = self._combat_can_again()
|
||||||
|
@ -47,7 +47,7 @@ class CombatSkill(UI):
|
|||||||
break
|
break
|
||||||
# New skill icon
|
# New skill icon
|
||||||
if prev_image is not None:
|
if prev_image is not None:
|
||||||
if not match_template(self.image_crop(button), prev_image):
|
if not match_template(self.image_crop(button, copy=False), prev_image):
|
||||||
logger.info(f'Skill used: {button} (icon changed)')
|
logger.info(f'Skill used: {button} (icon changed)')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ class CombatState(UI):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
def _is_combat_button_active(self, button):
|
def _is_combat_button_active(self, button):
|
||||||
image = rgb2luma(self.image_crop(button))
|
image = rgb2luma(self.image_crop(button, copy=False))
|
||||||
lines = cv2.reduce(image, 1, cv2.REDUCE_AVG).flatten()
|
lines = cv2.reduce(image, 1, cv2.REDUCE_AVG).flatten()
|
||||||
# [122 122 122 182 141 127 139 135 130 135 136 141 147 149 149 150 147 145
|
# [122 122 122 182 141 127 139 135 130 135 136 141 147 149 149 150 147 145
|
||||||
# 148 150 150 150 150 150 144 138 134 141 136 133 173 183 130 128 127 126]
|
# 148 150 150 150 150 150 144 138 134 141 136 133 173 183 130 128 127 126]
|
||||||
|
@ -30,7 +30,7 @@ class SupportCharacter:
|
|||||||
def __init__(self, name, screenshot, similarity=0.75):
|
def __init__(self, name, screenshot, similarity=0.75):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.image = self._scale_character()
|
self.image = self._scale_character()
|
||||||
self.screenshot = crop(screenshot, SupportCharacter._crop_area)
|
self.screenshot = crop(screenshot, SupportCharacter._crop_area, copy=False)
|
||||||
self.similarity = similarity
|
self.similarity = similarity
|
||||||
self.button = self._find_character()
|
self.button = self._find_character()
|
||||||
|
|
||||||
|
@ -33,10 +33,10 @@ class DailyQuestOcr(Ocr):
|
|||||||
|
|
||||||
def pre_process(self, image):
|
def pre_process(self, image):
|
||||||
image = super().pre_process(image)
|
image = super().pre_process(image)
|
||||||
image = crop(image, OCR_DAILY_QUEST.area)
|
image = crop(image, OCR_DAILY_QUEST.area, copy=False)
|
||||||
mask = MASK_DAILY_QUEST.matched_button.image
|
mask = MASK_DAILY_QUEST.matched_button.image
|
||||||
# Remove "+200Activity"
|
# Remove "+200Activity"
|
||||||
cv2.bitwise_and(image, mask, dst=image)
|
image = cv2.bitwise_and(image, mask)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
def after_process(self, result):
|
def after_process(self, result):
|
||||||
|
@ -39,7 +39,7 @@ class DungeonState(UI):
|
|||||||
)
|
)
|
||||||
|
|
||||||
ocr = OcrSimUniPoint(OCR_SIMUNI_POINT)
|
ocr = OcrSimUniPoint(OCR_SIMUNI_POINT)
|
||||||
value, _, total = ocr.ocr_single_line(crop(image, area), direct_ocr=True)
|
value, _, total = ocr.ocr_single_line(crop(image, area, copy=False), direct_ocr=True)
|
||||||
if total and value <= total:
|
if total and value <= total:
|
||||||
logger.attr('SimulatedUniverse', f'{value}/{total}')
|
logger.attr('SimulatedUniverse', f'{value}/{total}')
|
||||||
self.config.stored.SimulatedUniverse.set(value, total)
|
self.config.stored.SimulatedUniverse.set(value, total)
|
||||||
|
@ -334,7 +334,7 @@ class DungeonUI(DungeonState):
|
|||||||
|
|
||||||
# Check if having any content
|
# Check if having any content
|
||||||
# List background: 254, guild border: 225
|
# List background: 254, guild border: 225
|
||||||
r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK))
|
r, g, b = cv2.split(self.image_crop(LIST_LOADED_CHECK, copy=False))
|
||||||
minimum = cv2.min(cv2.min(r, g), b)
|
minimum = cv2.min(cv2.min(r, g), b)
|
||||||
minimum = inrange(minimum, lower=0, upper=180)
|
minimum = inrange(minimum, lower=0, upper=180)
|
||||||
if minimum.size > 100:
|
if minimum.size > 100:
|
||||||
|
@ -35,7 +35,7 @@ class ForgottenHallTeam(UI):
|
|||||||
continue
|
continue
|
||||||
|
|
||||||
def is_character_chosen(self, button: ButtonWrapper) -> bool:
|
def is_character_chosen(self, button: ButtonWrapper) -> bool:
|
||||||
image = color_similarity_2d(self.image_crop(button), color=(255, 255, 255))
|
image = color_similarity_2d(self.image_crop(button, copy=False), color=(255, 255, 255))
|
||||||
color = cv2.mean(image)[0]
|
color = cv2.mean(image)[0]
|
||||||
# print(button, color)
|
# print(button, color)
|
||||||
# Chosen:
|
# Chosen:
|
||||||
|
@ -23,7 +23,7 @@ class ForgottenHallStageOcr(Ocr):
|
|||||||
def _find_number(self, image):
|
def _find_number(self, image):
|
||||||
raw = image.copy()
|
raw = image.copy()
|
||||||
area = OCR_STAGE.area
|
area = OCR_STAGE.area
|
||||||
image = crop(raw, area)
|
image = crop(raw, area, copy=False)
|
||||||
yellow = color_similarity_2d(image, color=(255, 200, 112))
|
yellow = color_similarity_2d(image, color=(255, 200, 112))
|
||||||
gray = color_similarity_2d(image, color=(100, 109, 134))
|
gray = color_similarity_2d(image, color=(100, 109, 134))
|
||||||
image = np.maximum(yellow, gray)
|
image = np.maximum(yellow, gray)
|
||||||
|
@ -56,11 +56,11 @@ class Synthesize(CombatObtain):
|
|||||||
Pages:
|
Pages:
|
||||||
in: page_synthesize
|
in: page_synthesize
|
||||||
"""
|
"""
|
||||||
image = self.image_crop(button)
|
image = self.image_crop(button, copy=False)
|
||||||
image = cv2.GaussianBlur(image, (3, 3), 0)
|
image = cv2.GaussianBlur(image, (3, 3), 0)
|
||||||
x2, y2 = image_size(image)
|
x2, y2 = image_size(image)
|
||||||
y1 = y2 - int(y2 // 4)
|
y1 = y2 - int(y2 // 4)
|
||||||
image = crop(image, (0, y1, x2, y2))
|
image = crop(image, (0, y1, x2, y2), copy=False)
|
||||||
# self.device.image_show(image)
|
# self.device.image_show(image)
|
||||||
# print(image.shape)
|
# print(image.shape)
|
||||||
|
|
||||||
|
@ -150,7 +150,7 @@ class Minimap(MapResource):
|
|||||||
# Image.fromarray((local_maximum * 255).astype(np.uint8)).save('local_maximum.png')
|
# Image.fromarray((local_maximum * 255).astype(np.uint8)).save('local_maximum.png')
|
||||||
|
|
||||||
# Calculate the precise location using CUBIC
|
# Calculate the precise location using CUBIC
|
||||||
# precise = crop(result, area=area_offset((-4, -4, 4, 4), offset=local_loca))
|
# precise = crop(result, area=area_offset((-4, -4, 4, 4), offset=local_loca), copy=False)
|
||||||
# precise_sim, precise_loca = cubic_find_maximum(precise, precision=0.05)
|
# precise_sim, precise_loca = cubic_find_maximum(precise, precision=0.05)
|
||||||
# precise_loca -= 5
|
# precise_loca -= 5
|
||||||
precise_loca = np.array((0, 0))
|
precise_loca = np.array((0, 0))
|
||||||
@ -190,7 +190,7 @@ class Minimap(MapResource):
|
|||||||
loca = state.loca
|
loca = state.loca
|
||||||
local_loca = state.local_loca
|
local_loca = state.local_loca
|
||||||
|
|
||||||
precise = crop(result, area=area_offset((-4, -4, 4, 4), offset=loca))
|
precise = crop(result, area=area_offset((-4, -4, 4, 4), offset=loca), copy=False)
|
||||||
precise_sim, precise_loca = cubic_find_maximum(precise, precision=0.05)
|
precise_sim, precise_loca = cubic_find_maximum(precise, precision=0.05)
|
||||||
precise_loca -= 5
|
precise_loca -= 5
|
||||||
|
|
||||||
@ -265,7 +265,7 @@ class Minimap(MapResource):
|
|||||||
logger.warning('No direction arrow on minimap')
|
logger.warning('No direction arrow on minimap')
|
||||||
return
|
return
|
||||||
|
|
||||||
image = crop(image, area=area)
|
image = crop(image, area=area, copy=False)
|
||||||
scale = self.DIRECTION_ROTATION_SCALE * self.DIRECTION_SEARCH_SCALE
|
scale = self.DIRECTION_ROTATION_SCALE * self.DIRECTION_SEARCH_SCALE
|
||||||
mapping = cv2.resize(image, None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST)
|
mapping = cv2.resize(image, None, fx=scale, fy=scale, interpolation=cv2.INTER_NEAREST)
|
||||||
result = cv2.matchTemplate(self.ArrowRotateMap, mapping, cv2.TM_CCOEFF_NORMED)
|
result = cv2.matchTemplate(self.ArrowRotateMap, mapping, cv2.TM_CCOEFF_NORMED)
|
||||||
|
@ -55,7 +55,7 @@ class ResourceGenerator(ResourceConst):
|
|||||||
arrows = {}
|
arrows = {}
|
||||||
for degree in range(0, 360):
|
for degree in range(0, 360):
|
||||||
rotated = rotate_bound(image, degree)
|
rotated = rotate_bound(image, degree)
|
||||||
rotated = crop(rotated, area=get_bbox(rotated, threshold=15))
|
rotated = crop(rotated, area=get_bbox(rotated, threshold=15), copy=False)
|
||||||
# rotated = cv2.resize(rotated, None, fx=self.ROTATE, fy=self.ROTATE, interpolation=cv2.INTER_NEAREST)
|
# rotated = cv2.resize(rotated, None, fx=self.ROTATE, fy=self.ROTATE, interpolation=cv2.INTER_NEAREST)
|
||||||
rotated = color_similarity_2d(rotated, color=self.DIRECTION_ARROW_COLOR)
|
rotated = color_similarity_2d(rotated, color=self.DIRECTION_ARROW_COLOR)
|
||||||
arrows[degree] = rotated
|
arrows[degree] = rotated
|
||||||
|
@ -101,7 +101,7 @@ class MapResource(ResourceConst):
|
|||||||
Crop the minimap area on image.
|
Crop the minimap area on image.
|
||||||
"""
|
"""
|
||||||
area = area_offset((-radius, -radius, radius, radius), offset=self.MINIMAP_CENTER)
|
area = area_offset((-radius, -radius, radius, radius), offset=self.MINIMAP_CENTER)
|
||||||
image = crop(image, area)
|
image = crop(image, area, copy=False)
|
||||||
return image
|
return image
|
||||||
|
|
||||||
def get_circle_mask(self, image):
|
def get_circle_mask(self, image):
|
||||||
|
Loading…
Reference in New Issue
Block a user