mirror of
https://github.com/LmeSzinc/StarRailCopilot.git
synced 2024-11-23 09:01:45 +00:00
a674198365
- 稍微移动了章节OCR的位置, 因为4-4会识别为14-4 - 针对第四章这种偏红的地图做了一些优化 - 稍微延长了敌人刷新时的等待时间 - 更改出错截图文件名为格式化的时间
324 lines
12 KiB
Python
324 lines
12 KiB
Python
from module.base.timer import Timer
|
|
from module.handler.ambush import AmbushHandler
|
|
from module.logger import logger
|
|
from module.map.camera import Camera
|
|
from module.map.map_base import location2node, location_ensure
|
|
from module.map.map_operation import MapOperation
|
|
|
|
|
|
class Fleet(Camera, MapOperation, AmbushHandler):
|
|
fleet_1_location = ()
|
|
fleet_2_location = ()
|
|
fleet_current_index = 1
|
|
battle_count = 0
|
|
mystery_count = 0
|
|
siren_count = 0
|
|
fleet_ammo = 5
|
|
ammo_count = 3
|
|
|
|
@property
|
|
def fleet_1(self):
|
|
if self.fleet_current_index != 1:
|
|
self.fleet_switch()
|
|
return self
|
|
|
|
@fleet_1.setter
|
|
def fleet_1(self, value):
|
|
self.fleet_1_location = value
|
|
|
|
@property
|
|
def fleet_2(self):
|
|
if self.fleet_current_index != 2:
|
|
self.fleet_switch()
|
|
return self
|
|
|
|
@fleet_2.setter
|
|
def fleet_2(self, value):
|
|
self.fleet_2_location = value
|
|
|
|
@property
|
|
def fleet_current(self):
|
|
if self.fleet_current_index == 2:
|
|
return self.fleet_2_location
|
|
else:
|
|
return self.fleet_1_location
|
|
|
|
def fleet_switch(self):
|
|
self.fleet_switch_click()
|
|
self.fleet_current_index = 1 if self.fleet_current_index == 2 else 2
|
|
self.camera = self.fleet_current
|
|
self.update()
|
|
self.find_path_initial()
|
|
self.map.show_cost()
|
|
self.show_fleet()
|
|
self.handle_strategy(index=self.fleet_current_index)
|
|
|
|
def switch_to(self):
|
|
pass
|
|
|
|
def _goto(self, location, expected=''):
|
|
"""Goto a grid directly and handle ambush, air raid, mystery picked up, combat.
|
|
|
|
Args:
|
|
location (tuple, str, GridInfo): Destination.
|
|
"""
|
|
location = location_ensure(location)
|
|
self.in_sight(location, sight=(-3, 0, 3, 2))
|
|
grid = self.convert_map_to_grid(location)
|
|
result_mystery = ''
|
|
|
|
while 1:
|
|
self.ambush_color_initial()
|
|
self.enemy_searching_color_initial()
|
|
grid.__str__ = location
|
|
result = 'nothing'
|
|
self.device.click(grid)
|
|
arrived = False
|
|
# Wait to confirm fleet arrived. It does't appear immediately if fleet in combat .
|
|
arrive_timer = Timer(0.3)
|
|
arrive_unexpected_timer = Timer(1.5)
|
|
# Wait after ambushed.
|
|
ambushed_retry = Timer(0.5)
|
|
# If nothing happens, click again.
|
|
walk_timeout = Timer(10)
|
|
walk_timeout.start()
|
|
|
|
while 1:
|
|
self.device.screenshot()
|
|
grid.image = self.device.image
|
|
|
|
if self.handle_ambush():
|
|
ambushed_retry.start()
|
|
# 这个虽然到了之后还会原地再点一次, 但还是先用着, 问题不大
|
|
# arrived = False
|
|
# 这个可能会误以为已经到达
|
|
# arrived = grid.predict_fleet()
|
|
# 把break去掉就搞定了
|
|
# break
|
|
mystery = self.handle_mystery(button=grid)
|
|
if mystery:
|
|
# arrived = True
|
|
self.mystery_count += 1
|
|
result = 'mystery'
|
|
result_mystery = mystery
|
|
# break
|
|
|
|
if self.combat_appear():
|
|
self.combat(expected_end=self._expected_combat_end(expected), fleet_index=self.fleet_current_index)
|
|
self.hp_get()
|
|
if self.hp_withdraw_triggered():
|
|
self.withdraw()
|
|
arrived = True
|
|
result = 'combat'
|
|
self.battle_count += 1
|
|
self.fleet_ammo -= 1
|
|
if 'siren' in expected:
|
|
self.siren_count += 1
|
|
else:
|
|
self.map[location_ensure(location)].is_cleared = True
|
|
|
|
self.handle_boss_appear_refocus()
|
|
grid = self.convert_map_to_grid(location)
|
|
walk_timeout.reset()
|
|
# break
|
|
|
|
if self.handle_map_cat_attack():
|
|
continue
|
|
|
|
if self.is_in_map() and grid.predict_fleet():
|
|
arrive_timer.start()
|
|
arrive_unexpected_timer.start()
|
|
if not arrive_timer.reached():
|
|
continue
|
|
if expected and result not in expected:
|
|
if arrive_unexpected_timer.reached():
|
|
logger.warning('Arrive with unexpected result')
|
|
else:
|
|
continue
|
|
logger.info(f'Arrive confirm. Result: {result}. Expected: {expected}')
|
|
arrived = True
|
|
break
|
|
|
|
# End
|
|
if ambushed_retry.started() and ambushed_retry.reached():
|
|
break
|
|
if walk_timeout.reached():
|
|
logger.warning('Walk timeout. Retrying.')
|
|
break
|
|
|
|
# End
|
|
if arrived:
|
|
break
|
|
|
|
self.map[self.fleet_current].is_fleet = False
|
|
self.map[location].wipe_out()
|
|
self.map[location].is_fleet = True
|
|
self.__setattr__('fleet_%s_location' % self.fleet_current_index, location)
|
|
if result_mystery == 'get_carrier':
|
|
prev_enemy = self.map.select(is_enemy=True)
|
|
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count,
|
|
siren_count=self.siren_count, carrier_count=self.carrier_count, is_carrier_scan=True)
|
|
diff = self.map.select(is_enemy=True).delete(prev_enemy)
|
|
logger.info(f'Carrier spawn: {diff}')
|
|
self.find_path_initial()
|
|
|
|
def goto(self, location, optimize=True, expected=''):
|
|
# self.device.sleep(1000)
|
|
location = location_ensure(location)
|
|
if self.config.MAP_HAS_AMBUSH and optimize:
|
|
nodes = self.map.find_path(location)
|
|
for node in nodes:
|
|
self._goto(node, expected=expected if node == nodes[-1] else '')
|
|
else:
|
|
self._goto(location, expected=expected)
|
|
|
|
def find_path_initial(self):
|
|
self.map.find_path_initial(self.fleet_current, has_ambush=self.config.MAP_HAS_AMBUSH)
|
|
|
|
def show_fleet(self):
|
|
fleets = []
|
|
for n in [1, 2]:
|
|
fleet = self.__getattribute__('fleet_%s_location' % n)
|
|
if len(fleet):
|
|
text = 'Fleet_%s: %s' % (n, location2node(fleet))
|
|
if self.fleet_current_index == n:
|
|
text = '[%s]' % text
|
|
fleets.append(text)
|
|
logger.info(' '.join(fleets))
|
|
|
|
def find_current_fleet(self):
|
|
fleets = self.map.select(is_fleet=True, is_spawn_point=True)
|
|
logger.info('Fleets: %s' % str(fleets))
|
|
count = fleets.count
|
|
if count == 1:
|
|
self.fleet_1 = fleets[0].location
|
|
elif count == 2:
|
|
fleets = fleets.sort_by_camera_distance(self.camera)
|
|
self.in_sight(fleets[0], sight=(-1, 0, 1, 2))
|
|
if self.convert_map_to_grid(fleets[0]).predict_current_fleet():
|
|
self.fleet_1 = fleets[0].location
|
|
self.fleet_2 = fleets[1].location
|
|
else:
|
|
self.in_sight(fleets[1], sight=(-1, 0, 1, 2))
|
|
if self.convert_map_to_grid(fleets[1]).predict_current_fleet():
|
|
self.fleet_1 = fleets[1].location
|
|
self.fleet_2 = fleets[0].location
|
|
else:
|
|
logger.warning('Current fleet not found')
|
|
self.fleet_1 = fleets[0].location
|
|
self.fleet_2 = fleets[1].location
|
|
else:
|
|
if count == 0:
|
|
logger.warning('No fleets detected. Checking fleet spawn points.')
|
|
if count > 2:
|
|
logger.warning('Too many fleets: %s. Re-checking all spawn points.' % str(fleets))
|
|
queue = self.map.select(is_spawn_point=True)
|
|
while queue:
|
|
queue = queue.sort_by_camera_distance(self.camera)
|
|
self.in_sight(queue[0], sight=(-1, 0, 1, 2))
|
|
grid = self.convert_map_to_grid(queue[0])
|
|
if grid.predict_current_fleet():
|
|
self.fleet_1 = grid.location
|
|
elif grid.predict_fleet():
|
|
self.fleet_2 = grid.location
|
|
queue = queue[1:]
|
|
|
|
self.fleet_current_index = 1
|
|
self.show_fleet()
|
|
return self.fleet_current
|
|
|
|
def map_init(self, map_):
|
|
logger.hr('Map init')
|
|
self.battle_count = 0
|
|
self.mystery_count = 0
|
|
self.carrier_count = 0
|
|
self.siren_count = 0
|
|
self.ammo_count = 3
|
|
self.map = map_
|
|
self.map.reset()
|
|
self.hp_init()
|
|
self.handle_strategy(index=self.fleet_current_index)
|
|
self.ensure_edge_insight(preset=self.map.in_map_swipe_preset_data)
|
|
self.full_scan(battle_count=self.battle_count, mystery_count=self.mystery_count, siren_count=self.siren_count,
|
|
carrier_count=self.carrier_count)
|
|
self.find_current_fleet()
|
|
self.find_path_initial()
|
|
self.map.show_cost()
|
|
|
|
def _expected_combat_end(self, expected):
|
|
for data in self.map._spawn_data_backup:
|
|
if data.get('battle') == self.battle_count and 'boss' in expected:
|
|
return 'in_stage'
|
|
if data.get('battle') == self.battle_count + 1:
|
|
if data.get('enemy', 0) + data.get('siren', 0) + data.get('boss', 0) > 0:
|
|
return 'with_searching'
|
|
else:
|
|
return 'no_searching'
|
|
|
|
if 'boss' in expected:
|
|
return 'in_stage'
|
|
return 'no_searching'
|
|
|
|
def fleet_at(self, grid, fleet=None):
|
|
"""
|
|
Args:
|
|
grid (Grid):
|
|
fleet (int): 1, 2
|
|
|
|
Returns:
|
|
bool: If fleet is at grid.
|
|
"""
|
|
if fleet is None:
|
|
return self.fleet_current == grid.location
|
|
if fleet == 1:
|
|
return self.fleet_1_location == grid.location
|
|
else:
|
|
return self.fleet_2_location == grid.location
|
|
|
|
def check_accessibility(self, grid, fleet=None):
|
|
"""
|
|
Args:
|
|
grid (Grid):
|
|
fleet (int): 1, 2
|
|
|
|
Returns:
|
|
bool: If accessible.
|
|
"""
|
|
if fleet is None:
|
|
return grid.is_accessible
|
|
if fleet == self.fleet_current_index:
|
|
return grid.is_accessible
|
|
else:
|
|
backup = self.fleet_current_index
|
|
self.fleet_current_index = fleet
|
|
self.find_path_initial()
|
|
result = grid.is_accessible
|
|
|
|
self.fleet_current_index = backup
|
|
self.find_path_initial()
|
|
return result
|
|
|
|
def handle_boss_appear_refocus(self):
|
|
"""
|
|
|
|
"""
|
|
appear = False
|
|
for data in self.map.spawn_data:
|
|
if data.get('battle') == self.battle_count and data.get('boss', 0):
|
|
appear = True
|
|
|
|
if appear:
|
|
logger.info('Catch camera re-positioning after boss appear')
|
|
camera = self.camera
|
|
self.ensure_edge_insight()
|
|
logger.info('Refocus to previous camera position.')
|
|
self.focus_to(camera)
|
|
return True
|
|
else:
|
|
return False
|
|
|
|
def fleet_checked_reset(self):
|
|
self.map_fleet_checked = False
|
|
self.fleet_1_formation_fixed = False
|
|
self.fleet_2_formation_fixed = False
|