mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-21 16:28:17 +00:00
Fix: support (#64)
* Fix: support * Upd: support * Upd: support * Upd: support * Upd: support * Upd: support * Upd: support * Upd: support --------- Co-authored-by: LmeSzinc <lmeszincsales@gmail.com>
This commit is contained in:
parent
246c039dc8
commit
eb28485d5d
BIN
assets/support/selected_character_arrow.png
Normal file
BIN
assets/support/selected_character_arrow.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 668 B |
@ -1,23 +1,36 @@
|
|||||||
import cv2
|
import cv2
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from scipy import signal
|
from scipy import signal
|
||||||
|
from module.base.button import Button, ButtonWrapper
|
||||||
|
|
||||||
from module.base.timer import Timer
|
from module.base.timer import Timer
|
||||||
from module.base.utils import area_size, crop, rgb2luma, load_image
|
from module.base.utils import area_size, crop, rgb2luma, load_image, crop
|
||||||
from module.logger import logger
|
from module.logger import logger
|
||||||
from module.ui.scroll import Scroll
|
from module.ui.scroll import Scroll
|
||||||
|
from tasks.base.assets.assets_base_popup import CANCEL_POPUP
|
||||||
from tasks.base.ui import UI
|
from tasks.base.ui import UI
|
||||||
from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST, \
|
from tasks.combat.assets.assets_combat_support import COMBAT_SUPPORT_ADD, COMBAT_SUPPORT_LIST, \
|
||||||
COMBAT_SUPPORT_LIST_SCROLL, COMBAT_SUPPORT_SELECTED
|
COMBAT_SUPPORT_LIST_SCROLL, COMBAT_SUPPORT_SELECTED, COMBAT_SUPPORT_LIST_GRID
|
||||||
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT
|
from tasks.combat.assets.assets_combat_team import COMBAT_TEAM_SUPPORT, COMBAT_TEAM_DISMISSSUPPORT
|
||||||
|
|
||||||
|
|
||||||
|
def get_position_in_original_image(position_in_croped_image, crop_area):
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
tuple: (x, y) of position in original image
|
||||||
|
"""
|
||||||
|
return (
|
||||||
|
position_in_croped_image[0] + crop_area[0], position_in_croped_image[1] + crop_area[1]) if position_in_croped_image else None
|
||||||
|
|
||||||
|
|
||||||
class SupportCharacter:
|
class SupportCharacter:
|
||||||
_image_cache = {}
|
_image_cache = {}
|
||||||
|
_crop_area = COMBAT_SUPPORT_LIST_GRID.matched_button.area
|
||||||
|
|
||||||
def __init__(self, name, screenshot, similarity=0.85):
|
def __init__(self, name, screenshot, similarity=0.85):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.image = self._scale_character()
|
self.image = self._scale_character()
|
||||||
self.screenshot = screenshot
|
self.screenshot = crop(screenshot, SupportCharacter._crop_area)
|
||||||
self.similarity = similarity
|
self.similarity = similarity
|
||||||
self.button = self._find_character()
|
self.button = self._find_character()
|
||||||
|
|
||||||
@ -49,10 +62,12 @@ class SupportCharacter:
|
|||||||
def _find_character(self):
|
def _find_character(self):
|
||||||
character = np.array(self.image)
|
character = np.array(self.image)
|
||||||
support_list_img = self.screenshot
|
support_list_img = self.screenshot
|
||||||
res = cv2.matchTemplate(character, support_list_img, cv2.TM_CCOEFF_NORMED)
|
res = cv2.matchTemplate(
|
||||||
|
character, support_list_img, cv2.TM_CCOEFF_NORMED)
|
||||||
|
|
||||||
_, max_val, _, max_loc = cv2.minMaxLoc(res)
|
_, max_val, _, max_loc = cv2.minMaxLoc(res)
|
||||||
|
max_loc = get_position_in_original_image(
|
||||||
|
max_loc, SupportCharacter._crop_area)
|
||||||
character_width = character.shape[1]
|
character_width = character.shape[1]
|
||||||
character_height = character.shape[0]
|
character_height = character.shape[0]
|
||||||
|
|
||||||
@ -68,6 +83,66 @@ class SupportCharacter:
|
|||||||
self.button[0], self.button[1] - 5, self.button[0] + 30, self.button[1]) if self.button else None
|
self.button[0], self.button[1] - 5, self.button[0] + 30, self.button[1]) if self.button else None
|
||||||
|
|
||||||
|
|
||||||
|
class ArrowWrapper(ButtonWrapper):
|
||||||
|
|
||||||
|
def find_center(self, image):
|
||||||
|
res = cv2.matchTemplate(
|
||||||
|
self.matched_button.image, image, cv2.TM_CCOEFF_NORMED)
|
||||||
|
_, max_val, _, max_loc = cv2.minMaxLoc(res)
|
||||||
|
return (
|
||||||
|
(
|
||||||
|
(max_loc[0] + self.matched_button.image.shape[1] / 2),
|
||||||
|
(max_loc[1] + self.matched_button.image.shape[0] / 2),
|
||||||
|
)
|
||||||
|
if max_val > 0.75
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class NextSupportCharacter:
|
||||||
|
_arrow = ArrowWrapper(
|
||||||
|
name="NextSupportCharacterArrow",
|
||||||
|
share=Button(
|
||||||
|
file='./assets/support/selected_character_arrow.png',
|
||||||
|
area=None,
|
||||||
|
search=None,
|
||||||
|
color=None,
|
||||||
|
button=None,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
_crop_area = (290, 115, 435, 634)
|
||||||
|
|
||||||
|
def __init__(self, screenshot):
|
||||||
|
self.name = "SupportCharacterArrow"
|
||||||
|
self.screenshot = crop(screenshot, NextSupportCharacter._crop_area)
|
||||||
|
self.arrow_center = self._find_center()
|
||||||
|
self.button = self._get_next_support_character_button()
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return self.button is not None
|
||||||
|
|
||||||
|
def _find_center(self):
|
||||||
|
center = NextSupportCharacter._arrow.find_center(self.screenshot)
|
||||||
|
center = get_position_in_original_image(
|
||||||
|
center, NextSupportCharacter._crop_area) if center else None
|
||||||
|
return center
|
||||||
|
|
||||||
|
def _get_next_support_character_button(self):
|
||||||
|
area = (self.arrow_center[0] - 200, min(self.arrow_center[1] + 65, 615), self.arrow_center[0] + 10, min(
|
||||||
|
self.arrow_center[1] + 80, 620)) if self.arrow_center and self.arrow_center[1] < 510 else None
|
||||||
|
return ButtonWrapper(
|
||||||
|
name="NextSupportCharacterButton",
|
||||||
|
share=Button(
|
||||||
|
file='./assets/support/selected_character_arrow.png',
|
||||||
|
area=area,
|
||||||
|
search=area,
|
||||||
|
# if next support was selected, the average color of the button will larger than 220
|
||||||
|
color=(220, 220, 220),
|
||||||
|
button=area,
|
||||||
|
)
|
||||||
|
) if self.arrow_center and self.arrow_center[1] < 510 else None
|
||||||
|
|
||||||
|
|
||||||
class SupportListScroll(Scroll):
|
class SupportListScroll(Scroll):
|
||||||
def cal_position(self, main):
|
def cal_position(self, main):
|
||||||
"""
|
"""
|
||||||
@ -130,11 +205,18 @@ class CombatSupport(UI):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
# Click
|
# Click
|
||||||
if self.appear(COMBAT_TEAM_SUPPORT, interval=2):
|
if self.appear(COMBAT_TEAM_SUPPORT, interval=1):
|
||||||
self.device.click(COMBAT_TEAM_SUPPORT)
|
self.device.click(COMBAT_TEAM_SUPPORT)
|
||||||
self.interval_reset(COMBAT_TEAM_SUPPORT)
|
self.interval_reset(COMBAT_TEAM_SUPPORT)
|
||||||
continue
|
continue
|
||||||
if self.appear(COMBAT_SUPPORT_LIST, interval=2):
|
if self.appear(CANCEL_POPUP, interval=1):
|
||||||
|
logger.warning(
|
||||||
|
"selected identical character, trying select another")
|
||||||
|
self._cancel_popup()
|
||||||
|
self._select_next_support()
|
||||||
|
self.interval_reset(CANCEL_POPUP)
|
||||||
|
continue
|
||||||
|
if self.appear(COMBAT_SUPPORT_LIST, interval=1):
|
||||||
if support_character_name != "FirstCharacter":
|
if support_character_name != "FirstCharacter":
|
||||||
self._search_support(
|
self._search_support(
|
||||||
support_character_name) # Search support
|
support_character_name) # Search support
|
||||||
@ -167,7 +249,6 @@ class CombatSupport(UI):
|
|||||||
|
|
||||||
logger.info("Searching support")
|
logger.info("Searching support")
|
||||||
skip_first_screenshot = False
|
skip_first_screenshot = False
|
||||||
character = None
|
|
||||||
while 1:
|
while 1:
|
||||||
if skip_first_screenshot:
|
if skip_first_screenshot:
|
||||||
skip_first_screenshot = False
|
skip_first_screenshot = False
|
||||||
@ -175,7 +256,8 @@ class CombatSupport(UI):
|
|||||||
self.device.screenshot()
|
self.device.screenshot()
|
||||||
|
|
||||||
if not support_character_name.startswith("Trailblazer"):
|
if not support_character_name.startswith("Trailblazer"):
|
||||||
character = SupportCharacter(support_character_name, self.device.image)
|
character = SupportCharacter(
|
||||||
|
support_character_name, self.device.image)
|
||||||
else:
|
else:
|
||||||
character = SupportCharacter(f"Stelle{support_character_name[11:]}",
|
character = SupportCharacter(f"Stelle{support_character_name[11:]}",
|
||||||
self.device.image) or SupportCharacter(
|
self.device.image) or SupportCharacter(
|
||||||
@ -223,3 +305,73 @@ class CombatSupport(UI):
|
|||||||
self.device.click(character)
|
self.device.click(character)
|
||||||
interval.reset()
|
interval.reset()
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
def _cancel_popup(self):
|
||||||
|
"""
|
||||||
|
Pages:
|
||||||
|
in: CANCEL_POPUP
|
||||||
|
out: COMBAT_SUPPORT_LIST
|
||||||
|
"""
|
||||||
|
logger.hr("Combat support cancel popup")
|
||||||
|
skip_first_screenshot = True
|
||||||
|
|
||||||
|
while 1:
|
||||||
|
if skip_first_screenshot:
|
||||||
|
skip_first_screenshot = False
|
||||||
|
else:
|
||||||
|
self.device.screenshot()
|
||||||
|
|
||||||
|
# End
|
||||||
|
if self.appear(COMBAT_SUPPORT_LIST):
|
||||||
|
logger.info("Popup canceled")
|
||||||
|
return
|
||||||
|
|
||||||
|
if self.appear(CANCEL_POPUP):
|
||||||
|
self.device.click(CANCEL_POPUP)
|
||||||
|
continue
|
||||||
|
|
||||||
|
def _select_next_support(self):
|
||||||
|
"""
|
||||||
|
Pages:
|
||||||
|
in: COMBAT_SUPPORT_LIST
|
||||||
|
out: COMBAT_SUPPORT_LIST
|
||||||
|
"""
|
||||||
|
skip_first_screenshot = True
|
||||||
|
scroll = SupportListScroll(area=COMBAT_SUPPORT_LIST_SCROLL.area, color=(194, 196, 205),
|
||||||
|
name=COMBAT_SUPPORT_LIST_SCROLL.name)
|
||||||
|
interval = Timer(1)
|
||||||
|
next_support = None
|
||||||
|
if scroll.appear(main=self):
|
||||||
|
while 1:
|
||||||
|
if skip_first_screenshot:
|
||||||
|
skip_first_screenshot = False
|
||||||
|
else:
|
||||||
|
self.device.screenshot()
|
||||||
|
|
||||||
|
# End
|
||||||
|
if next_support and self._next_support_selected(next_support):
|
||||||
|
return
|
||||||
|
|
||||||
|
if interval.reached():
|
||||||
|
next_support = NextSupportCharacter(self.device.image)
|
||||||
|
if next_support:
|
||||||
|
logger.info("Next support found, clicking")
|
||||||
|
self.device.click(next_support.button)
|
||||||
|
elif not scroll.at_bottom(main=self):
|
||||||
|
scroll.next_page(main=self, page=0.4)
|
||||||
|
else:
|
||||||
|
logger.warning("No more support")
|
||||||
|
return
|
||||||
|
|
||||||
|
interval.reset()
|
||||||
|
continue
|
||||||
|
|
||||||
|
def _next_support_selected(self, next_support: NextSupportCharacter):
|
||||||
|
"""
|
||||||
|
Returns:
|
||||||
|
bool: True if selected else False
|
||||||
|
"""
|
||||||
|
if self.match_color(next_support.button, threshold=20):
|
||||||
|
logger.info("Next support selected")
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
Loading…
Reference in New Issue
Block a user