mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-24 17:42:46 +00:00
136 lines
4.3 KiB
Python
136 lines
4.3 KiB
Python
from module.base.button import match_template
|
|
from module.base.timer import Timer
|
|
from module.logger import logger
|
|
from tasks.base.ui import UI
|
|
from tasks.combat.assets.assets_combat_skill import *
|
|
|
|
|
|
class CombatSkill(UI):
|
|
def is_in_skill(self) -> bool:
|
|
"""
|
|
Combat paused, require manual skill use
|
|
"""
|
|
if not self.appear(IN_SKILL):
|
|
return False
|
|
|
|
if not self.image_color_count(IN_SKILL, color=(255, 255, 255), threshold=180, count=50):
|
|
return False
|
|
|
|
return True
|
|
|
|
def _skill_click(self, button, skip_first_screenshot=True):
|
|
"""
|
|
Click a skill button.
|
|
Not in skill page means skill has been used and skill animation is ongoing
|
|
"""
|
|
logger.info(f'Skill use: {button}')
|
|
interval = Timer(1)
|
|
clicked = False
|
|
prev_image = None
|
|
while 1:
|
|
if skip_first_screenshot:
|
|
skip_first_screenshot = False
|
|
else:
|
|
self.device.screenshot()
|
|
|
|
if self.is_in_skill():
|
|
if interval.reached():
|
|
prev_image = self.image_crop(button)
|
|
self.device.click(button)
|
|
interval.reset()
|
|
clicked = True
|
|
continue
|
|
else:
|
|
# Skill animation on going
|
|
if clicked:
|
|
logger.info(f'Skill used: {button} (skill ongoing)')
|
|
break
|
|
# New skill icon
|
|
if prev_image is not None:
|
|
if not match_template(self.image_crop(button, copy=False), prev_image):
|
|
logger.info(f'Skill used: {button} (icon changed)')
|
|
break
|
|
|
|
if self.is_in_main():
|
|
logger.warning('_skill_click ended at is_in_main')
|
|
break
|
|
|
|
def _is_skill_active(self, button):
|
|
flag = self.image_color_count(button, color=(220, 196, 145), threshold=221, count=50)
|
|
return flag
|
|
|
|
def _skill_switch(self, check_button, click_button, skip_first_screenshot=True):
|
|
"""
|
|
Switch to A or E
|
|
"""
|
|
logger.info(f'Skill switch: {check_button}')
|
|
interval = Timer(1)
|
|
while 1:
|
|
if skip_first_screenshot:
|
|
skip_first_screenshot = False
|
|
else:
|
|
self.device.screenshot()
|
|
|
|
# Raw brown border
|
|
if self._is_skill_active(check_button):
|
|
logger.info(f'Skill switched: {check_button}')
|
|
break
|
|
|
|
if self.is_in_skill() and (self._is_skill_active(CHECK_A) or self._is_skill_active(CHECK_E)):
|
|
if interval.reached():
|
|
self.device.click(click_button)
|
|
interval.reset()
|
|
continue
|
|
|
|
def wait_next_skill(self, expected_end=None, skip_first_screenshot=True):
|
|
"""
|
|
Args:
|
|
expected_end: A function returns bool, True represents end.
|
|
skip_first_screenshot:
|
|
|
|
Returns:
|
|
bool: True if is_in_skill
|
|
False if triggered expected_end
|
|
"""
|
|
logger.info('Wait next skill')
|
|
while 1:
|
|
if skip_first_screenshot:
|
|
skip_first_screenshot = False
|
|
else:
|
|
self.device.screenshot()
|
|
|
|
if self.is_in_skill():
|
|
return True
|
|
if callable(expected_end) and expected_end():
|
|
logger.info(f'Combat execute ended at {expected_end.__name__}')
|
|
return False
|
|
|
|
def use_A(self) -> bool:
|
|
logger.hr('Use A')
|
|
self._skill_switch(check_button=CHECK_A, click_button=USE_A)
|
|
self._skill_click(USE_A)
|
|
return True
|
|
|
|
def use_E(self) -> bool:
|
|
logger.hr('Use E')
|
|
self._skill_switch(check_button=CHECK_E, click_button=USE_E)
|
|
self._skill_click(USE_E)
|
|
return True
|
|
|
|
def use_Q(self, position: int) -> bool:
|
|
"""
|
|
Args:
|
|
position: 1 to 4
|
|
"""
|
|
logger.hr(f'Use Q {position}')
|
|
try:
|
|
button = [USE_Q1, USE_Q2, USE_Q3, USE_Q4][position - 1]
|
|
except IndexError:
|
|
logger.error(f'use_Q: position {position} does not exist')
|
|
return False
|
|
|
|
self._skill_click(button)
|
|
self.wait_next_skill()
|
|
self._skill_click(USE_Q_AIM)
|
|
return True
|