Beispiel #1
0
    def switch_fleet(self, context):
        preset_id = self._get_next_preset_id(context)
        Log.log_msg(f"Switching to Fleet Preset {preset_id}.")
        if preset_id not in self.presets:
            Log.log_error(
                f"Fleet Preset {preset_id} is not specified in-game. Please "
                f"check your config.")
            exit(1)

        list_idx = (preset_id if preset_id < 5 else 5) - 1
        idx_offset = preset_id - 5
        if idx_offset > 0:
            kca_u.kca.sleep()
            self._scroll_preset_list(idx_offset)

        kca_u.kca.r['top'].hover()
        kca_u.kca.sleep()
        preset_idx_region = Region(kca_u.kca.game_x + 410,
                                   kca_u.kca.game_y + 275 + (list_idx * 76),
                                   70, 45)
        kca_u.kca.click_existing(preset_idx_region,
                                 'fleetswitcher|fleetswitch_button.png')
        if kca_u.kca.exists('left',
                            'fleetswitcher|fleetswitch_fail_check.png'):
            Log.log_error(
                f"Could not switch in fleet preset {preset_id}. Please check "
                f"your config and fleet presets.")
            exit(1)
        Log.log_msg(f"Fleet Preset {preset_id} loaded.")

        if context == 'combat':
            self._set_next_combat_preset()
Beispiel #2
0
    def _change_page(region, target, offset):
        """Method that clicks on the arrow and page number navigation at the
        bottom of the ship list. 'first', 'prev', 'next', 'last' targets will
        click their respective arrow buttons, while an int target between 1 and
        5 (inclusive) will click the page number at that position at the bottom
        of the page (left to right).

        Args:
            regions (dict): dict of regions
            target (str, int): specifies which navigation button to press
            offset (tuple): tuple of x, y pixel offsets as defined by
                offset_mode and the OFFSET class dictionary
        """
        Log.log_debug(f"Changing to page {target} with {offset} offsets.")
        if target == 'first':
            kca_u.kca.click_existing(
                region, 'global|page_first.png', pad=PAGE_NAV)
        elif target == 'prev':
            kca_u.kca.click_existing(
                region, 'global|page_prev.png', pad=PAGE_NAV)
        elif target == 'next':
            kca_u.kca.click_existing(
                region, 'global|page_next.png', pad=PAGE_NAV)
        elif target == 'last':
            kca_u.kca.click_existing(
                region, 'global|page_last.png', pad=PAGE_NAV)
        elif 1 <= target <= 5:
            zero_target = target - 1
            x_start = kca_u.kca.game_x + 735 + (zero_target * 53) + offset[0]
            y_start = kca_u.kca.game_y + 675 + offset[1]

            Region(x_start, y_start, 16, 15).click()
        kca_u.kca.sleep(0.5)
Beispiel #3
0
    def _conduct_pvp(self, index):
        pvp_list_region = Region(kca_u.kca.game_x + 280,
                                 kca_u.kca.game_y + 268 + (index * 82), 795,
                                 64)
        kca_u.kca.click(pvp_list_region)
        api_result = api.api.update_from_api({KCSAPIEnum.PVP_ENEMY_INFO})
        formation, nb = self._get_formation_and_nb(
            api_result[KCSAPIEnum.PVP_ENEMY_INFO.name][0])
        kca_u.kca.r['top'].hover()
        kca_u.kca.wait_and_click('lower', 'pvp|pvp_start_1.png')
        kca_u.kca.sleep()
        kca_u.kca.wait_and_click('lower', 'pvp|pvp_start_2.png')
        kca_u.kca.sleep()
        sts.stats.pvp.pvp_done += 1

        kca_u.kca.wait_and_click(f'formation_{formation.value}',
                                 f'fleet|formation_{formation.value}.png')
        kca_u.kca.r['top'].hover()

        while not kca_u.kca.exists('lower_right_corner', 'global|next.png'):
            if nb:
                kca_u.kca.click_existing('kc', 'global|combat_nb_fight.png')
            else:
                kca_u.kca.click_existing('kc', 'global|combat_nb_retreat.png')
            kca_u.kca.sleep(2)

        while not kca_u.kca.exists('home_menu', 'nav|home_menu_sortie.png'):
            kca_u.kca.r['shipgirl'].click()
            kca_u.kca.sleep(1)

        Log.log_debug("PvP complete.")
        api.api.update_from_api({KCSAPIEnum.PORT})
Beispiel #4
0
    def find_all(asset, similarity):
        region = Region()

        Log.log_warn(f"Searching for {asset} with similarity {similarity}.")
        Log.log_warn("Results:")
        results = region.find_all(asset, similarity)
        for result in results:
            print(result)
