diff --git a/assets/cn/equipment/FLEET_1_BACKLINE_1.png b/assets/cn/equipment/FLEET_1_BACKLINE_1.png new file mode 100644 index 000000000..99be07f76 Binary files /dev/null and b/assets/cn/equipment/FLEET_1_BACKLINE_1.png differ diff --git a/assets/cn/equipment/FLEET_1_BACKLINE_3.png b/assets/cn/equipment/FLEET_1_BACKLINE_3.png new file mode 100644 index 000000000..97b2c613c Binary files /dev/null and b/assets/cn/equipment/FLEET_1_BACKLINE_3.png differ diff --git a/assets/cn/equipment/FLEET_1_VANGUARD_1.png b/assets/cn/equipment/FLEET_1_VANGUARD_1.png new file mode 100644 index 000000000..dcf535763 Binary files /dev/null and b/assets/cn/equipment/FLEET_1_VANGUARD_1.png differ diff --git a/assets/cn/equipment/FLEET_1_VANGUARD_3.png b/assets/cn/equipment/FLEET_1_VANGUARD_3.png new file mode 100644 index 000000000..5ae208e56 Binary files /dev/null and b/assets/cn/equipment/FLEET_1_VANGUARD_3.png differ diff --git a/assets/cn/equipment/FLEET_2_BACKLINE_1.png b/assets/cn/equipment/FLEET_2_BACKLINE_1.png new file mode 100644 index 000000000..9cf641249 Binary files /dev/null and b/assets/cn/equipment/FLEET_2_BACKLINE_1.png differ diff --git a/assets/cn/equipment/FLEET_2_BACKLINE_3.png b/assets/cn/equipment/FLEET_2_BACKLINE_3.png new file mode 100644 index 000000000..01e7d4b59 Binary files /dev/null and b/assets/cn/equipment/FLEET_2_BACKLINE_3.png differ diff --git a/assets/cn/equipment/FLEET_2_VANGUARD_1.png b/assets/cn/equipment/FLEET_2_VANGUARD_1.png new file mode 100644 index 000000000..340faa258 Binary files /dev/null and b/assets/cn/equipment/FLEET_2_VANGUARD_1.png differ diff --git a/assets/cn/equipment/FLEET_2_VANGUARD_3.png b/assets/cn/equipment/FLEET_2_VANGUARD_3.png new file mode 100644 index 000000000..4e8f91bec Binary files /dev/null and b/assets/cn/equipment/FLEET_2_VANGUARD_3.png differ diff --git a/assets/cn/equipment/FLEET_ENTER.png b/assets/cn/equipment/FLEET_ENTER.png index 04eb03415..ea390f965 100644 Binary files a/assets/cn/equipment/FLEET_ENTER.png and b/assets/cn/equipment/FLEET_ENTER.png differ diff --git a/assets/cn/equipment/FLEET_ENTER_FLAGSHIP.png b/assets/cn/equipment/FLEET_ENTER_FLAGSHIP.png index 5b62c21c9..b6925b550 100644 Binary files a/assets/cn/equipment/FLEET_ENTER_FLAGSHIP.png and b/assets/cn/equipment/FLEET_ENTER_FLAGSHIP.png differ diff --git a/assets/cn/retire/DOCK_UNMOUNT.png b/assets/cn/retire/DOCK_UNMOUNT.png new file mode 100644 index 000000000..827391787 Binary files /dev/null and b/assets/cn/retire/DOCK_UNMOUNT.png differ diff --git a/assets/en/equipment/FLEET_1_BACKLINE_1.png b/assets/en/equipment/FLEET_1_BACKLINE_1.png new file mode 100644 index 000000000..99be07f76 Binary files /dev/null and b/assets/en/equipment/FLEET_1_BACKLINE_1.png differ diff --git a/assets/en/equipment/FLEET_1_BACKLINE_3.png b/assets/en/equipment/FLEET_1_BACKLINE_3.png new file mode 100644 index 000000000..97b2c613c Binary files /dev/null and b/assets/en/equipment/FLEET_1_BACKLINE_3.png differ diff --git a/assets/en/equipment/FLEET_1_VANGUARD_1.png b/assets/en/equipment/FLEET_1_VANGUARD_1.png new file mode 100644 index 000000000..dcf535763 Binary files /dev/null and b/assets/en/equipment/FLEET_1_VANGUARD_1.png differ diff --git a/assets/en/equipment/FLEET_1_VANGUARD_3.png b/assets/en/equipment/FLEET_1_VANGUARD_3.png new file mode 100644 index 000000000..5ae208e56 Binary files /dev/null and b/assets/en/equipment/FLEET_1_VANGUARD_3.png differ diff --git a/assets/en/equipment/FLEET_2_BACKLINE_1.png b/assets/en/equipment/FLEET_2_BACKLINE_1.png new file mode 100644 index 000000000..9cf641249 Binary files /dev/null and b/assets/en/equipment/FLEET_2_BACKLINE_1.png differ diff --git a/assets/en/equipment/FLEET_2_BACKLINE_3.png b/assets/en/equipment/FLEET_2_BACKLINE_3.png new file mode 100644 index 000000000..01e7d4b59 Binary files /dev/null and b/assets/en/equipment/FLEET_2_BACKLINE_3.png differ diff --git a/assets/en/equipment/FLEET_2_VANGUARD_1.png b/assets/en/equipment/FLEET_2_VANGUARD_1.png new file mode 100644 index 000000000..340faa258 Binary files /dev/null and b/assets/en/equipment/FLEET_2_VANGUARD_1.png differ diff --git a/assets/en/equipment/FLEET_2_VANGUARD_3.png b/assets/en/equipment/FLEET_2_VANGUARD_3.png new file mode 100644 index 000000000..4e8f91bec Binary files /dev/null and b/assets/en/equipment/FLEET_2_VANGUARD_3.png differ diff --git a/assets/en/equipment/FLEET_ENTER.png b/assets/en/equipment/FLEET_ENTER.png index 04eb03415..ea390f965 100644 Binary files a/assets/en/equipment/FLEET_ENTER.png and b/assets/en/equipment/FLEET_ENTER.png differ diff --git a/assets/en/equipment/FLEET_ENTER_FLAGSHIP.png b/assets/en/equipment/FLEET_ENTER_FLAGSHIP.png index 5b62c21c9..b6925b550 100644 Binary files a/assets/en/equipment/FLEET_ENTER_FLAGSHIP.png and b/assets/en/equipment/FLEET_ENTER_FLAGSHIP.png differ diff --git a/assets/en/retire/DOCK_UNMOUNT.png b/assets/en/retire/DOCK_UNMOUNT.png new file mode 100644 index 000000000..827391787 Binary files /dev/null and b/assets/en/retire/DOCK_UNMOUNT.png differ diff --git a/assets/jp/equipment/FLEET_1_BACKLINE_1.png b/assets/jp/equipment/FLEET_1_BACKLINE_1.png new file mode 100644 index 000000000..99be07f76 Binary files /dev/null and b/assets/jp/equipment/FLEET_1_BACKLINE_1.png differ diff --git a/assets/jp/equipment/FLEET_1_BACKLINE_3.png b/assets/jp/equipment/FLEET_1_BACKLINE_3.png new file mode 100644 index 000000000..97b2c613c Binary files /dev/null and b/assets/jp/equipment/FLEET_1_BACKLINE_3.png differ diff --git a/assets/jp/equipment/FLEET_1_VANGUARD_1.png b/assets/jp/equipment/FLEET_1_VANGUARD_1.png new file mode 100644 index 000000000..dcf535763 Binary files /dev/null and b/assets/jp/equipment/FLEET_1_VANGUARD_1.png differ diff --git a/assets/jp/equipment/FLEET_1_VANGUARD_3.png b/assets/jp/equipment/FLEET_1_VANGUARD_3.png new file mode 100644 index 000000000..5ae208e56 Binary files /dev/null and b/assets/jp/equipment/FLEET_1_VANGUARD_3.png differ diff --git a/assets/jp/equipment/FLEET_2_BACKLINE_1.png b/assets/jp/equipment/FLEET_2_BACKLINE_1.png new file mode 100644 index 000000000..9cf641249 Binary files /dev/null and b/assets/jp/equipment/FLEET_2_BACKLINE_1.png differ diff --git a/assets/jp/equipment/FLEET_2_BACKLINE_3.png b/assets/jp/equipment/FLEET_2_BACKLINE_3.png new file mode 100644 index 000000000..01e7d4b59 Binary files /dev/null and b/assets/jp/equipment/FLEET_2_BACKLINE_3.png differ diff --git a/assets/jp/equipment/FLEET_2_VANGUARD_1.png b/assets/jp/equipment/FLEET_2_VANGUARD_1.png new file mode 100644 index 000000000..340faa258 Binary files /dev/null and b/assets/jp/equipment/FLEET_2_VANGUARD_1.png differ diff --git a/assets/jp/equipment/FLEET_2_VANGUARD_3.png b/assets/jp/equipment/FLEET_2_VANGUARD_3.png new file mode 100644 index 000000000..4e8f91bec Binary files /dev/null and b/assets/jp/equipment/FLEET_2_VANGUARD_3.png differ diff --git a/assets/jp/equipment/FLEET_ENTER.png b/assets/jp/equipment/FLEET_ENTER.png index 04eb03415..ea390f965 100644 Binary files a/assets/jp/equipment/FLEET_ENTER.png and b/assets/jp/equipment/FLEET_ENTER.png differ diff --git a/assets/jp/equipment/FLEET_ENTER_FLAGSHIP.png b/assets/jp/equipment/FLEET_ENTER_FLAGSHIP.png index 5b62c21c9..b6925b550 100644 Binary files a/assets/jp/equipment/FLEET_ENTER_FLAGSHIP.png and b/assets/jp/equipment/FLEET_ENTER_FLAGSHIP.png differ diff --git a/assets/jp/retire/DOCK_UNMOUNT.png b/assets/jp/retire/DOCK_UNMOUNT.png new file mode 100644 index 000000000..827391787 Binary files /dev/null and b/assets/jp/retire/DOCK_UNMOUNT.png differ diff --git a/assets/tw/equipment/FLEET_1_BACKLINE_1.png b/assets/tw/equipment/FLEET_1_BACKLINE_1.png new file mode 100644 index 000000000..99be07f76 Binary files /dev/null and b/assets/tw/equipment/FLEET_1_BACKLINE_1.png differ diff --git a/assets/tw/equipment/FLEET_1_BACKLINE_3.png b/assets/tw/equipment/FLEET_1_BACKLINE_3.png new file mode 100644 index 000000000..97b2c613c Binary files /dev/null and b/assets/tw/equipment/FLEET_1_BACKLINE_3.png differ diff --git a/assets/tw/equipment/FLEET_1_VANGUARD_1.png b/assets/tw/equipment/FLEET_1_VANGUARD_1.png new file mode 100644 index 000000000..dcf535763 Binary files /dev/null and b/assets/tw/equipment/FLEET_1_VANGUARD_1.png differ diff --git a/assets/tw/equipment/FLEET_1_VANGUARD_3.png b/assets/tw/equipment/FLEET_1_VANGUARD_3.png new file mode 100644 index 000000000..5ae208e56 Binary files /dev/null and b/assets/tw/equipment/FLEET_1_VANGUARD_3.png differ diff --git a/assets/tw/equipment/FLEET_2_BACKLINE_1.png b/assets/tw/equipment/FLEET_2_BACKLINE_1.png new file mode 100644 index 000000000..9cf641249 Binary files /dev/null and b/assets/tw/equipment/FLEET_2_BACKLINE_1.png differ diff --git a/assets/tw/equipment/FLEET_2_BACKLINE_3.png b/assets/tw/equipment/FLEET_2_BACKLINE_3.png new file mode 100644 index 000000000..01e7d4b59 Binary files /dev/null and b/assets/tw/equipment/FLEET_2_BACKLINE_3.png differ diff --git a/assets/tw/equipment/FLEET_2_VANGUARD_1.png b/assets/tw/equipment/FLEET_2_VANGUARD_1.png new file mode 100644 index 000000000..340faa258 Binary files /dev/null and b/assets/tw/equipment/FLEET_2_VANGUARD_1.png differ diff --git a/assets/tw/equipment/FLEET_2_VANGUARD_3.png b/assets/tw/equipment/FLEET_2_VANGUARD_3.png new file mode 100644 index 000000000..4e8f91bec Binary files /dev/null and b/assets/tw/equipment/FLEET_2_VANGUARD_3.png differ diff --git a/assets/tw/equipment/FLEET_ENTER.png b/assets/tw/equipment/FLEET_ENTER.png index 04eb03415..ea390f965 100644 Binary files a/assets/tw/equipment/FLEET_ENTER.png and b/assets/tw/equipment/FLEET_ENTER.png differ diff --git a/assets/tw/equipment/FLEET_ENTER_FLAGSHIP.png b/assets/tw/equipment/FLEET_ENTER_FLAGSHIP.png index 5b62c21c9..b6925b550 100644 Binary files a/assets/tw/equipment/FLEET_ENTER_FLAGSHIP.png and b/assets/tw/equipment/FLEET_ENTER_FLAGSHIP.png differ diff --git a/assets/tw/retire/DOCK_UNMOUNT.png b/assets/tw/retire/DOCK_UNMOUNT.png new file mode 100644 index 000000000..827391787 Binary files /dev/null and b/assets/tw/retire/DOCK_UNMOUNT.png differ diff --git a/campaign/campaign_hard/campaign_hard.py b/campaign/campaign_hard/campaign_hard.py index 95f1a72af..0950cf458 100644 --- a/campaign/campaign_hard/campaign_hard.py +++ b/campaign/campaign_hard/campaign_hard.py @@ -1,7 +1,6 @@ from module.base.timer import Timer from module.campaign.campaign_base import CampaignBase from module.exception import CampaignEnd -from module.hard.equipment import HardEquipment from module.logger import logger from module.map.assets import FLEET_PREPARATION, MAP_PREPARATION from module.ui.assets import CAMPAIGN_CHECK @@ -13,7 +12,7 @@ class Config: ENABLE_HP_BALANCE = False -class Campaign(CampaignBase, HardEquipment): +class Campaign(CampaignBase): # def run(self): # logger.hr(self.ENTRANCE, level=2) # self.enter_map(self.ENTRANCE, mode='hard') @@ -36,9 +35,6 @@ class Campaign(CampaignBase, HardEquipment): # except CampaignEnd: # logger.hr('Campaign end') - # def fleet_preparation(self): - # self.equipment_take_on() - def _expected_end(self, expected): return 'in_stage' @@ -60,45 +56,3 @@ class Campaign(CampaignBase, HardEquipment): self.clear_potential_boss() return False - - def equipment_take_off_when_finished(self): - if self.config.FLEET_HARD_EQUIPMENT is None: - return False - if not self.equipment_has_take_on: - return False - - logger.info('equipment_take_off_when_finished') - campaign_timer = Timer(2) - map_timer = Timer(1) - fleet_timer = Timer(1) - - while 1: - self.device.screenshot() - - # Enter campaign - if campaign_timer.reached() and self.is_in_stage(): - self.device.click(self.ENTRANCE) - campaign_timer.reset() - continue - - # Map preparation - if map_timer.reached() and self.appear(MAP_PREPARATION, offset=(20, 20)): - self.device.click(MAP_PREPARATION) - map_timer.reset() - campaign_timer.reset() - continue - - # Fleet preparation - if fleet_timer.reached() and self.appear(FLEET_PREPARATION, offset=(20, 50)): - self.equipment_take_off() - self.ui_back(check_button=CAMPAIGN_CHECK, appear_button=FLEET_PREPARATION) - break - - # Retire - if self.handle_retirement(): - continue - - # Emotion - pass - - return True diff --git a/module/campaign/gems_farming.py b/module/campaign/gems_farming.py index 6bf22f94f..6b8cdb008 100644 --- a/module/campaign/gems_farming.py +++ b/module/campaign/gems_farming.py @@ -1,70 +1,29 @@ from datetime import datetime -from module.base.decorator import cached_property +from module.base.decorator import Config, cached_property from module.base.timer import Timer from module.campaign.campaign_base import CampaignBase from module.campaign.run import CampaignRun from module.combat.assets import BATTLE_PREPARATION from module.combat.emotion import Emotion from module.equipment.assets import * -from module.equipment.equipment_code import EquipmentCodeHandler -from module.equipment.fleet_equipment import OCR_FLEET_INDEX -from module.exception import CampaignEnd, ScriptError, RequestHumanTakeover +from module.exception import CampaignEnd, HardNotSatisfied from module.handler.assets import AUTO_SEARCH_MAP_OPTION_OFF from module.logger import logger from module.map.assets import FLEET_PREPARATION, MAP_PREPARATION -from module.retire.assets import ( - DOCK_CHECK, DOCK_SHIP_DOWN, - TEMPLATE_BOGUE, TEMPLATE_HERMES, TEMPLATE_LANGLEY, TEMPLATE_RANGER, - TEMPLATE_CASSIN_1, TEMPLATE_CASSIN_2, TEMPLATE_DOWNES_1, TEMPLATE_DOWNES_2, - TEMPLATE_AULICK, TEMPLATE_FOOTE -) +from module.ocr.ocr import Digit +from module.retire.assets import * from module.retire.dock import Dock -# TEMPLATE_COMMON_CV and TEMPLATE_COMMON_DD are both used in function find_custom_candidates -from module.retire.retirement import TEMPLATE_COMMON_CV, TEMPLATE_COMMON_DD from module.retire.scanner import ShipScanner -from module.ui.assets import BACK_ARROW, FLEET_CHECK +from module.ui.assets import BACK_ARROW from module.ui.page import page_fleet + +FLEET_INDEX = Digit(OCR_FLEET_INDEX, letter=(90, 154, 255), threshold=128, alphabet='123456') SIM_VALUE = 0.92 -class GemsEmotion(Emotion): - - def check_reduce(self, battle): - """ - Overwrite emotion.check_reduce() - Check emotion before entering a campaign. - Args: - battle (int): Battles in this campaign - Raise: - CampaignEnd: Pause current task to prevent emotion control in the future. - """ - - if not self.is_calculate: - return - - recovered, delay = self._check_reduce(battle) - if delay: - self.config.GEMS_EMOTION_TRIGGERED = True - logger.info('Detect low emotion, pause current task') - raise CampaignEnd('Emotion control') - - def wait(self, fleet_index): - """ - Override Emotion.wait to trigger stop condition when emotion is too low after battle. - """ - self.update() - self.record() - self.show() - fleet = self.fleets[fleet_index - 1] - recovered = fleet.get_recovered(expected_reduce=self.reduce_per_battle) - if recovered > datetime.now(): - self.config.GEMS_EMOTION_TRIGGERED = True - - class GemsCampaignOverride(CampaignBase): - def handle_combat_low_emotion(self): """ Overwrite info_handler.handle_combat_low_emotion() @@ -108,55 +67,66 @@ class GemsCampaignOverride(CampaignBase): raise CampaignEnd('Emotion withdraw') -class GemsFarming(CampaignRun, Dock): - def hard_mode_override(self): - if self.campaign.config.Campaign_Mode == 'hard': - logger.info('Is in hard mode, switch ship changing method.') - self.hard_mode = True - self._ship_detail_enter = self._ship_detail_enter_hard - self._fleet_detail_enter = self._fleet_detail_enter_hard - self._fleet_back = self._fleet_back_hard - self.page_fleet_check_button = FLEET_PREPARATION - if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all': - self.fleet_detail_enter_flagship = FLEET_DETAIL_ENTER_FLAGSHIP_HARD_2 - self.fleet_enter_flagship = FLEET_ENTER_FLAGSHIP_HARD_2 - self.fleet_detail_enter = FLEET_DETAIL_ENTER_HARD_2 - self.fleet_enter = FLEET_ENTER_HARD_2 - else: - self.fleet_detail_enter_flagship = FLEET_DETAIL_ENTER_FLAGSHIP_HARD_1 - self.fleet_enter_flagship = FLEET_ENTER_FLAGSHIP_HARD_1 - self.fleet_detail_enter = FLEET_DETAIL_ENTER_HARD_1 - self.fleet_enter = FLEET_ENTER_HARD_1 - else: - self.hard_mode = False - self.page_fleet_check_button = page_fleet.check_button - self.fleet_detail_enter_flagship = FLEET_DETAIL_ENTER_FLAGSHIP - self.fleet_detail_enter = FLEET_DETAIL_ENTER - self.fleet_enter_flagship = FLEET_ENTER_FLAGSHIP - self.fleet_enter = FLEET_ENTER +class GemsEmotion(Emotion): + def check_reduce(self, battle): + """ + Override Emotion.check_reduce to trigger stop condition when emotion is too low before battle. + """ + if not self.is_calculate: + return + recovered, delay = self._check_reduce(battle) + if delay: + self.config.GEMS_EMOTION_TRIGGERED = True + logger.info('Detect low emotion, pause current task') + raise CampaignEnd('Emotion control') + + def wait(self, fleet_index): + """ + Override Emotion.wait to trigger stop condition when emotion is too low after battle. + """ + self.update() + self.record() + self.show() + fleet = self.fleets[fleet_index - 1] + recovered = fleet.get_recovered(expected_reduce=self.reduce_per_battle) + if recovered > datetime.now(): + self.config.GEMS_EMOTION_TRIGGERED = True + + +class GemsFarming(CampaignRun, Dock): def load_campaign(self, name, folder='campaign_main'): super().load_campaign(name, folder) + gems = self class GemsCampaign(GemsCampaignOverride, self.module.Campaign): - @cached_property - def emotion(self) -> GemsEmotion: + def emotion(self): return GemsEmotion(config=self.config) + def fleet_preparation(self): + try: + return super().fleet_preparation() + except HardNotSatisfied: + pass + + prepared = gems.hard_fleet_prepare() + + if prepared: + try: + return super().fleet_preparation() + except HardNotSatisfied: + logger.warning('Hard fleet still not satisfied after preparation, delay GemsFarming') + else: + logger.warning('No ship available for hard fleet preparation, delay GemsFarming') + gems.config.task_delay(minute=30) + gems.config.task_stop() + return False + self.campaign = GemsCampaign(device=self.campaign.device, config=self.campaign.config) - if self.change_vanguard: - self.campaign.config.override(Emotion_Mode='ignore_calculate') - else: + if not self.change_vanguard: self.campaign.config.override(Emotion_Mode='ignore') - - @property - def emotion_lower_bound(self): - return 4 + self.campaign._map_battle * 2 - - @property - def change_flagship(self): - return 'ship' in self.config.GemsFarming_ChangeFlagship + self.campaign.config.override(EnemyPriority_EnemyScaleBalanceWeight='S1_enemy_first') @property def change_flagship_equip(self): @@ -170,24 +140,68 @@ class GemsFarming(CampaignRun, Dock): def change_vanguard_equip(self): return 'equip' in self.config.GemsFarming_ChangeVanguard + @property + def allow_high_flagship_level(self): + return self.config.GemsFarming_ALLowHighFlagshipLevel + + @property + def max_level(self): + if self.config.SERVER == 'cn': + return 100 + else: + return 70 + + @property + def min_emotion(self): + return (2 + self.campaign._map_battle) * self.campaign.emotion.reduce_per_battle + + _new_fleet_emotion = 0 + @property def fleet_to_attack(self): + if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all': + return 2 + else: + return 1 + + @property + def fleet_to_attack_index(self): if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all': return self.config.Fleet_Fleet2 else: return self.config.Fleet_Fleet1 - def _fleet_detail_enter(self, fleet): + @Config.when(Campaign_Mode='normal') + def ui_goto_fleet(self): self.ui_ensure(page_fleet) - self.ui_ensure_index(fleet, letter=OCR_FLEET_INDEX, - next_button=FLEET_NEXT, prev_button=FLEET_PREV, skip_first_screenshot=True) + + # ui_ensure_index, set fleet + letter = FLEET_INDEX + next_button = FLEET_NEXT + prev_button = FLEET_PREV + interval = (0.2, 0.3) - def _ship_detail_enter(self, button): - self.ui_click(FLEET_DETAIL, appear_button=page_fleet.check_button, - check_button=FLEET_DETAIL_CHECK, skip_first_screenshot=True) - self.ship_info_enter(button, long_click=False) + retry = Timer(1, count=2) + for _ in self.loop(): + current = letter.ocr(self.device.image) + logger.attr("Index", current) - def _fleet_detail_enter_hard(self, fleet): + # ui_ensure_index but ignore default value 0 + # otherwise we would have 1 extra click switching from 1 to 4 + if current == 0: + continue + + diff = self.fleet_to_attack_index - current + if diff == 0: + break + + if retry.reached(): + button = next_button if diff > 0 else prev_button + self.device.multi_click(button, n=abs(diff), interval=interval) + retry.reset() + + @Config.when(Campaign_Mode='hard') + def ui_goto_fleet(self): if self.appear(FLEET_PREPARATION, offset=(20, 50)): return self.campaign.ensure_campaign_ui(self.stage, 'hard') @@ -210,228 +224,65 @@ class GemsFarming(CampaignRun, Dock): campaign_timer.reset() continue - def _ship_detail_enter_hard(self, button): - self.ship_info_enter(button) + @property + def fleet_check_button(self): + if self.config.Campaign_Mode == 'hard': + return FLEET_PREPARATION + return page_fleet.check_button - def _fleet_back(self): - self.ui_back(FLEET_DETAIL_CHECK) - self.ui_back(FLEET_CHECK) + @property + def fleet_backline_1_button(self): + if self.config.Campaign_Mode == 'hard': + return globals()[f'FLEET_{self.fleet_to_attack}_BACKLINE_1'] + return FLEET_ENTER_FLAGSHIP - def _fleet_back_hard(self): - self.ui_back(self.page_fleet_check_button) + @property + def fleet_vanguard_1_button(self): + if self.config.Campaign_Mode == 'hard': + return globals()[f'FLEET_{self.fleet_to_attack}_VANGUARD_1'] + return FLEET_ENTER - def flagship_change(self): - """ - Change flagship and flagship's equipment using gear code + def ui_enter_ship(self, click_button, long_click=True): + if long_click: + enter_button_map = { + FLEET_ENTER_FLAGSHIP: FLEET_DETAIL_ENTER_FLAGSHIP, + FLEET_ENTER: FLEET_DETAIL_ENTER, + } + enter_button = enter_button_map.get(click_button) + if enter_button is None: + self.ship_info_enter(click_button=click_button, long_click=True, skip_first_screenshot=False) + return - Returns: - bool: True if flagship changed. - """ - logger.hr('Change flagship', level=1) - logger.attr('ChangeFlagship', self.config.GemsFarming_ChangeFlagship) - self._fleet_detail_enter(self.fleet_to_attack) - if self.change_flagship_equip: - logger.hr('Unmount flagship equipments', level=2) - self._ship_detail_enter(self.fleet_detail_enter_flagship) - self.ship_equipment_take_off() - self._fleet_back() - - logger.hr('Change flagship', level=2) - success = self.flagship_change_execute() - - if self.change_flagship_equip: - logger.hr('Mount flagship equipments', level=2) - self._ship_detail_enter(self.fleet_detail_enter_flagship) - self.ship_equipment_take_on() - self._fleet_back() - - return success - - def vanguard_change(self): - """ - Change vanguard and vanguard's equipment using gear code - - Returns: - bool: True if vanguard changed - """ - logger.hr('Change vanguard', level=1) - logger.attr('ChangeVanguard', self.config.GemsFarming_ChangeVanguard) - self._fleet_detail_enter(self.fleet_to_attack) - if self.change_vanguard_equip: - logger.hr('Unmount vanguard equipments', level=2) - self._ship_detail_enter(self.fleet_detail_enter) - self.ship_equipment_take_off() - self._fleet_back() - - logger.hr('Change vanguard', level=2) - success = self.vanguard_change_execute() - - if self.change_vanguard_equip: - logger.hr('Mount vanguard equipments', level=2) - self._ship_detail_enter(self.fleet_detail_enter) - self.ship_equipment_take_on() - self._fleet_back() - - return success - - def _ship_change_confirm(self, button): - self.dock_select_one(button) - self.dock_reset() - self.dock_select_confirm(check_button=self.page_fleet_check_button) - - def get_common_rarity_cv(self, lv=31, emotion=16): - """ - Get a common rarity cv by config.GemsFarming_CommonCV - If config.GemsFarming_CommonCV == 'any', return a common lv1 ~ lv33 cv - - _dock_reset() needs to be called later. - - Args: - lv (int): max level of common cv - emotion (int): min emotion of common cv - Returns: - Ship: - """ - faction = 'eagle' if self.config.GemsFarming_CommonCV == 'eagle' else 'all' - extra = 'can_limit_break' if self.config.GemsFarming_ALLowHighFlagshipLevel else 'enhanceable' - self.dock_favourite_set(False, wait_loading=False) - self.dock_sort_method_dsc_set(False, wait_loading=False) - self.dock_filter_set( - index='cv', rarity='common', faction=faction, extra=extra, sort='total') - - logger.hr('FINDING FLAGSHIP') - - if self.config.GemsFarming_ALLowHighFlagshipLevel: - if self.config.SERVER in ['cn']: - max_level = 100 - else: - max_level = 70 - min_level = max_level + self.ui_click(FLEET_DETAIL, appear_button=self.fleet_check_button, + check_button=FLEET_DETAIL_CHECK, skip_first_screenshot=True) + self.ship_info_enter(enter_button, long_click=False) else: - max_level = lv - min_level = 1 - emotion_lower_bound = 0 if emotion == 0 else self.emotion_lower_bound - fleet = [0, self.fleet_to_attack] if self.config.GemsFarming_ALLowHighFlagshipLevel else self.fleet_to_attack - scanner = ShipScanner( - level=(min_level, max_level), emotion=(emotion_lower_bound, 150), fleet=fleet, status='free') - scanner.disable('rarity') - - if not self.config.GemsFarming_ALLowHighFlagshipLevel: - ships = scanner.scan(self.device.image) - if ships: - # Don't need to change current - return ships - - # Change to any ship - scanner.set_limitation(fleet=0) - - if self.config.GemsFarming_CommonCV in ['custom', 'any', 'eagle']: - candidates = self.find_custom_candidates(scanner, ship_type='cv') - - if candidates: - # Change to specific ship - return candidates - - return scanner.scan(self.device.image, output=False) + self.ship_info_enter(click_button=click_button, check_button=DOCK_CHECK, + long_click=False, skip_first_screenshot=False) + def ui_leave_ship(self, check_button=None): + if check_button is None: + check_button = self.fleet_check_button + if check_button == page_fleet.check_button: + self.ui_back(check_button=[FLEET_DETAIL_CHECK, page_fleet.check_button]) + self.ui_back(check_button=page_fleet.check_button) else: - template = TEMPLATE_COMMON_CV[f'{self.config.GemsFarming_CommonCV.upper()}'] + self.ui_back(check_button=check_button) - candidates = [ship for ship in scanner.scan(self.device.image, output=False) - if template.match(self.image_crop(ship.button, copy=False), similarity=SIM_VALUE)] - - if candidates: - # Change to specific ship - return candidates - - logger.info('No specific CV was found, try reversed order.') - self.dock_sort_method_dsc_set(True) - - candidates = [ship for ship in scanner.scan(self.device.image) - if template.match(self.image_crop(ship.button, copy=False), similarity=SIM_VALUE)] - - return candidates - - def get_common_rarity_dd(self, emotion=16): + def find_candidates(self, templates, scanner: ShipScanner, output=False): """ - Get a common rarity dd with level is 100 (70 for servers except CN) - and emotion >= self.emotion_lower_bound - - _dock_reset() needs to be called later. - - Args: - emotion (int): min emotion of common dd - Returns: - Ship: + Find candidates based on template matching using a scanner. """ - rarity = 'common' - extra = 'can_limit_break' - if self.config.GemsFarming_CommonDD in ['any', 'custom']: - faction = ['eagle', 'iron'] - elif self.config.GemsFarming_CommonDD == 'favourite': - faction = 'all' - elif self.config.GemsFarming_CommonDD == 'z20_or_z21': - faction = 'iron' - elif self.config.GemsFarming_CommonDD == 'DDG': - faction = 'dragon' - rarity = 'super_rare' - extra = 'no_limit' - elif self.config.GemsFarming_CommonDD in ['aulick_or_foote', 'cassin_or_downes']: - faction = 'eagle' - else: - logger.error(f'Invalid CommonDD setting: {self.config.GemsFarming_CommonDD}') - raise ScriptError('Invalid GemsFarming_CommonDD') - favourite = self.config.GemsFarming_CommonDD == 'favourite' - self.dock_favourite_set(favourite, wait_loading=False) - self.dock_sort_method_dsc_set(True, wait_loading=False) - self.dock_filter_set( - index='dd', rarity=rarity, faction=faction, extra=extra) - - logger.hr('FINDING VANGUARD') - - if self.config.SERVER in ['cn']: - max_level = 100 - else: - max_level = 70 - if self.config.GemsFarming_CommonDD == 'DDG': - max_level = 125 - if self.config.GemsFarming_ALLowLowVanguardLevel: - min_level = 30 - else: - min_level = max_level - if self.hard_mode: - min_level = max(min_level, 70) - emotion_lower_bound = 0 if emotion == 0 else self.emotion_lower_bound - scanner = ShipScanner(level=(min_level, max_level), emotion=(emotion_lower_bound, 150), - fleet=[0, self.fleet_to_attack], status='free') - scanner.disable('rarity') - - if self.config.GemsFarming_CommonDD in ['any', 'favourite', 'z20_or_z21', 'DDG']: - # Change to any ship - return scanner.scan(self.device.image) - - elif self.config.GemsFarming_CommonDD == 'custom': - candidates = self.find_custom_candidates(scanner, ship_type='dd') - - if candidates: - # Change to specific ship - return candidates - - return scanner.scan(self.device.image, output=False) - - else: - candidates = self.find_candidates(self.get_templates(self.config.GemsFarming_CommonDD), scanner) - - if candidates: - # Change to specific ship - return candidates - - logger.info('No specific DD was found, try reversed order.') - self.dock_sort_method_dsc_set(False) - - # Change specific ship - candidates = self.find_candidates(self.get_templates(self.config.GemsFarming_CommonDD), scanner) - return candidates + ships = scanner.scan(self.device.image, output=output) + if not templates: + return ships + candidates = [] + for ship in ships: + for template in templates: + if template.match(self.image_crop(ship.button, copy=False), similarity=SIM_VALUE): + candidates.append(ship) + break + return candidates def find_custom_candidates(self, scanner, ship_type='cv'): """ @@ -487,163 +338,342 @@ class GemsFarming(CampaignRun, Dock): return [] - def find_candidates(self, template, scanner): + def get_cv_templates(self): """ - Find candidates based on template matching using a scanner. + Get CV templates based on config.GemsFarming_CommonCV + Returns: + list[Template]: CV templates """ - candidates = [] - if isinstance(template, list): - for item in template: - candidates = [ship for ship in scanner.scan(self.device.image, output=False) - if item.match(self.image_crop(ship.button, copy=False), similarity=SIM_VALUE)] - if candidates: - break + if self.config.GemsFarming_CommonCV in ['custom', 'any', 'eagle']: + return [] else: - candidates = [ship for ship in scanner.scan(self.device.image, output=False) - if template.match(self.image_crop(ship.button, copy=False), similarity=SIM_VALUE)] - return candidates + templates = { + 'bogue': TEMPLATE_BOGUE, + 'hermes': TEMPLATE_HERMES, + 'langley': TEMPLATE_LANGLEY, + 'ranger': TEMPLATE_RANGER, + } + return [templates[self.config.GemsFarming_CommonCV]] - @staticmethod - def get_templates(common_dd): + def get_common_rarity_cv(self, max_level=31, min_emotion=0): """ - Returns the corresponding template list based on CommonDD + Get a common rarity cv by config.GemsFarming_CommonCV + If config.GemsFarming_CommonCV == 'any', return a common lv1 ~ lv31 cv by default. + + Returns: + list[Ship]: Common rarity CVs that meet the level, emotion and fleet requirements. """ - if common_dd == 'aulick_or_foote': + faction = 'eagle' if self.config.GemsFarming_CommonCV == 'eagle' else 'all' + extra = 'can_limit_break' if self.allow_high_flagship_level else 'enhanceable' + self.dock_favourite_set(False, wait_loading=False) + self.dock_sort_method_dsc_set(False, wait_loading=False) + self.dock_filter_set(index='cv', rarity='common', faction=faction, extra=extra, sort='total') + + logger.hr('FINDING FLAGSHIP') + templates = self.get_cv_templates() + if self.allow_high_flagship_level: + min_level = self.max_level + max_level = self.max_level + else: + min_level = 1 + fleet = [0, self.fleet_to_attack_index] if self.allow_high_flagship_level else self.fleet_to_attack_index + scanner = ShipScanner(level=(min_level, max_level), emotion=(min_emotion, 150), fleet=fleet, status='free') + scanner.disable('rarity') + + if not self.allow_high_flagship_level: + candidates = self.find_candidates(templates, scanner, output=True) + if candidates: + return candidates + + scanner.set_limitation(fleet=0) + + if self.config.GemsFarming_CommonCV in ['custom', 'any', 'eagle']: + candidates = self.find_custom_candidates(scanner, ship_type='cv') + return candidates + else: + candidates = self.find_candidates(templates, scanner, output=False) + if candidates or templates == []: + return candidates + + logger.info('No specific CV was found, try reversed order.') + self.dock_sort_method_dsc_set(True) + candidates = self.find_candidates(templates, scanner, output=True) + return candidates + + @Config.when(Campaign_Mode='normal') + def flagship_change_execute(self): + self.ui_enter_ship(FLEET_ENTER_FLAGSHIP, long_click=False) + candidate = self.get_common_rarity_cv(min_emotion=self.min_emotion) + if candidate: + ship = max(candidate, key=lambda s: (s.level, s.emotion)) + if self.allow_high_flagship_level: + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=page_fleet.check_button) + logger.info('Change flagship success') + return True + + logger.info('Change flagship failed, no CV in common rarity.') + self._new_fleet_emotion = 0 + self.dock_reset() + self.ui_leave_ship() + return False + + @Config.when(Campaign_Mode='hard') + def flagship_change_execute(self): + unmount_button = globals()[f'FLEET_{self.fleet_to_attack}_BACKLINE_1'] + mount_button = globals()[f'FLEET_{self.fleet_to_attack}_BACKLINE_3'] + + if self.appear(unmount_button, offset=(20, 20)): + logger.info('No flagship to unmount, skip unmounting.') + else: + self.ui_enter_ship(unmount_button, long_click=False) + self.ui_click(DOCK_UNMOUNT, check_button=FLEET_PREPARATION, appear_button=DOCK_CHECK, + additional=self.ensure_no_info_bar, confirm_wait=1, retry_wait=5) + + self.ui_enter_ship(mount_button, long_click=False) + candidate = self.get_common_rarity_cv(max_level=31, min_emotion=self.min_emotion) + if candidate: + ship = max(candidate, key=lambda s: (s.level, s.emotion)) + if self.allow_high_flagship_level: + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=FLEET_PREPARATION) + logger.info('Change flagship success') + return True + + logger.info('Change flagship failed, try using leveled and exhausted CVs.') + candidate = self.get_common_rarity_cv(max_level=self.max_level, min_emotion=0) + if candidate: + ship = min(candidate, key=lambda s: (s.level, -s.emotion)) + if self.allow_high_flagship_level: + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=FLEET_PREPARATION) + return False + + logger.info('Change flagship failed, no CV was found.') + self._new_fleet_emotion = 0 + self.dock_reset() + self.ui_leave_ship() + return False + + def flagship_change(self): + """ + Change flagship and flagship's equipment + + Returns: + bool: True if flagship changed. + """ + logger.hr('Change flagship', level=1) + logger.attr('ChangeFlagship', self.config.GemsFarming_ChangeFlagship) + self.ui_goto_fleet() + button = self.fleet_backline_1_button + + if self.change_flagship_equip and not self.appear(button, offset=(20, 20)): + logger.hr('Unmount flagship equipments', level=2) + self.ui_enter_ship(button, long_click=True) + self.ship_equipment_take_off() + self.ui_leave_ship() + + logger.hr('Change flagship', level=2) + success = self.flagship_change_execute() + + if self.change_flagship_equip and not self.appear(button, offset=(20, 20)): + logger.hr('Mount flagship equipments', level=2) + self.ui_enter_ship(button, long_click=True) + self.ship_equipment_take_on() + self.ui_leave_ship() + + return success + + def get_dd_faction(self): + if self.config.GemsFarming_CommonDD in ['any', 'custom']: + faction = ['eagle', 'iron'] + elif self.config.GemsFarming_CommonDD == 'favourite': + faction = 'all' + elif self.config.GemsFarming_CommonDD == 'z20_or_z21': + faction = 'iron' + elif self.config.GemsFarming_CommonDD == 'DDG': + faction = 'dragon' + elif self.config.GemsFarming_CommonDD in ['aulick_or_foote', 'cassin_or_downes']: + faction = 'eagle' + else: + logger.error(f'Invalid CommonDD setting: {self.config.GemsFarming_CommonDD}') + logger.error("Default to 'eagle' and 'iron' faction.") + faction = ['eagle', 'iron'] + return faction + + def get_dd_templates(self): + """ + Get DD templates based on config.GemsFarming_CommonDD + + Returns: + list[Template]: DD templates + """ + if self.config.GemsFarming_CommonDD == 'aulick_or_foote': return [ TEMPLATE_AULICK, TEMPLATE_FOOTE ] - elif common_dd == 'cassin_or_downes': + elif self.config.GemsFarming_CommonDD == 'cassin_or_downes': return [ TEMPLATE_CASSIN_1, TEMPLATE_CASSIN_2, TEMPLATE_DOWNES_1, TEMPLATE_DOWNES_2 ] else: - logger.error(f'Invalid CommonDD setting: {common_dd}') - raise ScriptError(f'Invalid CommonDD setting: {common_dd}') + return [] - def ship_down_hard(self): + def get_common_rarity_dd(self, min_emotion=0): """ - In hard mode, let the ship leave the fleet first - """ - if self.appear(DOCK_SHIP_DOWN): - self.ui_click(DOCK_SHIP_DOWN, - appear_button=DOCK_CHECK, check_button=self.page_fleet_check_button, skip_first_screenshot=True) - else: - self.ui_back(check_button=FLEET_PREPARATION) + Get a common rarity dd by config.GemsFarming_CommonDD + If config.GemsFarming_CommonDD == 'any', return a common self.max_level dd by default. - def dock_enter(self, button): - for _ in self.loop(): - if self.appear(DOCK_CHECK, offset=(20, 20)): - break - if self.appear(self.page_fleet_check_button, offset=(30, 30), interval=5): - self.device.click(button) - continue - # 2025.05.29 game tips that infos skin feature when you enter dock - if self.handle_game_tips(): - return False - return True - - def flagship_change_with_emotion(self, ship): - """ - Change flagship and calculate emotion - """ - target_ship = max(ship, key=lambda s: (s.level, s.emotion)) - if self.config.GemsFarming_ALLowHighFlagshipLevel: - self.set_emotion(target_ship.emotion) - self._ship_change_confirm(target_ship.button) - - def flagship_change_execute(self): - """ Returns: - bool: If success. - - Pages: - in: page_fleet - out: page_fleet + list[Ship]: Common rarity DDs that meet the emotion and fleet requirements. """ - if self.hard_mode: - if not self.dock_enter(self.fleet_detail_enter_flagship): - return True - self.ship_down_hard() - if not self.dock_enter(self.fleet_enter_flagship): - return True - - ship = self.get_common_rarity_cv() - if ship: - self.flagship_change_with_emotion(ship) - logger.info('Change flagship success') - return True + if self.config.GemsFarming_CommonDD == 'DDG': + rarity = 'super_rare' + extra = 'no_limit' else: - logger.info('Change flagship failed, no CV in common rarity.') + rarity = 'common' + extra = 'can_limit_break' + faction = self.get_dd_faction() + self.dock_favourite_set(self.config.GemsFarming_CommonDD == 'favourite', wait_loading=False) + self.dock_sort_method_dsc_set(True, wait_loading=False) + self.dock_filter_set(index='dd', rarity=rarity, faction=faction, extra=extra) - if self.config.SERVER in ['cn']: - max_level = 100 - else: - max_level = 70 - ship = self.get_common_rarity_cv(lv=max_level, emotion=0) - if ship and self.hard_mode: - self.flagship_change_with_emotion(ship) - else: - if self.hard_mode: - raise RequestHumanTakeover - self.dock_reset() - self.ui_back(check_button=self.page_fleet_check_button) - return False + logger.hr('FINDING VANGUARD') + templates = self.get_dd_templates() + max_level = 125 if self.config.GemsFarming_CommonDD == 'DDG' else self.max_level + min_level = 30 if self.config.GemsFarming_ALLowLowVanguardLevel else max_level + scanner = ShipScanner(level=(min_level, max_level), emotion=(min_emotion, 150), fleet=[0, self.fleet_to_attack_index], status='free') + scanner.disable('rarity') - def vanguard_change_with_emotion(self, ship): - """ - Change vanguard and calculate emotion - """ - target_ship = max(ship, key=lambda s: s.emotion) - if self.config.GemsFarming_ALLowHighFlagshipLevel: - self.set_emotion(min(self.get_emotion(), target_ship.emotion)) - else: - self.set_emotion(target_ship.emotion) - self._ship_change_confirm(target_ship.button) + candidates = self.find_candidates(templates, scanner, output=True) + if candidates or templates == []: + return candidates + logger.info('No specific DD was found, try reversed order.') + self.dock_sort_method_dsc_set(False) + candidates = self.find_candidates(templates, scanner, output=True) + return candidates + + @Config.when(Campaign_Mode='normal') def vanguard_change_execute(self): - """ - Returns: - bool: If success. - - Pages: - in: page_fleet - out: page_fleet - """ - if self.hard_mode: - if not self.dock_enter(self.fleet_detail_enter): - return True - self.ship_down_hard() - if not self.dock_enter(self.fleet_enter): + self.ui_enter_ship(FLEET_ENTER, long_click=False) + candidate = self.get_common_rarity_dd(min_emotion=self.min_emotion) + if candidate: + ship = max(candidate, key=lambda s: s.emotion) + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=page_fleet.check_button) + logger.info('Change vanguard success') return True - ship = self.get_common_rarity_dd() - if ship: - self.vanguard_change_with_emotion(ship) - logger.info('Change vanguard ship success') - return True + logger.info('Change vanguard failed, no DD in common rarity.') + self._new_fleet_emotion = 0 + self.dock_reset() + self.ui_leave_ship() + return False + + @Config.when(Campaign_Mode='hard') + def vanguard_change_execute(self): + unmount_button = globals()[f'FLEET_{self.fleet_to_attack}_VANGUARD_1'] + mount_button = globals()[f'FLEET_{self.fleet_to_attack}_VANGUARD_3'] + + if self.appear(unmount_button, offset=(20, 20)): + logger.info('No flagship to unmount, skip unmounting.') else: - logger.info('Change vanguard ship failed, no DD in common rarity.') + self.ui_enter_ship(unmount_button, long_click=False) + self.ui_click(DOCK_UNMOUNT, check_button=FLEET_PREPARATION, appear_button=DOCK_CHECK, + additional=self.ensure_no_info_bar, confirm_wait=1, retry_wait=5) - ship = self.get_common_rarity_dd(emotion=0) - if ship and self.hard_mode: - self.vanguard_change_with_emotion(ship) - else: - if self.hard_mode: - raise RequestHumanTakeover - self.dock_reset() - self.ui_back(check_button=self.page_fleet_check_button) + self.ui_enter_ship(mount_button, long_click=False) + candidate = self.get_common_rarity_dd(min_emotion=self.min_emotion) + if candidate: + ship = max(candidate, key=lambda s: s.emotion) + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=FLEET_PREPARATION) + logger.info('Change vanguard success') + return True + + logger.info('Change vanguard failed, try using exhausted DDs.') + candidate = self.get_common_rarity_dd(min_emotion=0) + if candidate: + ship = max(candidate, key=lambda s: s.emotion) + self._new_fleet_emotion = min(ship.emotion, self._new_fleet_emotion) if self._new_fleet_emotion else ship.emotion + self.dock_select_one(ship.button) + self.dock_reset() + self.dock_select_confirm(check_button=FLEET_PREPARATION) return False - _trigger_lv32 = False - _trigger_emotion = False + logger.info('Change vanguard failed, no DD was found.') + self._new_fleet_emotion = 0 + self.dock_reset() + self.ui_leave_ship() + return False + + def vanguard_change(self): + """ + Change vanguard and vanguard's equipment + + Returns: + bool: True if vanguard changed. + """ + logger.hr('Change vanguard', level=1) + logger.attr('ChangeVanguard', self.config.GemsFarming_ChangeVanguard) + self.ui_goto_fleet() + button = self.fleet_vanguard_1_button + + if self.change_vanguard_equip and not self.appear(button, offset=(20, 20)): + logger.hr('Unmount vanguard equipments', level=2) + self.ui_enter_ship(button, long_click=True) + self.ship_equipment_take_off() + self.ui_leave_ship() + + logger.hr('Change vanguard', level=2) + success = self.vanguard_change_execute() + + if self.change_vanguard_equip and not self.appear(button, offset=(20, 20)): + logger.hr('Mount vanguard equipments', level=2) + self.ui_enter_ship(button, long_click=True) + self.ship_equipment_take_on() + self.ui_leave_ship() + + return success + + def hard_fleet_prepare(self): + """ + Fill empty hard-mode fleet slots after ships used for hard requirements were retired. + + Returns: + bool: True if any slot has been filled. + """ + prepared = False + if self.appear(self.fleet_backline_1_button, offset=(20, 20)): + logger.info('Backline is empty, change flagship') + self.flagship_change() + prepared = True + if self.appear(self.fleet_vanguard_1_button, offset=(20, 20)): + logger.info('Vanguard is empty, change vanguard') + self.vanguard_change() + prepared = True + return prepared + + _trigger_lv32: bool = False + _trigger_emotion: bool = False def triggered_stop_condition(self, oil_check=True): # Lv32 limit - if self.change_flagship and self.campaign.config.LV32_TRIGGERED \ - and not self.config.GemsFarming_ALLowHighFlagshipLevel: + if self.campaign.config.LV32_TRIGGERED: self._trigger_lv32 = True logger.hr('TRIGGERED LV32 LIMIT') return True @@ -655,24 +685,6 @@ class GemsFarming(CampaignRun, Dock): return super().triggered_stop_condition(oil_check=oil_check) - def get_emotion(self): - """ - Get fleet emotion value from config - """ - if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all': - return self.campaign.config.Emotion_Fleet2Value - else: - return self.campaign.config.Emotion_Fleet1Value - - def set_emotion(self, emotion): - """ - Set fleet emotion value - """ - if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all': - self.campaign.config.set_record(Emotion_Fleet2Value=emotion) - else: - self.campaign.config.set_record(Emotion_Fleet1Value=emotion) - def run(self, name, folder='campaign_main', mode='normal', total=0): """ Args: @@ -681,65 +693,28 @@ class GemsFarming(CampaignRun, Dock): mode (str): `normal` or `hard` total (int): """ - self.config.STOP_IF_REACH_LV32 = self.change_flagship - ship_change_attempted = False + self.config.override(STOP_IF_REACH_LV32=True) + while 1: self._trigger_lv32 = False is_limit = self.config.StopCondition_RunCount + try: super().run(name=name, folder=folder, total=total) except CampaignEnd as e: - if e.args[0] == 'Emotion control': + if "Emotion" in e.args[0]: self._trigger_emotion = True - elif e.args[0] == 'Emotion withdraw': - self._trigger_emotion = True - self.set_emotion(0) else: - raise e - except RequestHumanTakeover as e: - if (not e.args or e.args[0] != 'Hard not satisfied' - or not (self.change_flagship or self.change_vanguard)): - raise - - if ship_change_attempted: - logger.critical("Hard mode requirements still not satisfied after ship change") raise - attack_fleet = ('FLEET_2' if self.config.Fleet_FleetOrder == 'fleet1_standby_fleet2_all' - else 'FLEET_1') - if e.args[1:] != (attack_fleet, ): - logger.critical("Fleet not meeting requirements is not (or not only) the attack fleet, " \ - "please check ALAS settings and in-game fleet preparation") - raise - - logger.warning('Hard mode requirements not satisfied, attempting ship change once') - try: - self.hard_mode_override() - if self.change_flagship: - self.flagship_change() - if self.change_vanguard: - self.vanguard_change() - ship_change_attempted = True - continue - except RequestHumanTakeover: - logger.warning("Failed to change ship") - raise - except Exception: - from module.exception import GameStuckError - raise GameStuckError - - ship_change_attempted = False - + # End if self._trigger_lv32 or self._trigger_emotion: - success = True - self.hard_mode_override() - emotion = self.get_emotion() - if self.change_flagship: - success = self.flagship_change() - if self.change_vanguard and success: - success = self.vanguard_change() - if not success and self.config.GemsFarming_ALLowHighFlagshipLevel: - self.set_emotion(emotion) + self._new_fleet_emotion = 150 + success = self.flagship_change() + if self.change_vanguard: + success = success and self.vanguard_change() + + self.campaign.config.set_record(Emotion_Fleet1Value=self._new_fleet_emotion) if is_limit and self.config.StopCondition_RunCount <= 0: logger.hr('Triggered stop condition: Run count') @@ -748,22 +723,19 @@ class GemsFarming(CampaignRun, Dock): break self._trigger_lv32 = False + self._trigger_emotion = False self.campaign.config.LV32_TRIGGERED = False self.campaign.config.GEMS_EMOTION_TRIGGERED = False # Scheduler if self.config.task_switched(): - self._trigger_emotion = False self.campaign.ensure_auto_search_exit() self.config.task_stop() - elif not success and (self.config.GemsFarming_DelayTaskIFNoFlagship \ - or self._trigger_emotion): - self._trigger_emotion = False + elif not success: self.campaign.ensure_auto_search_exit() self.config.task_delay(minute=30) self.config.task_stop() - self._trigger_emotion = False continue else: break diff --git a/module/campaign/run.py b/module/campaign/run.py index be9ebc2cd..bdfddcd44 100644 --- a/module/campaign/run.py +++ b/module/campaign/run.py @@ -420,7 +420,8 @@ class CampaignRun(CampaignEvent, ShopStatus): # Because event_20240725 task balancer delete self.campaign.ensure_auto_search_exit() self.campaign.ensure_campaign_ui(name=self.stage, mode=mode) else: - self.campaign.ensure_campaign_ui(name=self.stage, mode=mode) + self.campaign.ensure_campaign_ui(name=self.stage, mode=mode) + self.config.override(Campaign_Mode=self.campaign.config.Campaign_Mode) self.disable_raid_on_event() self.handle_commission_notice() diff --git a/module/coalition/combat.py b/module/coalition/combat.py index 2df319b93..feab3c93b 100644 --- a/module/coalition/combat.py +++ b/module/coalition/combat.py @@ -29,6 +29,8 @@ class CoalitionCombat(CoalitionUI, CampaignBase): # End if self.is_combat_loading(): break + if self.is_combat_executing(): + break if self.in_coalition(): raise CampaignEnd diff --git a/module/combat/auto_search_combat.py b/module/combat/auto_search_combat.py index 36d97edd4..6220b3142 100644 --- a/module/combat/auto_search_combat.py +++ b/module/combat/auto_search_combat.py @@ -307,6 +307,12 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): self.config.Scheduler_Enable = False self.config.task_stop() + def auto_search_combat_end(self): + """ + A custom combat end that used in coalition + """ + return False + def auto_search_combat_execute(self, emotion_reduce, fleet_index, battle=None, expected_end=None): """ Args: @@ -414,6 +420,8 @@ class AutoSearchCombat(MapOperation, Combat, CampaignStatus): if expected_end(): self.device.screenshot_interval_set() break + if self.auto_search_combat_end(): + break def auto_search_combat_status(self, emotion_reduce, fleet_index): """ diff --git a/module/config/argument/argument.yaml b/module/config/argument/argument.yaml index a368aa565..025086a46 100644 --- a/module/config/argument/argument.yaml +++ b/module/config/argument/argument.yaml @@ -295,7 +295,7 @@ GemsFarming: option: [ disabled, ship, ship_equip ] CommonDD: value: any - option: [ custom, any, favourite, aulick_or_foote , cassin_or_downes, z20_or_z21, DDG] + option: [ custom, any, favourite, aulick_or_foote , cassin_or_downes, z20_or_z21, DDG ] CommonDDFilter: |- z20 > z21 > aulick > foote > cassin > downes EquipmentCode: diff --git a/module/daily/daily.py b/module/daily/daily.py index 508675769..66b2d2c2d 100644 --- a/module/daily/daily.py +++ b/module/daily/daily.py @@ -5,7 +5,6 @@ from module.base.utils import get_color from module.combat.assets import BATTLE_PREPARATION from module.combat.combat import Combat from module.daily.assets import * -from module.daily.equipment import DailyEquipment from module.logger import logger from module.ocr.ocr import Digit from module.ui.assets import BACK_ARROW, DAILY_CHECK @@ -16,7 +15,7 @@ OCR_REMAIN = Digit(OCR_REMAIN, letter=(222, 223, 222), threshold=128, alphabet=' OCR_DAILY_FLEET_INDEX = Digit(OCR_DAILY_FLEET_INDEX, letter=(90, 154, 255), threshold=128, alphabet='123456') -class Daily(Combat, DailyEquipment): +class Daily(Combat): daily_current: int daily_checked: list emergency_module_development = False @@ -342,9 +341,7 @@ class Daily(Combat, DailyEquipment): in: Any page out: page_daily """ - # self.equipment_take_on() self.daily_run() - # self.equipment_take_off() # Cannot stay in page_daily, because order is disordered. self.config.task_delay(server_update=True) diff --git a/module/daily/equipment.py b/module/daily/equipment.py deleted file mode 100644 index 6e11bd08b..000000000 --- a/module/daily/equipment.py +++ /dev/null @@ -1,38 +0,0 @@ -from module.equipment.fleet_equipment import FleetEquipment -from module.logger import logger - - -class DailyEquipment(FleetEquipment): - - def fleet_enter(self, fleet=None): - fleet = self.config.FLEET_DAILY - if isinstance(fleet, list): - logger.info(f'Multiple daily fleets are set, change equipment only for the first one. fleet: {fleet}') - fleet = fleet[0] - super().fleet_enter(fleet) - - def equipment_take_on(self): - if self.config.FLEET_DAILY_EQUIPMENT is None: - return False - if self.equipment_has_take_on: - return False - - self.fleet_enter() - self.fleet_equipment_take_on_preset(preset_record=self.config.FLEET_DAILY_EQUIPMENT) - self.ui_back(self.is_in_main) - self.equipment_has_take_on = True - self.device.sleep(1) - return True - - def equipment_take_off(self): - if self.config.FLEET_DAILY_EQUIPMENT is None: - return False - if not self.equipment_has_take_on: - return False - - self.fleet_enter() - self.fleet_equipment_take_off() - self.ui_back(self.is_in_main) - self.equipment_has_take_on = False - self.device.sleep(1) - return True diff --git a/module/equipment/assets.py b/module/equipment/assets.py index 79f5ba584..0dc6ae159 100644 --- a/module/equipment/assets.py +++ b/module/equipment/assets.py @@ -36,6 +36,14 @@ EQUIP_TAKE_ON_1 = Button(area={'cn': (907, 338, 991, 431), 'en': (907, 338, 991, EQUIP_TAKE_ON_2 = Button(area={'cn': (866, 511, 950, 604), 'en': (866, 511, 950, 604), 'jp': (866, 511, 950, 604), 'tw': (866, 511, 950, 604)}, color={'cn': (117, 118, 127), 'en': (117, 118, 127), 'jp': (117, 118, 127), 'tw': (117, 118, 127)}, button={'cn': (866, 511, 950, 604), 'en': (866, 511, 950, 604), 'jp': (866, 511, 950, 604), 'tw': (866, 511, 950, 604)}, file={'cn': './assets/cn/equipment/EQUIP_TAKE_ON_2.png', 'en': './assets/en/equipment/EQUIP_TAKE_ON_2.png', 'jp': './assets/jp/equipment/EQUIP_TAKE_ON_2.png', 'tw': './assets/tw/equipment/EQUIP_TAKE_ON_2.png'}) EQUIP_TAKE_ON_3 = Button(area={'cn': (129, 252, 213, 345), 'en': (129, 252, 213, 345), 'jp': (129, 252, 213, 345), 'tw': (129, 252, 213, 345)}, color={'cn': (105, 108, 115), 'en': (105, 108, 115), 'jp': (105, 108, 115), 'tw': (105, 108, 115)}, button={'cn': (129, 252, 213, 345), 'en': (129, 252, 213, 345), 'jp': (129, 252, 213, 345), 'tw': (129, 252, 213, 345)}, file={'cn': './assets/cn/equipment/EQUIP_TAKE_ON_3.png', 'en': './assets/en/equipment/EQUIP_TAKE_ON_3.png', 'jp': './assets/jp/equipment/EQUIP_TAKE_ON_3.png', 'tw': './assets/tw/equipment/EQUIP_TAKE_ON_3.png'}) EQUIP_TAKE_ON_4 = Button(area={'cn': (128, 432, 212, 525), 'en': (128, 432, 212, 525), 'jp': (128, 432, 212, 525), 'tw': (128, 432, 212, 525)}, color={'cn': (109, 111, 120), 'en': (109, 111, 120), 'jp': (109, 111, 120), 'tw': (109, 111, 120)}, button={'cn': (128, 432, 212, 525), 'en': (128, 432, 212, 525), 'jp': (128, 432, 212, 525), 'tw': (128, 432, 212, 525)}, file={'cn': './assets/cn/equipment/EQUIP_TAKE_ON_4.png', 'en': './assets/en/equipment/EQUIP_TAKE_ON_4.png', 'jp': './assets/jp/equipment/EQUIP_TAKE_ON_4.png', 'tw': './assets/tw/equipment/EQUIP_TAKE_ON_4.png'}) +FLEET_1_BACKLINE_1 = Button(area={'cn': (412, 195, 456, 239), 'en': (412, 195, 456, 239), 'jp': (412, 195, 456, 239), 'tw': (412, 195, 456, 239)}, color={'cn': (76, 67, 66), 'en': (76, 67, 66), 'jp': (76, 67, 66), 'tw': (76, 67, 66)}, button={'cn': (412, 195, 456, 239), 'en': (412, 195, 456, 239), 'jp': (412, 195, 456, 239), 'tw': (412, 195, 456, 239)}, file={'cn': './assets/cn/equipment/FLEET_1_BACKLINE_1.png', 'en': './assets/en/equipment/FLEET_1_BACKLINE_1.png', 'jp': './assets/jp/equipment/FLEET_1_BACKLINE_1.png', 'tw': './assets/tw/equipment/FLEET_1_BACKLINE_1.png'}) +FLEET_1_BACKLINE_3 = Button(area={'cn': (616, 195, 659, 238), 'en': (616, 195, 659, 238), 'jp': (616, 195, 659, 238), 'tw': (616, 195, 659, 238)}, color={'cn': (62, 62, 67), 'en': (62, 62, 67), 'jp': (62, 62, 67), 'tw': (62, 62, 67)}, button={'cn': (616, 195, 659, 238), 'en': (616, 195, 659, 238), 'jp': (616, 195, 659, 238), 'tw': (616, 195, 659, 238)}, file={'cn': './assets/cn/equipment/FLEET_1_BACKLINE_3.png', 'en': './assets/en/equipment/FLEET_1_BACKLINE_3.png', 'jp': './assets/jp/equipment/FLEET_1_BACKLINE_3.png', 'tw': './assets/tw/equipment/FLEET_1_BACKLINE_3.png'}) +FLEET_1_VANGUARD_1 = Button(area={'cn': (728, 195, 770, 237), 'en': (728, 195, 770, 237), 'jp': (728, 195, 770, 237), 'tw': (728, 195, 770, 237)}, color={'cn': (54, 57, 63), 'en': (54, 57, 63), 'jp': (54, 57, 63), 'tw': (54, 57, 63)}, button={'cn': (728, 195, 770, 237), 'en': (728, 195, 770, 237), 'jp': (728, 195, 770, 237), 'tw': (728, 195, 770, 237)}, file={'cn': './assets/cn/equipment/FLEET_1_VANGUARD_1.png', 'en': './assets/en/equipment/FLEET_1_VANGUARD_1.png', 'jp': './assets/jp/equipment/FLEET_1_VANGUARD_1.png', 'tw': './assets/tw/equipment/FLEET_1_VANGUARD_1.png'}) +FLEET_1_VANGUARD_3 = Button(area={'cn': (932, 195, 974, 237), 'en': (932, 195, 974, 237), 'jp': (932, 195, 974, 237), 'tw': (932, 195, 974, 237)}, color={'cn': (53, 55, 62), 'en': (53, 55, 62), 'jp': (53, 55, 62), 'tw': (53, 55, 62)}, button={'cn': (932, 195, 974, 237), 'en': (932, 195, 974, 237), 'jp': (932, 195, 974, 237), 'tw': (932, 195, 974, 237)}, file={'cn': './assets/cn/equipment/FLEET_1_VANGUARD_3.png', 'en': './assets/en/equipment/FLEET_1_VANGUARD_3.png', 'jp': './assets/jp/equipment/FLEET_1_VANGUARD_3.png', 'tw': './assets/tw/equipment/FLEET_1_VANGUARD_3.png'}) +FLEET_2_BACKLINE_1 = Button(area={'cn': (412, 309, 455, 352), 'en': (412, 309, 455, 352), 'jp': (412, 309, 455, 352), 'tw': (412, 309, 455, 352)}, color={'cn': (73, 64, 63), 'en': (73, 64, 63), 'jp': (73, 64, 63), 'tw': (73, 64, 63)}, button={'cn': (412, 309, 455, 352), 'en': (412, 309, 455, 352), 'jp': (412, 309, 455, 352), 'tw': (412, 309, 455, 352)}, file={'cn': './assets/cn/equipment/FLEET_2_BACKLINE_1.png', 'en': './assets/en/equipment/FLEET_2_BACKLINE_1.png', 'jp': './assets/jp/equipment/FLEET_2_BACKLINE_1.png', 'tw': './assets/tw/equipment/FLEET_2_BACKLINE_1.png'}) +FLEET_2_BACKLINE_3 = Button(area={'cn': (616, 309, 659, 352), 'en': (616, 309, 659, 352), 'jp': (616, 309, 659, 352), 'tw': (616, 309, 659, 352)}, color={'cn': (51, 52, 57), 'en': (51, 52, 57), 'jp': (51, 52, 57), 'tw': (51, 52, 57)}, button={'cn': (616, 309, 659, 352), 'en': (616, 309, 659, 352), 'jp': (616, 309, 659, 352), 'tw': (616, 309, 659, 352)}, file={'cn': './assets/cn/equipment/FLEET_2_BACKLINE_3.png', 'en': './assets/en/equipment/FLEET_2_BACKLINE_3.png', 'jp': './assets/jp/equipment/FLEET_2_BACKLINE_3.png', 'tw': './assets/tw/equipment/FLEET_2_BACKLINE_3.png'}) +FLEET_2_VANGUARD_1 = Button(area={'cn': (729, 310, 770, 351), 'en': (729, 310, 770, 351), 'jp': (729, 310, 770, 351), 'tw': (729, 310, 770, 351)}, color={'cn': (52, 54, 61), 'en': (52, 54, 61), 'jp': (52, 54, 61), 'tw': (52, 54, 61)}, button={'cn': (729, 310, 770, 351), 'en': (729, 310, 770, 351), 'jp': (729, 310, 770, 351), 'tw': (729, 310, 770, 351)}, file={'cn': './assets/cn/equipment/FLEET_2_VANGUARD_1.png', 'en': './assets/en/equipment/FLEET_2_VANGUARD_1.png', 'jp': './assets/jp/equipment/FLEET_2_VANGUARD_1.png', 'tw': './assets/tw/equipment/FLEET_2_VANGUARD_1.png'}) +FLEET_2_VANGUARD_3 = Button(area={'cn': (932, 309, 974, 351), 'en': (932, 309, 974, 351), 'jp': (932, 309, 974, 351), 'tw': (932, 309, 974, 351)}, color={'cn': (51, 54, 62), 'en': (51, 54, 62), 'jp': (51, 54, 62), 'tw': (51, 54, 62)}, button={'cn': (932, 309, 974, 351), 'en': (932, 309, 974, 351), 'jp': (932, 309, 974, 351), 'tw': (932, 309, 974, 351)}, file={'cn': './assets/cn/equipment/FLEET_2_VANGUARD_3.png', 'en': './assets/en/equipment/FLEET_2_VANGUARD_3.png', 'jp': './assets/jp/equipment/FLEET_2_VANGUARD_3.png', 'tw': './assets/tw/equipment/FLEET_2_VANGUARD_3.png'}) FLEET_DETAIL = Button(area={'cn': (906, 644, 1008, 699), 'en': (906, 644, 1008, 699), 'jp': (906, 644, 1008, 699), 'tw': (906, 644, 1008, 699)}, color={'cn': (166, 170, 188), 'en': (166, 170, 188), 'jp': (166, 170, 188), 'tw': (166, 170, 188)}, button={'cn': (906, 644, 1008, 699), 'en': (906, 644, 1008, 699), 'jp': (906, 644, 1008, 699), 'tw': (906, 644, 1008, 699)}, file={'cn': './assets/cn/equipment/FLEET_DETAIL.png', 'en': './assets/en/equipment/FLEET_DETAIL.png', 'jp': './assets/jp/equipment/FLEET_DETAIL.png', 'tw': './assets/tw/equipment/FLEET_DETAIL.png'}) FLEET_DETAIL_CHECK = Button(area={'cn': (915, 647, 980, 679), 'en': (915, 649, 980, 677), 'jp': (915, 647, 979, 679), 'tw': (915, 647, 980, 680)}, color={'cn': (234, 195, 154), 'en': (236, 200, 160), 'jp': (234, 195, 154), 'tw': (237, 196, 154)}, button={'cn': (915, 647, 980, 679), 'en': (915, 649, 980, 677), 'jp': (915, 647, 979, 679), 'tw': (915, 647, 980, 680)}, file={'cn': './assets/cn/equipment/FLEET_DETAIL_CHECK.png', 'en': './assets/en/equipment/FLEET_DETAIL_CHECK.png', 'jp': './assets/jp/equipment/FLEET_DETAIL_CHECK.png', 'tw': './assets/tw/equipment/FLEET_DETAIL_CHECK.png'}) FLEET_DETAIL_ENTER = Button(area={'cn': (729, 314, 802, 438), 'en': (729, 314, 802, 438), 'jp': (729, 314, 802, 438), 'tw': (729, 314, 802, 438)}, color={'cn': (154, 149, 147), 'en': (154, 149, 147), 'jp': (154, 149, 147), 'tw': (154, 149, 147)}, button={'cn': (729, 314, 802, 438), 'en': (729, 314, 802, 438), 'jp': (729, 314, 802, 438), 'tw': (729, 314, 802, 438)}, file={'cn': './assets/cn/equipment/FLEET_DETAIL_ENTER.png', 'en': './assets/en/equipment/FLEET_DETAIL_ENTER.png', 'jp': './assets/jp/equipment/FLEET_DETAIL_ENTER.png', 'tw': './assets/tw/equipment/FLEET_DETAIL_ENTER.png'}) @@ -50,6 +58,8 @@ FLEET_ENTER_FLAGSHIP_HARD_1 = Button(area={'cn': (593, 173, 681, 261), 'en': (59 FLEET_ENTER_FLAGSHIP_HARD_2 = Button(area={'cn': (594, 287, 681, 374), 'en': (594, 287, 681, 374), 'jp': (594, 287, 681, 374), 'tw': (594, 287, 681, 374)}, color={'cn': (39, 45, 47), 'en': (39, 45, 47), 'jp': (39, 45, 47), 'tw': (39, 45, 47)}, button={'cn': (594, 287, 681, 374), 'en': (594, 287, 681, 374), 'jp': (594, 287, 681, 374), 'tw': (594, 287, 681, 374)}, file={'cn': './assets/cn/equipment/FLEET_ENTER_FLAGSHIP_HARD_2.png', 'en': './assets/cn/equipment/FLEET_ENTER_FLAGSHIP_HARD_2.png', 'jp': './assets/cn/equipment/FLEET_ENTER_FLAGSHIP_HARD_2.png', 'tw': './assets/cn/equipment/FLEET_ENTER_FLAGSHIP_HARD_2.png'}) FLEET_ENTER_HARD_1 = Button(area={'cn': (909, 173, 996, 260), 'en': (909, 173, 996, 260), 'jp': (909, 173, 996, 260), 'tw': (909, 173, 996, 260)}, color={'cn': (43, 47, 52), 'en': (43, 47, 52), 'jp': (43, 47, 52), 'tw': (43, 47, 52)}, button={'cn': (909, 173, 996, 260), 'en': (909, 173, 996, 260), 'jp': (909, 173, 996, 260), 'tw': (909, 173, 996, 260)}, file={'cn': './assets/cn/equipment/FLEET_ENTER_HARD_1.png', 'en': './assets/cn/equipment/FLEET_ENTER_HARD_1.png', 'jp': './assets/cn/equipment/FLEET_ENTER_HARD_1.png', 'tw': './assets/cn/equipment/FLEET_ENTER_HARD_1.png'}) FLEET_ENTER_HARD_2 = Button(area={'cn': (909, 287, 996, 374), 'en': (909, 287, 996, 374), 'jp': (909, 287, 996, 374), 'tw': (909, 287, 996, 374)}, color={'cn': (38, 44, 49), 'en': (38, 44, 49), 'jp': (38, 44, 49), 'tw': (38, 44, 49)}, button={'cn': (909, 287, 996, 374), 'en': (909, 287, 996, 374), 'jp': (909, 287, 996, 374), 'tw': (909, 287, 996, 374)}, file={'cn': './assets/cn/equipment/FLEET_ENTER_HARD_2.png', 'en': './assets/cn/equipment/FLEET_ENTER_HARD_2.png', 'jp': './assets/cn/equipment/FLEET_ENTER_HARD_2.png', 'tw': './assets/cn/equipment/FLEET_ENTER_HARD_2.png'}) +FLEET_ENTER = Button(area={'cn': (502, 474, 517, 489), 'en': (502, 474, 517, 489), 'jp': (502, 474, 517, 489), 'tw': (502, 474, 517, 489)}, color={'cn': (165, 193, 232), 'en': (165, 193, 232), 'jp': (165, 193, 232), 'tw': (165, 193, 232)}, button={'cn': (502, 474, 517, 489), 'en': (502, 474, 517, 489), 'jp': (502, 474, 517, 489), 'tw': (502, 474, 517, 489)}, file={'cn': './assets/cn/equipment/FLEET_ENTER.png', 'en': './assets/en/equipment/FLEET_ENTER.png', 'jp': './assets/jp/equipment/FLEET_ENTER.png', 'tw': './assets/tw/equipment/FLEET_ENTER.png'}) +FLEET_ENTER_FLAGSHIP = Button(area={'cn': (577, 277, 605, 291), 'en': (577, 277, 605, 291), 'jp': (577, 277, 605, 291), 'tw': (577, 277, 605, 291)}, color={'cn': (219, 196, 174), 'en': (219, 196, 174), 'jp': (219, 196, 174), 'tw': (219, 196, 174)}, button={'cn': (577, 277, 605, 291), 'en': (577, 277, 605, 291), 'jp': (577, 277, 605, 291), 'tw': (577, 277, 605, 291)}, file={'cn': './assets/cn/equipment/FLEET_ENTER_FLAGSHIP.png', 'en': './assets/en/equipment/FLEET_ENTER_FLAGSHIP.png', 'jp': './assets/jp/equipment/FLEET_ENTER_FLAGSHIP.png', 'tw': './assets/tw/equipment/FLEET_ENTER_FLAGSHIP.png'}) FLEET_NEXT = Button(area={'cn': (1234, 327, 1254, 356), 'en': (1234, 327, 1254, 356), 'jp': (1234, 327, 1254, 356), 'tw': (1234, 327, 1254, 356)}, color={'cn': (72, 93, 125), 'en': (72, 93, 125), 'jp': (72, 93, 125), 'tw': (72, 93, 125)}, button={'cn': (1234, 327, 1254, 356), 'en': (1234, 327, 1254, 356), 'jp': (1234, 327, 1254, 356), 'tw': (1234, 327, 1254, 356)}, file={'cn': './assets/cn/equipment/FLEET_NEXT.png', 'en': './assets/en/equipment/FLEET_NEXT.png', 'jp': './assets/jp/equipment/FLEET_NEXT.png', 'tw': './assets/tw/equipment/FLEET_NEXT.png'}) FLEET_PREV = Button(area={'cn': (26, 327, 46, 356), 'en': (26, 327, 46, 356), 'jp': (26, 327, 46, 356), 'tw': (26, 327, 46, 356)}, color={'cn': (72, 93, 125), 'en': (72, 93, 125), 'jp': (72, 93, 125), 'tw': (72, 93, 125)}, button={'cn': (26, 327, 46, 356), 'en': (26, 327, 46, 356), 'jp': (26, 327, 46, 356), 'tw': (26, 327, 46, 356)}, file={'cn': './assets/cn/equipment/FLEET_PREV.png', 'en': './assets/en/equipment/FLEET_PREV.png', 'jp': './assets/jp/equipment/FLEET_PREV.png', 'tw': './assets/tw/equipment/FLEET_PREV.png'}) OCR_FLEET_INDEX = Button(area={'cn': (957, 113, 987, 163), 'en': (957, 113, 987, 163), 'jp': (957, 113, 987, 163), 'tw': (957, 113, 987, 163)}, color={'cn': (36, 54, 86), 'en': (36, 54, 86), 'jp': (36, 54, 86), 'tw': (36, 54, 86)}, button={'cn': (957, 113, 987, 163), 'en': (957, 113, 987, 163), 'jp': (957, 113, 987, 163), 'tw': (957, 113, 987, 163)}, file={'cn': './assets/cn/equipment/OCR_FLEET_INDEX.png', 'en': './assets/en/equipment/OCR_FLEET_INDEX.png', 'jp': './assets/jp/equipment/OCR_FLEET_INDEX.png', 'tw': './assets/tw/equipment/OCR_FLEET_INDEX.png'}) diff --git a/module/equipment/equipment_code.py b/module/equipment/equipment_code.py index 24a4e8146..8cd6ea2ee 100644 --- a/module/equipment/equipment_code.py +++ b/module/equipment/equipment_code.py @@ -1,6 +1,6 @@ import yaml -from module.base.utils import random_rectangle_point, point2str +from module.base.timer import Timer from module.device.method.utils import HierarchyButton from module.equipment.assets import * from module.logger import logger @@ -9,6 +9,7 @@ from module.storage.assets import EQUIPMENT_FULL from module.storage.storage import StorageHandler EMPTY_CODE = "MC8wLzAvMC8wXDA=" +U2_CONTROL_METHODS = {'uiautomator2', 'minitouch', 'MaaTouch'} EQUIPMENT_PREVIEW = list([ EQUIPMENT_CODE_EQUIP_0, EQUIPMENT_CODE_EQUIP_1, @@ -21,6 +22,17 @@ EQUIPMENT_PREVIEW = list([ class EquipmentCodeHandler(StorageHandler): last_code: str = None + def equipment_code_supported(self): + method = self.config.Emulator_ControlMethod + if method in U2_CONTROL_METHODS: + return True + + logger.warning( + f"Equipment code requires uiautomator2 based control method, " + f"current control method is {method}, skip equipment change" + ) + return False + def get_code(self, name): try: config = {} @@ -61,14 +73,19 @@ class EquipmentCodeHandler(StorageHandler): if not self.appear(EMPTY_SHIP_R): break if TEMPLATE_BOGUE.match(self.device.image, scaling=1.46): # image has rotation + logger.info("Bogue detected") return 'bogue' elif TEMPLATE_HERMES.match(self.device.image, scaling=124 / 89): + logger.info("Hermes detected") return 'hermes' elif TEMPLATE_RANGER.match(self.device.image, scaling=4 / 3): + logger.info("Ranger detected") return 'ranger' elif TEMPLATE_LANGLEY.match(self.device.image, scaling=25 / 21): + logger.info("Langley detected") return 'langley' else: + logger.warning("Unknown ship detected, assuming DD") return 'DD' def _code_enter(self): @@ -81,7 +98,7 @@ class EquipmentCodeHandler(StorageHandler): if self.appear(EQUIPMENT_CODE_PAGE_CHECK, offset=(5, 5)): break - if self.appear_then_click(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5), interval=2): + if self.appear_then_click(EQUIPMENT_CODE_ENTRANCE, offset=(5, 5), interval=1): continue def _code_exit(self): @@ -108,7 +125,7 @@ class EquipmentCodeHandler(StorageHandler): if not self.is_code_preview_loaded(): return True - if self.appear_then_click(EQUIPMENT_CODE_CLEAR, offset=(5, 5)): + if self.appear_then_click(EQUIPMENT_CODE_CLEAR, offset=(5, 5), interval=1): continue else: return False @@ -124,9 +141,7 @@ class EquipmentCodeHandler(StorageHandler): def appear_then_click(xpath): b = HierarchyButton(h, xpath) if b: - point = random_rectangle_point(b.button) - logger.info(f'Click {point2str(*point)} @ {b}') - self.device.click_adb(*point) + self.device.click(b) return True else: return False @@ -144,18 +159,28 @@ class EquipmentCodeHandler(StorageHandler): self.device.adb_shell(['input', 'keyevent', '4']) + def set_fastinput_ime(self): + d = self.device.u2 + try: + d.set_fastinput_ime(True) + except Exception: + logger.warning("FastInputIME not enabled, trying to enable it") + self.fastinput_ime_enable() + def _code_input(self, code): logger.info(f"Code input: {code}") d = self.device.u2 - for _ in self.loop(timeout=10): + click_timer = Timer(1, count=3) + for _ in self.loop(): name, shown = d.current_ime() if shown: if name != 'com.github.uiautomator/.FastInputIME': - self.fastinput_ime_enable() + self.set_fastinput_ime() continue else: break - self.device.click(EQUIPMENT_CODE_TEXTBOX) + if click_timer.reached_and_reset(): + self.device.click(EQUIPMENT_CODE_TEXTBOX) else: logger.warning("Equipment code load failed") return False @@ -216,19 +241,25 @@ class EquipmentCodeHandler(StorageHandler): return code def code_clear(self, name=None): + if not self.equipment_code_supported(): + return False + self._code_enter() if name is None: name = self.current_ship() if self.get_code(name=name) is None: self.last_code = self._code_export() self.set_code(name=name, code=self.last_code) - self._code_apply(code=None) + return self._code_apply(code=None) def code_apply(self, name=None): + if not self.equipment_code_supported(): + return False + self._code_enter() if name is None: name = self.current_ship() code = self.get_code(name=name) if code is None: code = self.last_code - self._code_apply(code=code) + return self._code_apply(code=code) diff --git a/module/equipment/fleet_equipment.py b/module/equipment/fleet_equipment.py deleted file mode 100644 index 4f73c6536..000000000 --- a/module/equipment/fleet_equipment.py +++ /dev/null @@ -1,62 +0,0 @@ -from module.logger import logger -from module.base.timer import Timer -from module.equipment.assets import * -from module.equipment.equipment_change import EquipmentChange -from module.ocr.ocr import Digit -from module.ui.assets import FLEET_CHECK -from module.ui.page import page_fleet - -OCR_FLEET_INDEX = Digit(OCR_FLEET_INDEX, letter=(90, 154, 255), threshold=128, alphabet='123456') - - -class FleetEquipment(EquipmentChange): - def fleet_enter(self, fleet): - self.ui_ensure(page_fleet) - - # ui_ensure_index, set fleet - letter = OCR_FLEET_INDEX - next_button = FLEET_NEXT - prev_button = FLEET_PREV - interval = (0.2, 0.3) - - retry = Timer(1, count=2) - for _ in self.loop(): - current = letter.ocr(self.device.image) - logger.attr("Index", current) - - # ui_ensure_index but ignore default value 0 - # otherwise we would have 1 extra click switching from 1 to 4 - if current == 0: - continue - - diff = fleet - current - if diff == 0: - break - - if retry.reached(): - button = next_button if diff > 0 else prev_button - self.device.multi_click(button, n=abs(diff), interval=interval) - retry.reset() - - def fleet_equipment_take_on_preset(self, preset_record, enter=FLEET_DETAIL_ENTER_FLAGSHIP, - long_click=False, out=FLEET_DETAIL_CHECK): - self.ui_click(FLEET_DETAIL, appear_button=page_fleet.check_button, - check_button=FLEET_DETAIL_CHECK, skip_first_screenshot=True) - super().fleet_equipment_take_on_preset(preset_record=preset_record, enter=FLEET_DETAIL_ENTER_FLAGSHIP, - long_click=False, out=FLEET_DETAIL_CHECK) - self.ui_back(FLEET_CHECK) - - def fleet_equipment_take_off(self, enter=FLEET_DETAIL_ENTER_FLAGSHIP, long_click=False, out=FLEET_DETAIL_CHECK): - self.ui_click(FLEET_DETAIL, appear_button=page_fleet.check_button, - check_button=FLEET_DETAIL_CHECK, skip_first_screenshot=True) - super().fleet_equipment_take_off(enter=enter, long_click=long_click, out=out) - self.ui_back(FLEET_CHECK) - - def fleet_enter_ship(self, button): - self.ui_click(FLEET_DETAIL, appear_button=page_fleet.check_button, - check_button=FLEET_DETAIL_CHECK, skip_first_screenshot=True) - self.ship_info_enter(button, long_click=False) - - def fleet_back(self): - self.ui_back(FLEET_DETAIL_CHECK) - self.ui_back(FLEET_CHECK) diff --git a/module/exception.py b/module/exception.py index 5b08fe05d..c909369bd 100644 --- a/module/exception.py +++ b/module/exception.py @@ -69,3 +69,7 @@ class RequestHumanTakeover(Exception): # Request human takeover # Alas is unable to handle such error, probably because of wrong settings. pass + + +class HardNotSatisfied(RequestHumanTakeover): + pass diff --git a/module/exercise/combat.py b/module/exercise/combat.py index bdfbed9fa..0ee2c916f 100644 --- a/module/exercise/combat.py +++ b/module/exercise/combat.py @@ -1,12 +1,11 @@ from module.combat.combat import * from module.exercise.assets import * -from module.exercise.equipment import ExerciseEquipment from module.exercise.hp_daemon import HpDaemon from module.exercise.opponent import OPPONENT, OpponentChoose from module.ui.assets import EXERCISE_CHECK -class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): +class ExerciseCombat(HpDaemon, OpponentChoose, Combat): def _in_exercise(self): return self.appear(EXERCISE_CHECK, offset=(20, 20)) @@ -191,23 +190,3 @@ class ExerciseCombat(HpDaemon, OpponentChoose, ExerciseEquipment, Combat): self._preparation_quit() return False - - def equipment_take_off_when_finished(self): - if self.config.EXERCISE_FLEET_EQUIPMENT is None: - return False - if not self.equipment_has_take_on: - return False - - self._choose_opponent(0) - self.equipment_take_off() - self._preparation_quit() - - def equipment_take_on(self): - if self.config.EXERCISE_FLEET_EQUIPMENT is None: - return False - if self.equipment_has_take_on: - return False - - self._choose_opponent(0) - super().equipment_take_on() - self._preparation_quit() diff --git a/module/exercise/equipment.py b/module/exercise/equipment.py deleted file mode 100644 index 4d66b26e6..000000000 --- a/module/exercise/equipment.py +++ /dev/null @@ -1,43 +0,0 @@ -from module.base.timer import Timer -from module.combat.assets import BATTLE_PREPARATION -from module.equipment.equipment_change import EquipmentChange -from module.exercise.assets import * - - -class ExerciseEquipment(EquipmentChange): - def _active_edit(self): - timer = Timer(5) - while 1: - self.device.screenshot() - - if timer.reached() and self.appear_then_click(EQUIP_EDIT_INACTIVE): - timer.reset() - - # End - if self.appear(EQUIP_EDIT_ACTIVE): - self.device.sleep((0.2, 0.3)) - break - - def _inactive_edit(self): - timer = Timer(5) - while 1: - self.device.screenshot() - - if timer.reached() and self.appear_then_click(EQUIP_EDIT_ACTIVE): - timer.reset() - - # End - if self.appear(EQUIP_EDIT_INACTIVE): - self.device.sleep((0.2, 0.3)) - break - - def equipment_take_on(self): - self._active_edit() - self.fleet_equipment_take_on_preset(preset_record=self.config.EXERCISE_FLEET_EQUIPMENT, enter=EQUIP_ENTER, - long_click=True, out=BATTLE_PREPARATION) - self._inactive_edit() - - def equipment_take_off(self): - self._active_edit() - self.fleet_equipment_take_off(enter=EQUIP_ENTER, long_click=True, out=BATTLE_PREPARATION) - self._inactive_edit() diff --git a/module/hard/equipment.py b/module/hard/equipment.py deleted file mode 100644 index 59fbc7d81..000000000 --- a/module/hard/equipment.py +++ /dev/null @@ -1,27 +0,0 @@ -from module.equipment.equipment_change import EquipmentChange -from module.hard.assets import * -from module.map.assets import * - - -class HardEquipment(EquipmentChange): - - def equipment_take_on(self): - if self.config.FLEET_HARD_EQUIPMENT is None: - return False - if self.equipment_has_take_on: - return False - - enter = EQUIP_ENTER_1 if self.config.Hard_HardFleet == 1 else EQUIP_ENTER_2 - self.fleet_equipment_take_on_preset(preset_record=self.config.FLEET_HARD_EQUIPMENT, enter=enter, - long_click=True, out=FLEET_PREPARATION) - return True - - def equipment_take_off(self): - if self.config.FLEET_HARD_EQUIPMENT is None: - return False - if not self.equipment_has_take_on: - return False - - enter = EQUIP_ENTER_1 if self.config.Hard_HardFleet == 1 else EQUIP_ENTER_2 - self.fleet_equipment_take_off(enter=enter, long_click=True, out=FLEET_PREPARATION) - return True diff --git a/module/map/map_fleet_preparation.py b/module/map/map_fleet_preparation.py index 34be9b507..0b80a73e9 100644 --- a/module/map/map_fleet_preparation.py +++ b/module/map/map_fleet_preparation.py @@ -4,7 +4,7 @@ from scipy import signal from module.base.button import Button from module.base.timer import Timer from module.base.utils import * -from module.exception import RequestHumanTakeover +from module.exception import HardNotSatisfied from module.handler.assets import AUTO_SEARCH_SET_MOB, AUTO_SEARCH_SET_BOSS, \ AUTO_SEARCH_SET_ALL, AUTO_SEARCH_SET_STANDBY, \ AUTO_SEARCH_SET_SUB_AUTO, AUTO_SEARCH_SET_SUB_STANDBY @@ -122,13 +122,12 @@ class FleetOperator: # logger.attr('Light_orange_line', lines) return lines > 0 - # Remove this function, centralized validation and unified error raising - # def raise_hard_not_satisfied(self): - # if self.is_hard_satisfied() is False: - # stage = self.main.config.Campaign_Name - # logger.critical(f'Stage "{stage}" is a hard mode, ' - # f'please prepare your fleet "{str(self)}" in game before running Alas') - # raise RequestHumanTakeover('Hard not satisfied', str(self)) + def raise_hard_not_satisfied(self): + if self.is_hard_satisfied() is False: + stage = self.main.config.Campaign_Name + logger.critical(f'Stage "{stage}" is a hard mode, ' + f'please prepare your fleet "{str(self)}" in game before running Alas') + raise HardNotSatisfied def clear(self, skip_first_screenshot=True): """ @@ -347,11 +346,10 @@ class FleetPreparation(InfoHandler): h1, h2, h3 = fleet_1.is_hard_satisfied(), fleet_2.is_hard_satisfied(), submarine.is_hard_satisfied() logger.info(f'Hard satisfied: Fleet_1: {h1}, Fleet_2: {h2}, Submarine: {h3}') if self.config.SERVER in ['cn', 'en', 'jp']: - unsatisfied = [] - if self.config.Fleet_Fleet1 and h1 is False: - unsatisfied.append(str(fleet_1)) - if self.config.Fleet_Fleet2 and h2 is False: - unsatisfied.append(str(fleet_2)) + if self.config.Fleet_Fleet1: + fleet_1.raise_hard_not_satisfied() + if self.config.Fleet_Fleet2: + fleet_2.raise_hard_not_satisfied() if self.config.Submarine_Fleet and h3 is False: auto_recommend = self.config.Submarine_AutoRecommend logger.attr('Submarine AutoRecommend', auto_recommend) @@ -361,13 +359,7 @@ class FleetPreparation(InfoHandler): self.device.screenshot() h3 = submarine.is_hard_satisfied() logger.info(f'Hard satisfied: Fleet_1: {h1}, Fleet_2: {h2}, Submarine: {h3}') - if h3 is False: - unsatisfied.append(str(submarine)) - if unsatisfied: - stage = self.config.Campaign_Name - logger.critical(f'Stage "{stage}" is a hard mode, ' - f'please prepare your fleet(s): {", ".join(unsatisfied)} in game before running Alas') - raise RequestHumanTakeover('Hard not satisfied', *unsatisfied) + submarine.raise_hard_not_satisfied() # Skip fleet preparation in hard mode self.map_is_hard_mode = h1 or h2 or h3 diff --git a/module/retire/assets.py b/module/retire/assets.py index 241859e92..4b226ccce 100644 --- a/module/retire/assets.py +++ b/module/retire/assets.py @@ -15,6 +15,7 @@ DOCK_FIRST_NPC = Button(area={'cn': (96, 111, 123, 123), 'en': (96, 111, 123, 12 DOCK_SCROLL = Button(area={'cn': (1239, 76, 1248, 641), 'en': (1239, 76, 1248, 641), 'jp': (1237, 78, 1250, 628), 'tw': (1239, 76, 1248, 641)}, color={'cn': (47, 46, 37), 'en': (47, 46, 37), 'jp': (180, 156, 66), 'tw': (47, 46, 37)}, button={'cn': (1239, 76, 1248, 641), 'en': (1239, 76, 1248, 641), 'jp': (1237, 78, 1250, 628), 'tw': (1239, 76, 1248, 641)}, file={'cn': './assets/cn/retire/DOCK_SCROLL.png', 'en': './assets/en/retire/DOCK_SCROLL.png', 'jp': './assets/jp/retire/DOCK_SCROLL.png', 'tw': './assets/tw/retire/DOCK_SCROLL.png'}) DOCK_SELECTED = Button(area={'cn': (582, 662, 647, 685), 'en': (597, 658, 655, 691), 'jp': (603, 662, 655, 685), 'tw': (582, 662, 647, 685)}, color={'cn': (75, 75, 83), 'en': (64, 62, 73), 'jp': (84, 83, 92), 'tw': (75, 75, 83)}, button={'cn': (582, 662, 647, 685), 'en': (597, 658, 655, 691), 'jp': (603, 662, 655, 685), 'tw': (582, 662, 647, 685)}, file={'cn': './assets/cn/retire/DOCK_SELECTED.png', 'en': './assets/en/retire/DOCK_SELECTED.png', 'jp': './assets/jp/retire/DOCK_SELECTED.png', 'tw': './assets/tw/retire/DOCK_SELECTED.png'}) DOCK_SHIP_DOWN = Button(area={'cn': (164, 152, 195, 204), 'en': (164, 152, 195, 204), 'jp': (164, 152, 195, 204), 'tw': (164, 152, 195, 204)}, color={'cn': (106, 107, 108), 'en': (106, 107, 108), 'jp': (106, 107, 108), 'tw': (106, 107, 108)}, button={'cn': (90, 74, 223, 269), 'en': (90, 74, 223, 269), 'jp': (90, 74, 223, 269), 'tw': (90, 74, 223, 269)}, file={'cn': './assets/cn/retire/DOCK_SHIP_DOWN.png', 'en': './assets/cn/retire/DOCK_SHIP_DOWN.png', 'jp': './assets/cn/retire/DOCK_SHIP_DOWN.png', 'tw': './assets/cn/retire/DOCK_SHIP_DOWN.png'}) +DOCK_UNMOUNT = Button(area={'cn': (161, 141, 225, 216), 'en': (161, 141, 225, 216), 'jp': (161, 141, 225, 216), 'tw': (161, 141, 225, 216)}, color={'cn': (111, 111, 112), 'en': (111, 111, 112), 'jp': (111, 111, 112), 'tw': (111, 111, 112)}, button={'cn': (161, 141, 225, 216), 'en': (161, 141, 225, 216), 'jp': (161, 141, 225, 216), 'tw': (161, 141, 225, 216)}, file={'cn': './assets/cn/retire/DOCK_UNMOUNT.png', 'en': './assets/en/retire/DOCK_UNMOUNT.png', 'jp': './assets/jp/retire/DOCK_UNMOUNT.png', 'tw': './assets/tw/retire/DOCK_UNMOUNT.png'}) EMPTY_ENHANCE_SLOT_PLUS = Button(area={'cn': (737, 402, 773, 437), 'en': (747, 402, 782, 437), 'jp': (737, 402, 773, 437), 'tw': (747, 401, 782, 437)}, color={'cn': (46, 46, 46), 'en': (38, 38, 38), 'jp': (46, 46, 46), 'tw': (43, 43, 43)}, button={'cn': (737, 402, 773, 437), 'en': (747, 402, 782, 437), 'jp': (737, 402, 773, 437), 'tw': (747, 401, 782, 437)}, file={'cn': './assets/cn/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'en': './assets/en/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'jp': './assets/jp/retire/EMPTY_ENHANCE_SLOT_PLUS.png', 'tw': './assets/tw/retire/EMPTY_ENHANCE_SLOT_PLUS.png'}) ENHANCE_CONFIRM = Button(area={'cn': (1126, 602, 1256, 645), 'en': (1226, 605, 1262, 641), 'jp': (1126, 601, 1257, 646), 'tw': (1215, 606, 1253, 641)}, color={'cn': (203, 149, 81), 'en': (212, 167, 100), 'jp': (189, 139, 78), 'tw': (216, 169, 99)}, button={'cn': (1126, 602, 1256, 645), 'en': (1226, 605, 1262, 641), 'jp': (1126, 601, 1257, 646), 'tw': (1215, 606, 1253, 641)}, file={'cn': './assets/cn/retire/ENHANCE_CONFIRM.png', 'en': './assets/en/retire/ENHANCE_CONFIRM.png', 'jp': './assets/jp/retire/ENHANCE_CONFIRM.png', 'tw': './assets/tw/retire/ENHANCE_CONFIRM.png'}) ENHANCE_FILLED = Button(area={'cn': (728, 440, 781, 454), 'en': (728, 440, 781, 454), 'jp': (722, 387, 789, 400), 'tw': (728, 440, 781, 454)}, color={'cn': (156, 138, 127), 'en': (156, 138, 127), 'jp': (146, 153, 211), 'tw': (156, 138, 127)}, button={'cn': (728, 440, 781, 454), 'en': (728, 440, 781, 454), 'jp': (722, 387, 789, 400), 'tw': (728, 440, 781, 454)}, file={'cn': './assets/cn/retire/ENHANCE_FILLED.png', 'en': './assets/en/retire/ENHANCE_FILLED.png', 'jp': './assets/jp/retire/ENHANCE_FILLED.png', 'tw': './assets/tw/retire/ENHANCE_FILLED.png'}) diff --git a/module/retire/retirement.py b/module/retire/retirement.py index 7ff328638..5f387ebb5 100644 --- a/module/retire/retirement.py +++ b/module/retire/retirement.py @@ -582,9 +582,9 @@ class Retirement(Enhancement, QuickRetireSettingHandler): while 1: filter_obj.load(string) - common_cv = list(dict.fromkeys( + common_ship = list(dict.fromkeys( [str(name[0]) for name in filter_obj.filter if name[0].upper() in templates])) - if not common_cv: + if not common_ship: logger.warning(f'Invalid filter set: "{string}". Set to default filter.') string = default self.config.cross_set(keys=key, value=default) @@ -592,8 +592,8 @@ class Retirement(Enhancement, QuickRetireSettingHandler): # End if output: - logger.attr('Filter sort', ' > '.join(common_cv)) - return common_cv + logger.attr('Filter sort', ' > '.join(common_ship)) + return common_ship def retirement_get_common_rarity_cv_in_page(self): """