StarRailCopilot/module/map/map_operation.py
2020-05-01 17:54:24 +08:00

170 lines
5.2 KiB
Python

import numpy as np
from module.base.timer import Timer
from module.base.utils import color_similarity_2d
from module.exception import CampaignEnd
from module.exception import ScriptEnd
from module.handler.fast_forward import FastForwardHandler
from module.handler.low_emotion import LowEmotionHandler
from module.handler.mystery import MysteryHandler
from module.handler.urgent_commission import UrgentCommissionHandler
from module.logger import logger
from module.map.assets import *
from module.map.map_fleet_preparation import FleetPreparation
from module.retire.retirement import Retirement
class MapOperation(UrgentCommissionHandler, MysteryHandler, FleetPreparation, Retirement, FastForwardHandler,
LowEmotionHandler):
map_cat_attack_timer = Timer(2)
def fleet_switch_click(self):
"""
Switch fleet.
"""
logger.info('Switch over')
if self.appear_then_click(SWITCH_OVER):
pass
else:
logger.warning('No buttons detected.')
self.device.sleep((1, 1.5))
# self.ensure_no_info_bar()
def enter_map(self, button, mode='normal'):
"""Enter a campaign.
Args:
button: Campaign to enter.
mode (str): 'normal' or 'hard' or 'cd'
"""
logger.hr('Enter map')
campaign_timer = Timer(2)
map_timer = Timer(1)
fleet_timer = Timer(1)
checked_in_map = False
while 1:
self.device.screenshot()
if not checked_in_map and self.is_in_map():
logger.info('Already in map, skip enter_map.')
return False
else:
checked_in_map = True
# Map preparation
if map_timer.reached() and self.appear(MAP_PREPARATION):
self.device.sleep(0.3) # Wait for map information.
self.device.screenshot()
if self.handle_map_clear_mode_stop():
self.enter_map_cancel()
raise ScriptEnd(f'Reach condition: {self.config.CLEAR_MODE_STOP_CONDITION}')
self.handle_fast_forward()
self.device.click(MAP_PREPARATION)
map_timer.reset()
campaign_timer.reset()
continue
# Fleet preparation
if fleet_timer.reached() and self.appear(FLEET_PREPARATION):
if self.config.ENABLE_FLEET_CONTROL:
if mode == 'normal' or mode == 'hard':
self.fleet_preparation()
self.device.click(FLEET_PREPARATION)
fleet_timer.reset()
campaign_timer.reset()
continue
# Retire
if self.handle_retirement():
continue
# Emotion
if self.handle_combat_low_emotion():
continue
# Urgent commission
if self.handle_urgent_commission():
continue
# Story skip
if self.handle_story_skip():
campaign_timer.reset()
continue
# Enter campaign
if campaign_timer.reached() and self.is_in_stage():
self.device.click(button)
campaign_timer.reset()
continue
# End
if self.handle_in_map_with_enemy_searching():
break
return True
def enter_map_cancel(self, skip_first_screenshot=True):
logger.hr('Enter map cancel')
while 1:
if skip_first_screenshot:
skip_first_screenshot = False
else:
self.device.screenshot()
if self.appear(MAP_PREPARATION) or self.appear(FLEET_PREPARATION):
self.device.click(MAP_PREPARATION_CANCEL)
continue
if self.is_in_stage():
break
return True
def withdraw(self):
"""
Withdraw campaign.
"""
logger.hr('Map withdraw')
while 1:
self.device.screenshot()
if self.handle_popup_confirm():
continue
if self.appear_then_click(WITHDRAW, interval=2):
continue
# End
if self.handle_in_stage():
raise CampaignEnd('Withdraw')
def handle_map_cat_attack(self):
"""
Click to skip the animation when cat attacks.
"""
if not self.map_cat_attack_timer.reached():
return False
if np.sum(color_similarity_2d(self.image_area(MAP_CAT_ATTACK), (255, 231, 123)) > 221) > 100:
logger.info('Skip map cat attack')
self.map_cat_attack_timer.reset()
return True
return False
def handle_fleet_reverse(self):
"""
The game chooses the fleet with a smaller index to be the first fleet,
no matter what we choose in fleet preparation.
Returns:
bool: Fleet changed
"""
if (self.config.FLEET_2 == 0) or (self.config.FLEET_2 > self.config.FLEET_1):
return False
self.fleet_switch_click()
return True
def handle_spare_fleet(self):
pass