Beispiel #5
0
 def _select_ship(self, idx, ship):
     page = (idx // 10) + 1 if idx > 9 else 1
     Log.log_msg(f"Selecting lvl{ship.level} {ship.name} (pg{page}#{idx}).")
     if page > 1:
         tot_pages = shp.ships.current_ship_count // 10
         list_control_region = Region(kca_u.kca.game_x + 610,
                                      kca_u.kca.game_y + 660, 490, 45)
         nav.navigate_list.to_page(list_control_region, tot_pages,
                                   self.current_repair_list_page, page,
                                   'repair')
         self.current_repair_list_page = page
     repair_list_region = Region(kca_u.kca.game_x + 596,
                                 kca_u.kca.game_y + 194 + (idx % 10 * 46),
                                 500, 31)
     kca_u.kca.click(repair_list_region)
     kca_u.kca.r['top'].hover()
     kca_u.kca.wait('right', 'repair|repair_confirm_1.png')
Beispiel #6
0
 def _check_repair_sort(self):
     if not kca_u.kca.exists('upper_right', 'repair|repairlist_icon.png'):
         Log.log_msg("Changing repair list sort.")
         sort_button = Region(kca_u.kca.game_x + 1125,
                              kca_u.kca.game_y + 155, 58, 26)
         while not kca_u.kca.exists('upper_right',
                                    'repair|repairlist_icon.png'):
             sort_button.click()
Beispiel #7
0
 def _click_quest_idx(self, idx):
     Log.log_debug(f"Clicking quest at position {idx}.")
     quest_list_region = Region(kca_u.kca.game_x + 230,
                                kca_u.kca.game_y + 173 + (idx * 102), 830,
                                30)
     quest_list_region.click()
     api.api.update_from_api(
         {KCSAPIEnum.QUEST_LIST, KCSAPIEnum.QUEST_TURN_IN}, need_all=False)
     kca_u.kca.sleep(1)
Beispiel #8
0
 def _select_switch_button(self, slot_id):
     zero_idx = slot_id - 1
     slot_button_region = Region(
         kca_u.kca.game_x + 550 + ((zero_idx % 2) * 513),
         kca_u.kca.game_y + 295 + ((zero_idx // 2) * 168), 125, 55)
     kca_u.kca.click_existing(slot_button_region,
                              'shipswitcher|shiplist_button.png')
     kca_u.kca.wait_vanish(slot_button_region,
                           'shipswitcher|shiplist_button.png')
     kca_u.kca.r['top'].hover()
Beispiel #9
0
 def _select_replacement_ship(self, ship_idx, ship):
     target_page = (ship_idx // 10) + 1 if ship_idx > 9 else 1
     Log.log_msg(f"Selecting lvl{ship.level} {ship.name} "
                 f"(pg{target_page}#{ship_idx}).")
     if target_page > 1:
         tot_pages = shp.ships.current_ship_count // 10
         list_control_region = Region(kca_u.kca.game_x + 625,
                                      kca_u.kca.game_y + 655, 495, 45)
         kca_u.kca.sleep(0.5)
         nav.navigate_list.to_page(list_control_region, tot_pages,
                                   self.current_shipcomp_page, target_page,
                                   'shipcomp')
         self.current_shipcomp_page = target_page
     shipcomp_list_region = Region(
         kca_u.kca.game_x + 590,
         kca_u.kca.game_y + 225 + (ship_idx % 10 * 43), 435, 34)
     kca_u.kca.click(shipcomp_list_region)
     kca_u.kca.r['top'].hover()
     kca_u.kca.wait('lower_right',
                    'shipswitcher|shiplist_shipswitch_button.png')
Beispiel #10
0
    def recovery_from_catbomb(cls, screen=Region(), catbomb_201=False):
        """Method that contains steps for recovery attempt from catbombs. If
        the catbomb_201 flag is set to True the recovery is attempt is far less
        aggressive to not aggravate the fairies any further. Includes
        incremental fallback for retry attempts.

        Args:
            screen (Region, optional): screen region. Defaults to Region().
            catbomb_201 (bool, optional): whether or not this is a 201 catbomb.
                Defaults to False.

        Returns:
            bool: True if recovery was successful; False otherwise.
        """
        catbomb_count = 0 if not catbomb_201 else 2
        if catbomb_201:
            if sts.stats.recovery.catbomb_201_encountered > 0:
                Log.log_error(
                    "Multiple 201 catbombs encountered. Shutting down kcauto.")
                return False
            else:
                kca_u.kca.sleep(300)

        while catbomb_count < 3:
            cls._refresh_screen(screen)
            if kca_u.kca.start_kancolle():
                Log.log_success("Catbomb Recovery successful.")
                kca_u.kca.hook_chrome(port=cfg.config.general.chrome_dev_port)
                sts.stats.recovery.recoveries_done += 1
                if catbomb_201:
                    sts.stats.recovery.catbomb_201_encountered += 1
                    sts.stats.recovery.catbomb_201_recoveries_done += 1
                else:
                    sts.stats.recovery.catbomb_recoveries_done += 1
                return True
            elif kca_u.kca.exists(screen, 'global|catbomb.png'):
                if catbomb_201:
                    Log.log_error(
                        "Persistent 201 catbomb. Shutting down kcauto.")
                    return False

                catbomb_count += 1
                # incremental backoff; 16, 64, then 256 seconds
                sleep_len = pow(4, catbomb_count + 1)
                Log.log_warn(
                    f"Catbomb Recovery attempt {catbomb_count}. Sleeping for "
                    f"{sleep_len} seconds before next recovery attempt.")
                sleep(sleep_len)
            else:
                return False
        return False
Beispiel #11
0
    def attempt_recovery(cls):
        """Primary method that runs through all the various recovery options.
        Runs through basic recovery, result screen recovery, catbomb recovery,
        then Chrome tab crash recoveries. Typically run when there has been a
        generic Exception caused.

        Returns:
            bool: True if recovery was successful; False otherwise.
        """
        Log.log_warn("Attempting recovery.")

        screen = Region()

        if cls.basic_recovery():
            Log.log_success("Basic Recovery successful.")
            sts.stats.recovery.recoveries_done += 1
            sts.stats.recovery.basic_recoveries_done += 1
            return True

        if (
                kca_u.kca.exists(screen, 'global|next.png')
                or kca_u.kca.exists(screen, 'global|next_alt.png')):
            Log.log_warn("Results screen detected.")
            if cls.recovery_from_results(screen):
                Log.log_success("Results Recovery successful.")
                sts.stats.recovery.recoveries_done += 1
                sts.stats.recovery.results_recoveries_done += 1
                return True
            return False

        if kca_u.kca.exists(screen, 'global|catbomb.png'):
            Log.log_warn("Catbomb detected.")
            if cls.recovery_from_catbomb(screen=screen):
                return True
            else:
                Log.log_error("Catbomb Recovery failed.")
            return False

        if kca_u.kca.exists(screen, 'global|chrome_crash.png'):
            Log.log_warn("Chrome Crash (Type 1) detected.")
            if cls.recovery_from_chrome_crash(screen, crash_type=1):
                return True

        visual_events = kca_u.kca.visual_hook.pop_messages()
        for event in visual_events:
            if event['method'] == 'Inspector.targetCrashed':
                Log.log_warn("Chrome Crash (Type 2) detected.")
                if cls.recovery_from_chrome_crash(screen, crash_type=2):
                    return True
Beispiel #12
0
    def _create_or_shift_region(self, key, x, y, w, h):
        """Helper method for generating or shifting an existing Region's x
        and y position.

        Args:
            key (str): region key.
            x (int): x position of upper-left corner of Region.
            y (int): y position of upper-left corner of Region.
            w (int): width of Region.
            h (int): height of Region.
        """
        if key not in self.r or not isinstance(self.r[key], Region):
            self.r[key] = Region(x, y, w, h)
        else:
            self.r[key].shift_region(x, y)
Beispiel #13
0
    def start_kancolle(self):
        """Method that attempts to start Kancolle from the game's splash
        screen. If starting from the splash screen, kcauto will load the data
        from the get_data api call. Otherwise, it will load the stored data
        from previous startups.
        """
        screen = Region()
        if self.click_existing(screen, 'global|game_start.png'):
            Log.log_msg("Starting kancolle from splash screen.")
            api.api.update_from_api({
                KCSAPIEnum.GET_DATA, KCSAPIEnum.REQUIRE_INFO, KCSAPIEnum.PORT})
            self.wait(screen, 'nav|home_menu_sortie.png', 60)
            Log.log_success("Kancolle successfully started.")
            shp.ships.load_wctf_names(force_update=True)
        else:
            api.api.update_ship_library_from_json()
        self.sleep()

        return True
Beispiel #14
0
    def recovery_from_chrome_crash(cls, screen=Region(), crash_type=1):
        """Method that contains steps for recovery from Chrome tab crashes.

        Args:
            screen (Region, optional): screen region. Defaults to Region().
            crash_type (int, optional): type of Chrome tab crash encountered.
                Defaults to 1.

        Returns:
            bool: True if recovery was successful; False otherwise.
        """
        cls._refresh_screen(screen)
        if kca_u.kca.start_kancolle():
            Log.log_success("Chrome Crash Recovery successful.")
            sts.stats.recovery.recoveries_done += 1
            if crash_type == 1:
                sts.stats.recovery.chrome_crash_t1_recoveries_done += 1
            elif crash_type == 2:
                sts.stats.recovery.chrome_crash_t2_recoveries_done += 1
            return True
        Log.log_error("Chrome Crash Recovery failed.")
        return False
Beispiel #15
0
    def _select_expedition(self, expedition):
        kca_u.kca.sleep(0.1)
        expedition_list = self.available_expeditions_per_world[
            expedition.world]
        index = expedition_list.index(expedition)
        offset = 0
        if index >= self.NUM_VISIBLE_EXPEDITONS:
            if kca_u.kca.exists('lower_left', 'global|scroll_next.png'):
                self._scroll_list_down()
            offset = len(expedition_list) - self.NUM_VISIBLE_EXPEDITONS
        else:
            if kca_u.kca.exists('upper_left', 'global|scroll_prev.png'):
                self._scroll_list_up()

        true_index = index - offset
        if not 0 <= true_index < self.NUM_VISIBLE_EXPEDITONS:
            raise ValueError(f"Bad index {true_index}")
        expedition_list_region = Region(
            kca_u.kca.game_x + 190, kca_u.kca.game_y + 244 + (true_index * 45),
            520, 35)
        kca_u.kca.click(expedition_list_region)
        kca_u.kca.r['top'].hover()
        kca_u.kca.sleep(0.5)
Beispiel #16
0
    def find_kancolle(self):
        """Method that finds the Kancolle game on-screen and determine the UI
        being used as well as the position of the game. On first startup the
        method will look for all UIs until one is found; on subsequent runs
        it will first look for the last found UI. Generates or modifies
        pre-defined regions accordingly.

        Raises:
            FindFailed: could not find the game on-screen.
        """
        Log.log_msg("Finding kancolle.")
        ref_r = None
        attempt = 0
        screen = Region()

        # look for last-seen UI, if set
        if self.last_ui:
            try:
                ref_r = self.find(screen,
                                  f'global|kc_ref_point_{self.last_ui}.png',
                                  EXACT)
            except FindFailed:
                self.last_ui = None
                Log.log_debug("Last known UI not found.")

        # if last-seen UI was not found, or if kcauto is in first start
        while not ref_r:
            try:
                ref_r = self.find(screen, 'global|kc_ref_point_1.png', EXACT)
                self.last_ui = 1
                Log.log_debug("Using UI 1 or 2")
                break
            except FindFailed:
                Log.log_debug("Not using UI 1 or 2")
            try:
                ref_r = self.find(screen, 'global|kc_ref_point_2.png', EXACT)
                self.last_ui = 2
                Log.log_debug("Using UI 3")
                break
            except FindFailed:
                Log.log_debug("Not using UI 3")
            try:
                ref_r = self.find(screen, 'global|kc_ref_point_3.png', EXACT)
                self.last_ui = 3
                Log.log_debug("Using UI 4 or 5")
                break
            except FindFailed:
                Log.log_debug("Not using UI 4 or 5")
            attempt += 1
            sleep(1)
            if attempt > 3:
                Log.log_error("Could not find Kancolle reference point.")
                raise FindFailed()

        new_game_x = ref_r.x - 144
        new_game_y = ref_r.y
        Log.log_debug(f"Game X:{new_game_x}, Y:{new_game_y}")

        # define click callback as needed
        if not arg.args.parsed_args.no_click_track:
            ImageMatch.click_callback = clt.click_tracker.track_click

        # define click and hover method overrides as needed
        if (cfg.config.general.interaction_mode is
                InteractionModeEnum.CHROME_DRIVER):
            ImageMatch.override_click_method = self._override_click_method
            ImageMatch.override_hover_method = self._override_hover_method

        if new_game_x != self.game_x or new_game_y != self.game_y:
            if not self.game_x or self.game_y:
                Log.log_success("Game found. Initializing regions.")
            else:
                Log.log_msg("Game has moved. Shifting regions.")
            self.game_x = new_game_x
            self.game_y = new_game_y
            self._update_regions()

        return True
Beispiel #17
0
 def select(self):
     kca_u.kca.click(
         Region(kca_u.kca.game_x + self.x - 3,
                kca_u.kca.game_y + self.y - 3, 7, 7))