def test_twitter_functionality(self):
        Settings.farming_mode = "Raid"
        Settings.mission_name = "Lvl 120 Avatar"

        TwitterRoomFinder.connect()

        Game.wait(5)

        tries = 10
        room_codes = []
        while tries > 0:
            code = TwitterRoomFinder.get_room_code()
            if code != "":
                room_codes.append(code)
                if len(room_codes) >= 1:
                    break

            tries -= 1
            Game.wait(1)

        TwitterRoomFinder.disconnect()
        print(f"\nFound room codes: {room_codes}")
        self.assertGreaterEqual(len(room_codes), 1)
        self._reset_settings()
        return None
    def _navigate():
        """Navigates to the specified Proving Grounds mission.

        Returns:
            None
        """
        from bot.game import Game

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        MessageLog.print_message(
            f"\n[PROVING.GROUNDS] Now navigating to Proving Grounds...")

        # Go to the Event by clicking on the "Menu" button and then click the very first banner.
        Game.find_and_click_button("home_menu")
        banner_locations = ImageUtils.find_all("event_banner",
                                               custom_confidence=0.7)
        if len(banner_locations) == 0:
            banner_locations = ImageUtils.find_all("event_banner_blue",
                                                   custom_confidence=0.7)
            if len(banner_locations) == 0:
                raise ProvingGroundsException(
                    "Failed to find the Event banner.")
        MouseUtils.move_and_click_point(banner_locations[0][0],
                                        banner_locations[0][1], "event_banner")

        Game.wait(1)

        difficulty = ""
        if Settings.mission_name == "Extreme":
            difficulty = "Extreme"
        elif Settings.mission_name == "Extreme+":
            difficulty = "Extreme+"

        # Select the difficulty.
        if ImageUtils.confirm_location("proving_grounds"):
            if Game.find_and_click_button("proving_grounds_missions"):
                difficulty_button_locations = ImageUtils.find_all(
                    "play_round_button")

                if difficulty == "Extreme":
                    MouseUtils.move_and_click_point(
                        difficulty_button_locations[1][0],
                        difficulty_button_locations[1][1], "play_round_button")
                elif difficulty == "Extreme+":
                    MouseUtils.move_and_click_point(
                        difficulty_button_locations[2][0],
                        difficulty_button_locations[2][1], "play_round_button")

                # After the difficulty has been selected, click "Play" to land the bot at the Proving Grounds' Summon Selection screen.
                Game.find_and_click_button("play")
        else:
            raise ProvingGroundsException(
                "Failed to arrive at the main screen for Proving Grounds.")

        return None
    def move_and_click_point(x: int,
                             y: int,
                             image_name: str,
                             custom_mouse_speed: float = 0.0,
                             mouse_clicks: int = 1):
        """Move the cursor to the specified point on the screen and clicks it.

        Args:
            x (int): X coordinate on the screen.
            y (int): Y coordinate on the screen.
            image_name (str): File name of the image in /images/buttons/ folder.
            custom_mouse_speed (float, optional): Time in seconds it takes for the mouse to move to the specified point. Defaults to 0.0.
            mouse_clicks (int, optional): Number of mouse clicks. Defaults to 1.

        Returns:
            None
        """
        if Settings.debug_mode:
            MessageLog.print_message(f"[DEBUG] Old coordinates: ({x}, {y})")

        new_x, new_y = MouseUtils._randomize_point(x, y, image_name)

        if Settings.debug_mode:
            MessageLog.print_message(
                f"[DEBUG] New coordinates: ({new_x}, {new_y})")

        # Move the mouse to the specified coordinates.
        if Settings.enable_bezier_curve_mouse_movement:
            # HumanClicker only accepts int as the mouse speed.
            if int(custom_mouse_speed) < 1:
                custom_mouse_speed = 1

            MouseUtils._hc.move(
                (new_x, new_y),
                duration=custom_mouse_speed,
                humanCurve=pyclick.HumanCurve(pyautogui.position(),
                                              (new_x, new_y)))
        else:
            if custom_mouse_speed <= 0.0:
                custom_mouse_speed = Settings.custom_mouse_speed

            pyautogui.moveTo(x,
                             y,
                             duration=custom_mouse_speed,
                             tween=pyautogui.easeInOutQuad)

        pyautogui.click(clicks=mouse_clicks)

        # This delay is necessary as ImageUtils will take the screenshot too fast and the bot will use the last frame before clicking to navigate.
        from bot.game import Game
        Game.wait(1)

        return None
 def test_discord_connection(self):
     print("\n[DISCORD] Starting Discord process on a new Thread...")
     discord_queue = multiprocessing.Queue()
     self._discord_process = multiprocessing.Process(
         target=discord_utils.start_now,
         args=(Settings.discord_token, Settings.user_id, discord_queue))
     self._discord_process.start()
     Game.wait(3.0)
     discord_queue.put("Testing 1 2 3")
     Game.wait(3.0)
     self.assertTrue(discord_queue.empty())
     self._discord_process.terminate()
     return None
    def _navigate():
        """Navigates to the specified Xeno Clash mission.

        Returns:
            None
        """
        from bot.game import Game

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check = True)

        MessageLog.print_message(f"\n[XENO.CLASH] Now navigating to Xeno Clash...")

        # Go to the Event by clicking on the "Menu" button and then click the very first banner.
        Game.find_and_click_button("home_menu")
        event_banner_locations = ImageUtils.find_all("event_banner", custom_confidence = 0.7)
        if len(event_banner_locations) == 0:
            event_banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence = 0.7)
        MouseUtils.move_and_click_point(event_banner_locations[0][0], event_banner_locations[0][1], "event_banner")

        Game.wait(2.0)

        if Game.find_and_click_button("xeno_special", tries = 30):
            # Check to see if the user already has a Nightmare available.
            nightmare_is_available = 0
            if ImageUtils.find_button("event_nightmare", tries = 1) is not None:
                nightmare_is_available = 1

            # Find all the "Select" buttons.
            select_button_locations = ImageUtils.find_all("select")

            if Settings.mission_name == "Xeno Clash Extreme":
                MessageLog.print_message(f"[XENO.CLASH] Now hosting Xeno Clash Extreme...")
                MouseUtils.move_and_click_point(select_button_locations[1 + nightmare_is_available][0], select_button_locations[1 + nightmare_is_available][1], "select")

                difficulty_button_locations = ImageUtils.find_all("play_round_button")
                MouseUtils.move_and_click_point(difficulty_button_locations[0][0], difficulty_button_locations[0][1], "play_round_button")
            elif Settings.mission_name == "Xeno Clash Raid":
                MessageLog.print_message(f"[XENO.CLASH] Now hosting Xeno Clash Raid...")
                MouseUtils.move_and_click_point(select_button_locations[2 + nightmare_is_available][0], select_button_locations[2 + nightmare_is_available][1], "select")

                Game.wait(2.0)

                Game.find_and_click_button("play")
        else:
            raise(XenoClashException("Failed to open the Xeno Special tab."))

        return None
Пример #6
0
    def _navigate():
        """Navigates to the specified Raid.

        Returns:
            None
        """
        from bot.game import Game

        MessageLog.print_message(
            f"\n[RAID] Beginning process to navigate to the raid: {Settings.mission_name}..."
        )

        # Head to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        # Then navigate to the Quest screen.
        Game.find_and_click_button("quest")

        Game.wait(1)

        # Check for the "You retreated from the raid battle" popup.
        if ImageUtils.confirm_location("you_retreated_from_the_raid_battle",
                                       tries=1):
            Game.find_and_click_button("ok")

        # Check for any Pending Battles popup.
        if Game.check_for_pending():
            Game.find_and_click_button("quest")

        # Now navigate to the Raid screen.
        Game.find_and_click_button("raid")

        if ImageUtils.confirm_location("raid"):
            # Check for any joined raids and if the max number of raids joined was reached, clear them.
            Raid._check_for_joined_raids()
            Raid._clear_joined_raids()

            # Click on the "Enter ID" button and then start the process to join a raid.
            MessageLog.print_message(
                f"\n[RAID] Now moving to the \"Enter ID\" screen.")
            if Game.find_and_click_button("enter_id"):
                Raid._join_raid()
        else:
            raise RaidException("Failed to reach the Backup Requests screen.")
Пример #7
0
    def _check_for_joined_raids():
        """Check and update the number of raids currently joined.

        Returns:
            None
        """
        from bot.game import Game

        # Find out the number of currently joined raids.
        Game.wait(1)
        joined_locations = ImageUtils.find_all("joined")

        if joined_locations is not None:
            Raid._raids_joined = len(joined_locations)
            MessageLog.print_message(
                f"\n[RAID] There are currently {Raid._raids_joined} raids joined."
            )

        return None
Пример #8
0
    def _clear_joined_raids():
        """Begin process to wait out the joined raids if there are 3 or more currently active.

        Returns:
            None
        """
        from bot.game import Game

        # If the maximum number of raids has been joined, collect any pending rewards with a interval of 30 seconds in between until the number of joined raids is below 3.
        while Raid._raids_joined >= 3:
            MessageLog.print_message(
                f"\n[RAID] Maximum raids of 3 has been joined. Waiting 30 seconds to see if any finish."
            )
            Game.wait(30)

            Game.go_back_home(confirm_location_check=True)
            Game.find_and_click_button("quest")

            if Game.check_for_pending():
                Game.find_and_click_button("quest")
                Game.wait(1)

            Game.find_and_click_button("raid")
            Game.wait(1)
            Raid._check_for_joined_raids()

        return None
    def test_combat_mode_old_lignoid(self):
        # Make sure the bot is at the Home screen and go to the Trial Battles screen.
        self.game_object.go_back_home(confirm_location_check=True)
        MouseUtils.scroll_screen_from_home_button(-600)
        self.game_object.find_and_click_button("gameplay_extras")

        while self.game_object.find_and_click_button("trial_battles") is False:
            MouseUtils.scroll_screen_from_home_button(-300)

        self.assertTrue(ImageUtils.confirm_location("trial_battles"))
        # Click on the "Old Lignoid" button.
        self.game_object.find_and_click_button("trial_battles_old_lignoid")

        # Select any detected "Play" button.
        self.game_object.find_and_click_button("play_round_button")

        # Now select the first Summon.
        choose_a_summon_location = ImageUtils.find_button("choose_a_summon")
        MouseUtils.move_and_click_point(choose_a_summon_location[0],
                                        choose_a_summon_location[1] + 187,
                                        "choose_a_summon")

        # Now start the Old Lignoid Trial Battle right away and then wait a few seconds.
        self.game_object.find_and_click_button("party_selection_ok")
        Game.wait(3)

        if ImageUtils.confirm_location("trial_battles_description"):
            self.game_object.find_and_click_button("close")

        self.assertFalse(
            CombatMode.start_combat_mode(script_commands=[
                "Turn 1:", "\tsummon(6)", "\tcharacter1.useSkill(1)", "end",
                "", "Turn 5:", "\texit", "end"
            ]))
        self.assertTrue(ImageUtils.confirm_location("home"))
        return None
Пример #10
0
    def _navigate():
        """Navigates to the specified Special mission.

        Returns:
            None
        """
        from bot.game import Game

        MessageLog.print_message(
            f"\n[SPECIAL] Beginning process to navigate to the mission: {Settings.mission_name}..."
        )

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        # Go to the Quest screen.
        Game.find_and_click_button("quest", suppress_error=True)

        # Check for the "You retreated from the raid battle" popup.
        Game.wait(1)
        if ImageUtils.confirm_location("you_retreated_from_the_raid_battle",
                                       tries=1):
            Game.find_and_click_button("ok")

        if ImageUtils.confirm_location("quest"):
            # Go to the Special screen.
            Game.find_and_click_button("special")

            # Remove the difficulty prefix from the mission name.
            difficulty = ""
            if Settings.mission_name.find("N ") == 0:
                difficulty = "Normal"
                formatted_mission_name = Settings.mission_name[2:]
            elif Settings.mission_name.find("H ") == 0:
                difficulty = "Hard"
                formatted_mission_name = Settings.mission_name[2:]
            elif Settings.mission_name.find("VH ") == 0:
                difficulty = "Very Hard"
                formatted_mission_name = Settings.mission_name[3:]
            elif Settings.mission_name.find("EX ") == 0:
                difficulty = "Extreme"
                formatted_mission_name = Settings.mission_name[3:]
            else:
                formatted_mission_name = Settings.mission_name

            if ImageUtils.confirm_location("special"):
                tries = 2

                # Try to select the specified Special mission for a number of tries.
                while tries != 0:
                    # Scroll the screen down if its any of the Special Quests that are more towards the bottom of the page to alleviate problems for smaller screens.
                    if Settings.map_name != "Campaign-Exclusive Quest" and Settings.map_name != "Basic Treasure Quests" and Settings.map_name != "Shiny Slime Search!" and Settings.map_name != "Six Dragon Trial":
                        MouseUtils.scroll_screen_from_home_button(-500)

                    mission_select_button = ImageUtils.find_button(
                        Settings.map_name.lower().replace(" ", "_").replace(
                            "-", "_"))
                    if mission_select_button is not None:
                        MessageLog.print_message(
                            f"[SPECIAL] Navigating to {Settings.map_name}...")

                        # Move to the specified Special by clicking its "Select" button.
                        special_quest_select_button = (
                            mission_select_button[0] + 145,
                            mission_select_button[1] + 75)
                        MouseUtils.move_and_click_point(
                            special_quest_select_button[0],
                            special_quest_select_button[1], "select")

                        Game.wait(1)

                        if Settings.map_name == "Basic Treasure Quests":
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if formatted_mission_name == "Scarlet Trial":
                                # Navigate to Scarlet Trial.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Scarlet Trial...")
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Cerulean Trial":
                                # Navigate to Cerulean Trial.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Cerulean Trial...")
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Violet Trial":
                                # Navigate to Violet Trial.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Violet Trial...")
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                            Game.wait(1)

                            # Now start the Trial with the specified difficulty.
                            MessageLog.print_message(
                                f"[SPECIAL] Now navigating to {difficulty}...")
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if difficulty == "Normal":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif difficulty == "Hard":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif difficulty == "Very Hard":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                        elif Settings.map_name == "Shiny Slime Search!":
                            # Start up the Shiny Slime Search! mission by selecting its difficulty.
                            MessageLog.print_message(
                                f"[SPECIAL] Selecting {difficulty} Shiny Slime Search!..."
                            )
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if difficulty == "Normal":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif difficulty == "Hard":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif difficulty == "Very Hard":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                        elif Settings.map_name == "Six Dragon Trial":
                            # Start up the Six Dragon Trial mission by selecting its difficulty.
                            MessageLog.print_message(
                                f"[SPECIAL] Selecting {difficulty} Six Dragon Trial..."
                            )
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if difficulty == "Normal":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif difficulty == "Hard":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif difficulty == "Very Hard":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                        elif Settings.map_name == "Elemental Treasure Quests":
                            # Start up the specified Elemental Treasure Quest mission.
                            MessageLog.print_message(
                                f"[SPECIAL] Selecting {Settings.mission_name}..."
                            )
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if formatted_mission_name == "The Hellfire Trial":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif formatted_mission_name == "The Deluge Trial":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif formatted_mission_name == "The Wasteland Trial":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")
                            elif formatted_mission_name == "The Typhoon Trial":
                                MouseUtils.move_and_click_point(
                                    locations[3][0], locations[3][1],
                                    "play_round_button")
                            elif formatted_mission_name == "The Aurora Trial":
                                MouseUtils.move_and_click_point(
                                    locations[4][0], locations[4][1],
                                    "play_round_button")
                            elif formatted_mission_name == "The Oblivion Trial":
                                MouseUtils.move_and_click_point(
                                    locations[5][0], locations[5][1],
                                    "play_round_button")

                        elif Settings.map_name == "Showdowns":
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if formatted_mission_name == "Ifrit Showdown":
                                # Navigate to Ifrit Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Ifrit Showdown...")
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Cocytus Showdown":
                                # Navigate to Cocytus Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Cocytus Showdown...")
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Vohu Manah Showdown":
                                # Navigate to Vohu Manah Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Vohu Manah Showdown..."
                                )
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Sagittarius Showdown":
                                # Navigate to Sagittarius Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Sagittarius Showdown..."
                                )
                                MouseUtils.move_and_click_point(
                                    locations[3][0], locations[3][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Corow Showdown":
                                # Navigate to Corow Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Corow Showdown...")
                                MouseUtils.move_and_click_point(
                                    locations[4][0], locations[4][1],
                                    "play_round_button")
                            elif formatted_mission_name == "Diablo Showdown":
                                # Navigate to Diablo Showdown.
                                MessageLog.print_message(
                                    f"[SPECIAL] Selecting Diablo Showdown...")
                                MouseUtils.move_and_click_point(
                                    locations[5][0], locations[5][1],
                                    "play_round_button")

                            # Now start the Showdown with the specified difficulty.
                            Game.wait(1)
                            MessageLog.print_message(
                                f"[SPECIAL] Now navigating to {difficulty}...")
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if difficulty == "Hard":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif difficulty == "Very Hard":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif difficulty == "Extreme":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                        elif Settings.map_name == "Campaign-Exclusive Quest":
                            MessageLog.print_message(
                                f"[SPECIAL] Selecting Campaign-Exclusive Quest..."
                            )
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            # There is only one round "Play" button for this time-limited quest.
                            MouseUtils.move_and_click_point(
                                locations[0][0], locations[0][1],
                                "play_round_button")

                        else:
                            # Start up the Angel Halo mission by selecting its difficulty.
                            MessageLog.print_message(
                                f"[SPECIAL] Selecting {difficulty} Angel Halo..."
                            )
                            locations = ImageUtils.find_all(
                                "play_round_button")

                            if difficulty == "Normal":
                                MouseUtils.move_and_click_point(
                                    locations[0][0], locations[0][1],
                                    "play_round_button")
                            elif difficulty == "Hard":
                                MouseUtils.move_and_click_point(
                                    locations[1][0], locations[1][1],
                                    "play_round_button")
                            elif difficulty == "Very Hard":
                                MouseUtils.move_and_click_point(
                                    locations[2][0], locations[2][1],
                                    "play_round_button")

                        break
                    else:
                        # Scroll the screen down more if on a smaller screen and it obscures the targeted mission.
                        MouseUtils.scroll_screen(
                            Settings.home_button_location[0],
                            Settings.home_button_location[1] - 50, -500)
                        tries -= 1

        return None
Пример #11
0
    def check_for_dimensional_halo():
        """Checks for Dimensional Halo and if it appears and the user enabled it in user settings, start it.

        Returns:
            (bool): Return True if Dimensional Halo was detected and successfully completed. Otherwise, return False.
        """
        from bot.game import Game

        if Settings.enable_nightmare and ImageUtils.confirm_location(
                "limited_time_quests", tries=1):
            MessageLog.print_message(
                "\n[D.HALO] Detected Dimensional Halo. Starting it now...")
            Special._dimensional_halo_amount += 1

            MessageLog.print_message(
                "\n********************************************************************************"
            )
            MessageLog.print_message(
                "********************************************************************************"
            )
            MessageLog.print_message(f"[D.HALO] Dimensional Halo")
            MessageLog.print_message(
                f"[D.HALO] Dimensional Halo Summon Elements: {Settings.nightmare_summon_elements_list}"
            )
            MessageLog.print_message(
                f"[D.HALO] Dimensional Halo Summons: {Settings.nightmare_summon_list}"
            )
            MessageLog.print_message(
                f"[D.HALO] Dimensional Halo Group Number: {Settings.nightmare_group_number}"
            )
            MessageLog.print_message(
                f"[D.HALO] Dimensional Halo Party Number: {Settings.nightmare_party_number}"
            )
            MessageLog.print_message(
                f"[D.HALO] Dimensional Halo Combat Script: {Settings.nightmare_combat_script_name}"
            )
            MessageLog.print_message(
                "********************************************************************************"
            )
            MessageLog.print_message(
                "********************************************************************************\n"
            )

            # Click the "Play Next" button to head to the Summon Selection screen.
            Game.find_and_click_button("play_next")

            Game.wait(1)

            # Once the bot is at the Summon Selection screen, select your Summon and Party and start the mission.
            if ImageUtils.confirm_location("select_a_summon"):
                Game.select_summon(Settings.nightmare_summon_list,
                                   Settings.nightmare_summon_elements_list)
                start_check = Game.find_party_and_start_mission(
                    int(Settings.nightmare_group_number),
                    int(Settings.nightmare_party_number))

                # Once preparations are completed, start Combat Mode.
                if start_check and CombatMode.start_combat_mode(
                        is_nightmare=True):
                    Game.collect_loot(is_completed=False,
                                      is_event_nightmare=True)
                    return True

        elif not Settings.enable_nightmare and ImageUtils.confirm_location(
                "limited_time_quests", tries=1):
            MessageLog.print_message(
                "\n[D.HALO] Dimensional Halo detected but user opted to not run it. Moving on..."
            )
            Game.find_and_click_button("close")
        else:
            MessageLog.print_message(
                "\n[D.HALO] No Dimensional Halo detected. Moving on...")

        return False
    def _navigate_to_map() -> bool:
        """Navigates to the specified Arcarum expedition.

        Returns:
            (bool): True if the bot was able to start/resume the expedition. False otherwise.
        """
        from bot.game import Game

        if Arcarum._first_run:
            MessageLog.print_message(
                f"\n[ARCARUM] Now beginning navigation to {Arcarum._expedition}."
            )
            Game.go_back_home()

            # Navigate to the Arcarum banner.
            tries = 5
            while tries > 0:
                if Game.find_and_click_button("arcarum_banner",
                                              tries=1) is False:
                    MouseUtils.scroll_screen_from_home_button(-300)
                    tries -= 1
                    if tries <= 0:
                        raise ArcarumException(
                            "Failed to navigate to Arcarum from the Home screen."
                        )
                else:
                    break

            Arcarum._first_run = False
        else:
            Game.wait(4)

        # Now make sure that the Extreme difficulty is selected.
        Game.wait(1)

        # Confirm the completion popup if it shows up.
        if ImageUtils.confirm_location("arcarum_expedition", tries=1):
            Game.find_and_click_button("ok")

        Game.find_and_click_button("arcarum_extreme")

        # Finally, navigate to the specified map to start it.
        MessageLog.print_message(
            f"[ARCARUM] Now starting the specified expedition: {Arcarum._expedition}."
        )
        formatted_map_name = Arcarum._expedition.lower().replace(" ", "_")

        if Game.find_and_click_button(f"arcarum_{formatted_map_name}",
                                      tries=5) is False:
            # Resume the expedition if it is already in-progress.
            Game.find_and_click_button("arcarum_exploring")
        elif ImageUtils.confirm_location("arcarum_departure_check"):
            MessageLog.print_message(
                f"[ARCARUM] Now using 1 Arcarum ticket to start this expedition..."
            )
            result_check = Game.find_and_click_button("start_expedition")
            Game.wait(6)
            return result_check
        elif Game.find_and_click_button("resume"):
            Game.wait(3)
            return True
        else:
            raise ArcarumException(
                "Failed to encounter the Departure Check to confirm starting the expedition."
            )
    def _navigate():
        """Navigates to the specified Rise of the Beasts mission.

        Returns:
            None
        """
        from bot.game import Game

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        MessageLog.print_message(
            f"\n[ROTB] Now navigating to Rise of the Beasts...")

        # Go to the Event by clicking on the "Menu" button and then click the very first banner.
        Game.find_and_click_button("home_menu")
        banner_locations = ImageUtils.find_all("event_banner",
                                               custom_confidence=0.7)
        if len(banner_locations) == 0:
            banner_locations = ImageUtils.find_all("event_banner_blue",
                                                   custom_confidence=0.7)
        MouseUtils.move_and_click_point(banner_locations[0][0],
                                        banner_locations[0][1], "event_banner")

        Game.wait(1)

        if ImageUtils.confirm_location("rotb"):
            # Remove the difficulty prefix from the mission name.
            difficulty = ""
            temp_mission_name = ""
            if Settings.mission_name.find("VH ") == 0:
                difficulty = "Very Hard"
                temp_mission_name = Settings.mission_name[3:]
            elif Settings.mission_name.find("EX ") == 0:
                difficulty = "Extreme"
                temp_mission_name = Settings.mission_name[3:]

            # Only Raids are marked with Extreme difficulty.
            if difficulty == "Extreme":
                # Click on the Raid banner.
                MessageLog.print_message(
                    f"[ROTB] Now hosting {temp_mission_name} Raid...")
                Game.find_and_click_button("rotb_extreme")

                if ImageUtils.confirm_location("rotb_battle_the_beasts",
                                               tries=30):
                    if temp_mission_name == "Zhuque":
                        MessageLog.print_message(
                            f"[ROTB] Now starting EX Zhuque Raid...")
                        Game.find_and_click_button("rotb_raid_zhuque")
                    elif temp_mission_name == "Xuanwu":
                        MessageLog.print_message(
                            f"[ROTB] Now starting EX Xuanwu Raid...")
                        Game.find_and_click_button("rotb_raid_xuanwu")
                    elif temp_mission_name == "Baihu":
                        MessageLog.print_message(
                            f"[ROTB] Now starting EX Baihu Raid...")
                        Game.find_and_click_button("rotb_raid_baihu")
                    elif temp_mission_name == "Qinglong":
                        MessageLog.print_message(
                            f"[ROTB] Now starting EX Qinglong Raid...")
                        Game.find_and_click_button("rotb_raid_qinglong")
                else:
                    raise (RiseOfTheBeastsException(
                        "Failed to open the ROTB Battle the Beasts popup."))

            elif Settings.mission_name == "Lvl 100 Shenxian":
                # Click on Shenxian to host.
                MessageLog.print_message(
                    f"[ROTB] Now hosting Shenxian Raid...")
                Game.find_and_click_button("rotb_shenxian_host")

                if ImageUtils.wait_vanish("rotb_shenxian_host",
                                          timeout=10) is False:
                    MessageLog.print_message(
                        f"[ROTB] There are no more Shenxian hosts left. Alerting user..."
                    )
                    raise RiseOfTheBeastsException(
                        "There are no more Shenxian hosts left.")

            else:
                MessageLog.print_message(
                    f"[ROTB] Now hosting {temp_mission_name} Quest...")

                # Scroll the screen down to make way for smaller screens.
                MouseUtils.scroll_screen_from_home_button(-400)

                # Find all instances of the "Select" button on the screen and click on the first instance.
                select_button_locations = ImageUtils.find_all("select")
                MouseUtils.move_and_click_point(select_button_locations[0][0],
                                                select_button_locations[0][1],
                                                "select")

                if ImageUtils.confirm_location("rotb_rising_beasts_showdown",
                                               tries=30):
                    # Find all the round "Play" buttons.
                    round_play_button_locations = ImageUtils.find_all(
                        "play_round_button")

                    if temp_mission_name == "Zhuque":
                        MouseUtils.move_and_click_point(
                            round_play_button_locations[0][0],
                            round_play_button_locations[0][1],
                            "play_round_button")
                    elif temp_mission_name == "Xuanwu":
                        MouseUtils.move_and_click_point(
                            round_play_button_locations[1][0],
                            round_play_button_locations[1][1],
                            "play_round_button")
                    elif temp_mission_name == "Baihu":
                        MouseUtils.move_and_click_point(
                            round_play_button_locations[2][0],
                            round_play_button_locations[2][1],
                            "play_round_button")
                    elif temp_mission_name == "Qinglong":
                        MouseUtils.move_and_click_point(
                            round_play_button_locations[3][0],
                            round_play_button_locations[3][1],
                            "play_round_button")

                    Game.wait(2.0)

                    # Find all the round "Play" buttons again.
                    round_play_button_locations = ImageUtils.find_all(
                        "play_round_button")

                    # Only Very Hard difficulty will be supported for farming efficiency
                    MouseUtils.move_and_click_point(
                        round_play_button_locations[2][0],
                        round_play_button_locations[2][1], "play_round_button")
                else:
                    raise (RiseOfTheBeastsException(
                        "Failed to open the ROTB Rising Beasts Showdown popup."
                    ))

        return None
    def check_for_rotb_extreme_plus():
        """Checks for Extreme+ for Rise of the Beasts and if it appears and the user enabled it in user settings, start it.

        Returns:
            (bool): Return True if Extreme+ was detected and successfully completed. Otherwise, return False.
        """
        from bot.game import Game

        if Settings.enable_nightmare and ImageUtils.confirm_location(
                "rotb_extreme_plus", tries=1):
            MessageLog.print_message(
                "\n[ROTB] Detected Extreme+. Starting it now...")

            MessageLog.print_message(
                "\n********************************************************************************"
            )
            MessageLog.print_message(
                "********************************************************************************"
            )
            MessageLog.print_message(f"[ROTB] Rise of the Beasts Extreme+")
            MessageLog.print_message(
                f"[ROTB] Rise of the Beasts Extreme+ Summon Elements: {Settings.nightmare_summon_elements_list}"
            )
            MessageLog.print_message(
                f"[ROTB] Rise of the Beasts Extreme+ Summons: {Settings.nightmare_summon_list}"
            )
            MessageLog.print_message(
                f"[ROTB] Rise of the Beasts Extreme+ Group Number: {Settings.nightmare_group_number}"
            )
            MessageLog.print_message(
                f"[ROTB] Rise of the Beasts Extreme+ Party Number: {Settings.nightmare_party_number}"
            )
            MessageLog.print_message(
                f"[ROTB] Rise of the Beasts Extreme+ Combat Script: {Settings.nightmare_combat_script_name}"
            )
            MessageLog.print_message(
                "********************************************************************************"
            )
            MessageLog.print_message(
                "********************************************************************************\n"
            )

            # Click the "Play Next" button to head to the Summon Selection screen.
            Game.find_and_click_button("play_next")

            Game.wait(1)

            # Once the bot is at the Summon Selection screen, select your Summon and Party and start the mission.
            if ImageUtils.confirm_location("select_a_summon"):
                Game.select_summon(Settings.nightmare_summon_list,
                                   Settings.nightmare_summon_elements_list)
                start_check = Game.find_party_and_start_mission(
                    int(Settings.nightmare_group_number),
                    int(Settings.nightmare_party_number))

                # Once preparations are completed, start Combat mode.
                if start_check and CombatMode.start_combat_mode(
                        is_nightmare=True):
                    Game.collect_loot(is_completed=False,
                                      is_event_nightmare=True)
                    return True

        elif not Settings.enable_nightmare and ImageUtils.confirm_location(
                "rotb_extreme_plus", tries=2):
            MessageLog.print_message(
                "\n[ROTB] Rise of the Beasts Extreme+ detected but user opted to not run it. Moving on..."
            )
            Game.find_and_click_button("close")
        else:
            MessageLog.print_message(
                "\n[ROTB] No Rise of the Beasts Extreme+ detected. Moving on..."
            )

        return False
Пример #15
0
    def _navigate():
        """Navigates to the specified Dread Barrage mission.

        Returns:
            None
        """
        from bot.game import Game

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check = True)

        # Scroll down the screen a little bit and then click the Dread Barrage banner.
        MessageLog.print_message(f"\n[DREAD.BARRAGE] Now navigating to Dread Barrage...")
        MouseUtils.scroll_screen_from_home_button(-400)
        Game.find_and_click_button("dread_barrage")

        Game.wait(2)

        if ImageUtils.confirm_location("dread_barrage"):
            # Check if there is already a hosted Dread Barrage mission.
            if ImageUtils.confirm_location("resume_quests", tries = 1):
                MessageLog.print_message(f"\n[WARNING] Detected that there is already a hosted Dread Barrage mission.")
                expiry_time_in_seconds = 0

                while ImageUtils.confirm_location("resume_quests", tries = 1):
                    # If there is already a hosted Dread Barrage mission, the bot will wait for a total of 1 hour and 30 minutes
                    # for either the raid to expire or for anyone in the room to clear it.
                    MessageLog.print_message(f"\n[WARNING] The bot will now either wait for the expiry time of 1 hour and 30 minutes or for someone else in the room to clear it.")
                    MessageLog.print_message(f"[WARNING] The bot will now refresh the page every 30 seconds to check if it is still there before proceeding.")
                    MessageLog.print_message(f"[WARNING] User can either wait it out, revive and fight it to completion, or retreat from the mission manually.")
                    Game.wait(30)

                    Game.find_and_click_button("reload")
                    Game.wait(2)

                    expiry_time_in_seconds += 30
                    if expiry_time_in_seconds >= 5400:
                        break

                MessageLog.print_message(f"\n[SUCCESS] Hosted Dread Barrage mission is now gone either because of timeout or someone else in the room killed it. Moving on...\n")

            # Find all the "Play" buttons at the top of the window.
            dread_barrage_play_button_locations = ImageUtils.find_all("dread_barrage_play")

            difficulty = ""
            if Settings.mission_name.find("1 Star") == 0:
                difficulty = "1 Star"
            elif Settings.mission_name.find("2 Star") == 0:
                difficulty = "2 Star"
            elif Settings.mission_name.find("3 Star") == 0:
                difficulty = "3 Star"
            elif Settings.mission_name.find("4 Star") == 0:
                difficulty = "4 Star"
            elif Settings.mission_name.find("5 Star") == 0:
                difficulty = "5 Star"

            # Navigate to the specified difficulty.
            if difficulty == "1 Star":
                MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 1 Star Dread Barrage Raid...")
                MouseUtils.move_and_click_point(dread_barrage_play_button_locations[0][0], dread_barrage_play_button_locations[0][1], "dread_barrage_play")
            elif difficulty == "2 Star":
                MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 2 Star Dread Barrage Raid...")
                MouseUtils.move_and_click_point(dread_barrage_play_button_locations[1][0], dread_barrage_play_button_locations[1][1], "dread_barrage_play")
            elif difficulty == "3 Star":
                MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 3 Star Dread Barrage Raid...")
                MouseUtils.move_and_click_point(dread_barrage_play_button_locations[2][0], dread_barrage_play_button_locations[2][1], "dread_barrage_play")
            elif difficulty == "4 Star":
                MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 4 Star Dread Barrage Raid...")
                MouseUtils.move_and_click_point(dread_barrage_play_button_locations[3][0], dread_barrage_play_button_locations[3][1], "dread_barrage_play")
            elif difficulty == "5 Star":
                MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 5 Star Dread Barrage Raid...")
                MouseUtils.move_and_click_point(dread_barrage_play_button_locations[4][0], dread_barrage_play_button_locations[4][1], "dread_barrage_play")

            Game.wait(2)
    def start() -> int:
        """Starts the process of completing Arcarum expeditions.

        Returns:
            (int): Number of runs completed.
        """
        from bot.game import Game

        runs_completed = 0
        while runs_completed < Settings.item_amount_to_farm:
            Arcarum._navigate_to_map()

            while True:
                action = Arcarum._choose_action()
                MessageLog.print_message(
                    f"[ARCARUM] Action to take will be: {action}")

                if action == "Combat":
                    # Start Combat Mode.
                    if Game.find_party_and_start_mission(
                            Settings.group_number, Settings.party_number):
                        if ImageUtils.confirm_location("elemental_damage",
                                                       tries=1):
                            raise ArcarumException(
                                "Encountered an important mob for Arcarum and the selected party does not conform to the enemy's weakness. Perhaps you would like to do this battle yourself?"
                            )
                        elif ImageUtils.confirm_location("arcarum_restriction",
                                                         tries=1):
                            raise ArcarumException(
                                "Encountered a party restriction for Arcarum. Perhaps you would like to complete this section by yourself?"
                            )

                        if CombatMode.start_combat_mode():
                            Game.collect_loot(is_completed=False,
                                              skip_info=True)
                            Game.find_and_click_button("expedition")
                elif action == "Navigating":
                    # Move to the next available node.
                    Game.find_and_click_button("move")
                elif action == "Next Area":
                    # Either navigate to the next area or confirm the expedition's conclusion.
                    if Game.find_and_click_button("arcarum_next_stage"):
                        Game.find_and_click_button("ok")
                        MessageLog.print_message(
                            f"[ARCARUM] Moving to the next area...")
                    elif Game.find_and_click_button("arcarum_checkpoint"):
                        Game.find_and_click_button("arcarum")
                        MessageLog.print_message(
                            f"[ARCARUM] Expedition is complete.")
                        runs_completed += 1

                        Game.wait(1)
                        Game.check_for_skyscope()
                        break
                elif action == "Boss Detected":
                    MessageLog.print_message(
                        f"[ARCARUM] Boss has been detected. Stopping the bot.")
                    raise ArcarumException(
                        "Boss has been detected. Stopping the bot.")

                Game.wait(1)

        return runs_completed
    def check_for_event_nightmare():
        """Checks for Event Nightmare and if it appears and the user enabled it in user settings, start it.

        Returns:
            (bool): Return True if Event Nightmare was detected and successfully completed. Otherwise, return False.
        """
        from bot.game import Game

        if Settings.enable_nightmare and ImageUtils.confirm_location(
                "limited_time_quests", tries=1):
            # First check if the Event Nightmare is skippable.
            event_claim_loot_location = ImageUtils.find_button(
                "event_claim_loot", tries=1, suppress_error=True)
            if event_claim_loot_location is not None:
                MessageLog.print_message(
                    "\n[EVENT] Skippable Event Nightmare detected. Claiming it now..."
                )
                MouseUtils.move_and_click_point(event_claim_loot_location[0],
                                                event_claim_loot_location[1],
                                                "event_claim_loot")
                Game.collect_loot(is_completed=False, is_event_nightmare=True)
                return True
            else:
                MessageLog.print_message(
                    "\n[EVENT] Detected Event Nightmare. Starting it now...")

                MessageLog.print_message(
                    "\n********************************************************************************"
                )
                MessageLog.print_message(
                    "********************************************************************************"
                )
                MessageLog.print_message(f"[EVENT] Event Nightmare")
                MessageLog.print_message(
                    f"[EVENT] Event Nightmare Summon Elements: {Settings.nightmare_summon_elements_list}"
                )
                MessageLog.print_message(
                    f"[EVENT] Event Nightmare Summons: {Settings.nightmare_summon_list}"
                )
                MessageLog.print_message(
                    f"[EVENT] Event Nightmare Group Number: {Settings.nightmare_group_number}"
                )
                MessageLog.print_message(
                    f"[EVENT] Event Nightmare Party Number: {Settings.nightmare_party_number}"
                )
                MessageLog.print_message(
                    f"[EVENT] Event Nightmare Combat Script: {Settings.nightmare_combat_script_name}"
                )
                MessageLog.print_message(
                    "********************************************************************************"
                )
                MessageLog.print_message(
                    "********************************************************************************\n"
                )

                # Click the "Play Next" button to head to the Summon Selection screen.
                Game.find_and_click_button("play_next")

                Game.wait(1)

                # Once the bot is at the Summon Selection screen, select your Summon and Party and start the mission.
                if ImageUtils.confirm_location("select_a_summon"):
                    Game.select_summon(Settings.nightmare_summon_list,
                                       Settings.nightmare_summon_elements_list)
                    start_check = Game.find_party_and_start_mission(
                        int(Settings.nightmare_group_number),
                        int(Settings.nightmare_party_number))

                    # Once preparations are completed, start Combat Mode.
                    if start_check and CombatMode.start_combat_mode(
                            is_nightmare=True):
                        Game.collect_loot(is_completed=False,
                                          is_event_nightmare=True)
                        return True

        elif not Settings.enable_nightmare and ImageUtils.confirm_location(
                "limited_time_quests", tries=1):
            # First check if the Event Nightmare is skippable.
            event_claim_loot_location = ImageUtils.find_button(
                "event_claim_loot", tries=1, suppress_error=True)
            if event_claim_loot_location is not None:
                MessageLog.print_message(
                    "\n[EVENT] Skippable Event Nightmare detected but user opted to not run it. Claiming it regardless..."
                )
                MouseUtils.move_and_click_point(event_claim_loot_location[0],
                                                event_claim_loot_location[1],
                                                "event_claim_loot")
                Game.collect_loot(is_completed=False, is_event_nightmare=True)
                return True
            else:
                MessageLog.print_message(
                    "\n[EVENT] Event Nightmare detected but user opted to not run it. Moving on..."
                )
                Game.find_and_click_button("close")
        else:
            MessageLog.print_message(
                "\n[EVENT] No Event Nightmare detected. Moving on...")

        return False
Пример #18
0
    def find_summon(summon_list: List[str],
                    summon_element_list: List[str],
                    home_button_x: int,
                    home_button_y: int,
                    custom_confidence: float = 0.8,
                    suppress_error: bool = False):
        """Find the location of the specified Summon. Will attempt to scroll the screen down to see more Summons if the initial screen position yielded no matches.

        Args:
            summon_list (List[str]): List of names of the Summon image's file name in /images/summons/ folder.
            summon_element_list (List[str]): List of names of the Summon element image file in the /images/buttons/ folder.
            home_button_x (int): X coordinate of where the center of the Home Button is.
            home_button_y (int): Y coordinate of where the center of the Home Button is.
            custom_confidence (float, optional): Accuracy threshold for matching. Defaults to 0.8.
            suppress_error (bool, optional): Suppresses template matching error if True. Defaults to False.

        Returns:
            (Tuple[int, int]): Tuple of coordinates of where the center of the Summon is located if image matching was successful. Otherwise, return None.
        """
        from bot.game import Game

        if Settings.debug_mode:
            MessageLog.print_message(
                f"[DEBUG] Received the following list of Summons to search for: {str(summon_list)}"
            )
            MessageLog.print_message(
                f"[DEBUG] Received the following list of Elements: {str(summon_element_list)}"
            )

        last_summon_element = ""
        summon_index = 0

        # Make sure that the bot is at the Summon Selection screen.
        tries = 10
        while not ImageUtils.confirm_location("select_a_summon"):
            Game.find_and_click_button('reload')
            tries -= 1
            if tries <= 0 and ImageUtils.confirm_location("select_a_summon",
                                                          tries=1) is False:
                raise Exception("Could not reach the Summon Selection screen.")

        # Determine if all the summon elements are the same or not. This will influence whether or not the bot needs to change elements in repeated runs.
        ImageUtils._summon_selection_same_element = all(
            element == summon_element_list[0]
            for element in summon_element_list)

        while True:
            # Perform first time setup by selecting the correct summon element.
            if ImageUtils._summon_selection_first_run or ImageUtils._summon_selection_same_element is False:
                current_summon_element: str = summon_element_list[summon_index]
                if current_summon_element != last_summon_element:
                    Game.find_and_click_button(
                        f"summon_{current_summon_element}")
                    last_summon_element = current_summon_element

                ImageUtils._summon_selection_first_run = False

            summon_index = 0
            while summon_index < len(summon_list):
                # Now try and find the Summon at the current index.
                template: numpy.ndarray = cv2.imread(
                    f"{ImageUtils._current_dir}/images/summons/{summon_list[summon_index]}.jpg",
                    0)

                # Crop the summon template image so that plus marks would not potentially obscure any match.
                height, width = template.shape
                template = template[0:height, 0:width - 40]

                result_flag: bool = ImageUtils._match(template,
                                                      custom_confidence)

                if result_flag:
                    if Settings.debug_mode:
                        MessageLog.print_message(
                            f"[SUCCESS] Found {summon_list[summon_index].upper()} Summon at {ImageUtils._match_location}."
                        )

                    return ImageUtils._match_location
                else:
                    if suppress_error is False:
                        MessageLog.print_message(
                            f"[WARNING] Could not locate {summon_list[summon_index].upper()} Summon."
                        )

                    summon_index += 1

            # If the bot reached the bottom of the page, scroll back up to the top and start searching for the next Summon.
            if ImageUtils.find_button("bottom_of_summon_selection",
                                      tries=1) is not None:
                MessageLog.print_message(
                    f"[WARNING] Bot has reached the bottom of the page and found no suitable Summons. Resetting Summons now..."
                )
                return None

            # If matching failed, scroll the screen down to see more Summons.
            from utils.mouse_utils import MouseUtils
            MouseUtils.scroll_screen(home_button_x, home_button_y - 50, -700)
            Game.wait(1.0)
    def start(first_run: bool) -> int:
        """Starts the process to complete a run for Proving Grounds Farming Mode and returns the number of items detected.

        Args:
            first_run (bool): Flag that determines whether or not to run the navigation process again. Should be False if the Farming Mode supports the "Play Again" feature for repeated runs.

        Returns:
            (int): Number of runs completed.
        """
        from bot.game import Game

        runs_completed: int = 0

        # Start the navigation process.
        if first_run and ProvingGrounds._first_time:
            ProvingGrounds._navigate()
        elif ProvingGrounds._first_time and Game.find_and_click_button(
                "play_again"):
            MessageLog.print_message(
                "\n[PROVING.GROUNDS] Starting Proving Grounds Mission again..."
            )

        # Check for AP.
        Game.check_for_ap()

        # Check if the bot is at the Summon Selection screen.
        if (first_run
                or ProvingGrounds._first_time) and ImageUtils.confirm_location(
                    "proving_grounds_summon_selection", tries=30):
            summon_check = Game.select_summon(Settings.summon_list,
                                              Settings.summon_element_list)
            if summon_check:
                Game.wait(2.0)

                # No need to select a Party. Just click "OK" to start the mission and confirming the selected summon.
                Game.find_and_click_button("ok")

                Game.wait(2.0)

                MessageLog.print_message(
                    "\n[PROVING.GROUNDS] Now starting Mission for Proving Grounds..."
                )
                Game.find_and_click_button("proving_grounds_start")

                # Now start Combat Mode and detect any item drops.
                if CombatMode.start_combat_mode():
                    runs_completed = Game.collect_loot(is_completed=False)

                    # Click the "Next Battle" button if there are any battles left.
                    if Game.find_and_click_button(
                            "proving_grounds_next_battle"):
                        MessageLog.print_message(
                            "\n[PROVING.GROUNDS] Moving onto the next battle for Proving Grounds..."
                        )
                        Game.find_and_click_button("ok")
                        ProvingGrounds._first_time = False
        elif first_run is False and ProvingGrounds._first_time is False:
            # No need to select a Summon again as it is reused.
            if CombatMode.start_combat_mode():
                runs_completed = Game.collect_loot(is_completed=False)

                # Click the "Next Battle" button if there are any battles left.
                if Game.find_and_click_button("proving_grounds_next_battle"):
                    MessageLog.print_message(
                        "\n[PROVING.GROUNDS] Moving onto the next battle for Proving Grounds..."
                    )
                    Game.find_and_click_button("ok")
                else:
                    # Otherwise, all battles for the Mission has been completed. Collect the completion rewards at the end.
                    MessageLog.print_message(
                        "\n[PROVING.GROUNDS] Proving Grounds Mission has been completed."
                    )
                    Game.find_and_click_button("event")

                    # Check for friend request.
                    Game.find_and_click_button("cancel",
                                               tries=1,
                                               suppress_error=True)

                    # Check for trophy.
                    Game.find_and_click_button("close",
                                               tries=1,
                                               suppress_error=True)

                    Game.wait(2.0)
                    Game.find_and_click_button("proving_grounds_open_chest")

                    if ImageUtils.confirm_location(
                            "proving_grounds_completion_loot"):
                        MessageLog.print_message(
                            "\n[PROVING.GROUNDS] Completion rewards has been acquired."
                        )
                        runs_completed = Game.collect_loot(
                            is_completed=True, skip_popup_check=True)

                        # Reset the First Time flag so the bot can select a Summon and select the Mission again.
                        if Settings.item_amount_farmed < Settings.item_amount_to_farm:
                            ProvingGrounds._first_time = True
                    else:
                        raise ProvingGroundsException(
                            "Failed to detect the Completion Loot screen for completing this Proving Grounds mission."
                        )
        else:
            raise ProvingGroundsException(
                "Failed to arrive at the Summon Selection screen.")

        return runs_completed
    def _navigate():
        """Navigates to the specified Coop mission.

        Returns:
            None
        """
        from bot.game import Game

        MessageLog.print_message(
            f"\n[COOP] Beginning process to navigate to the mission: {Settings.mission_name}..."
        )

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        # Click the "Menu" button on the Home screen and then go to the Coop screen.
        Game.find_and_click_button("home_menu")
        Game.find_and_click_button("coop")

        if ImageUtils.confirm_location("coop"):
            # Scroll down the screen to see more of the Coop missions on smaller screens.
            MouseUtils.scroll_screen_from_home_button(-400)

            # Find the locations of all of the "Host Quest" buttons.
            host_quest_button_locations = ImageUtils.find_all(
                "coop_host_quest")

            # Select the difficulty of the mission that it is under.
            if Settings.mission_name == "H3-1 In a Dusk Dream":
                # Check if Hard difficulty is already selected. If not, make it active.
                if ImageUtils.find_button("coop_hard_selected") is None:
                    Game.find_and_click_button("coop_hard")

                MessageLog.print_message(
                    f"\n[COOP] Hard difficulty for Coop is now selected.")

                # Select the category, "Save the Oceans", which should be the 3rd category.
                MessageLog.print_message(
                    f"[COOP] Now navigating to \"{Settings.mission_name}\" for Hard difficulty."
                )
                MouseUtils.move_and_click_point(
                    host_quest_button_locations[2][0],
                    host_quest_button_locations[2][1], "coop_host_quest")

                if ImageUtils.confirm_location("coop_save_the_oceans"):
                    # Now click "In a Dusk Dream".
                    host_quests_circle_buttons = ImageUtils.find_all(
                        "coop_host_quest_circle")
                    MouseUtils.move_and_click_point(
                        host_quests_circle_buttons[0][0],
                        host_quests_circle_buttons[0][1], "coop_host_quest")

            else:
                # Check if Extra difficulty is already selected. If not, make it active.
                if ImageUtils.find_button("coop_extra_selected") is None:
                    Game.find_and_click_button("coop_extra")

                MessageLog.print_message(
                    f"\n[COOP] Extra difficulty for Coop is now selected.")

                # Make the specified EX category active. Then click the mission's button while making sure that the first mission in each category is skipped.
                if Settings.mission_name in Coop._coop_ex1_list:
                    MessageLog.print_message(
                        f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX1..."
                    )
                    MouseUtils.move_and_click_point(
                        host_quest_button_locations[0][0],
                        host_quest_button_locations[0][1], "coop_host_quest")

                    if ImageUtils.confirm_location("coop_ex1"):
                        MessageLog.print_message(
                            f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\""
                        )
                        coop_host_locations = ImageUtils.find_all(
                            "coop_host_quest_circle")
                        MouseUtils.move_and_click_point(
                            coop_host_locations[Coop._coop_ex1_list.index(
                                Settings.mission_name)][0],
                            coop_host_locations[Coop._coop_ex1_list.index(
                                Settings.mission_name)][1], "coop_host_quest")

                elif Settings.mission_name in Coop._coop_ex2_list:
                    MessageLog.print_message(
                        f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX2..."
                    )
                    MouseUtils.move_and_click_point(
                        host_quest_button_locations[1][0],
                        host_quest_button_locations[1][1], "coop_host_quest")

                    if ImageUtils.confirm_location("coop_ex2"):
                        MessageLog.print_message(
                            f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\""
                        )
                        coop_host_locations = ImageUtils.find_all(
                            "coop_host_quest_circle")
                        MouseUtils.move_and_click_point(
                            coop_host_locations[Coop._coop_ex2_list.index(
                                Settings.mission_name) + 1][0],
                            coop_host_locations[Coop._coop_ex2_list.index(
                                Settings.mission_name) + 1][1],
                            "coop_host_quest")

                elif Settings.mission_name in Coop._coop_ex3_list:
                    MessageLog.print_message(
                        f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX3."
                    )
                    MouseUtils.move_and_click_point(
                        host_quest_button_locations[2][0],
                        host_quest_button_locations[2][1], "coop_host_quest")

                    if ImageUtils.confirm_location("coop_ex3"):
                        MessageLog.print_message(
                            f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\""
                        )
                        coop_host_locations = ImageUtils.find_all(
                            "coop_host_quest_circle")
                        MouseUtils.move_and_click_point(
                            coop_host_locations[Coop._coop_ex3_list.index(
                                Settings.mission_name) + 1][0],
                            coop_host_locations[Coop._coop_ex3_list.index(
                                Settings.mission_name) + 1][1],
                            "coop_host_quest")

                elif Settings.mission_name in Coop._coop_ex4_list:
                    MessageLog.print_message(
                        f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX4."
                    )
                    MouseUtils.move_and_click_point(
                        host_quest_button_locations[3][0],
                        host_quest_button_locations[3][1], "coop_host_quest")

                    if ImageUtils.confirm_location("coop_ex4"):
                        MessageLog.print_message(
                            f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\""
                        )
                        coop_host_locations = ImageUtils.find_all(
                            "coop_host_quest_circle")
                        MouseUtils.move_and_click_point(
                            coop_host_locations[Coop._coop_ex4_list.index(
                                Settings.mission_name) + 1][0],
                            coop_host_locations[Coop._coop_ex4_list.index(
                                Settings.mission_name) + 1][1],
                            "coop_host_quest")

            # After clicking on the Coop mission, create a new Room.
            MessageLog.print_message(f"\n[COOP] Opening up a new Coop room...")
            Game.find_and_click_button("coop_post_to_crew_chat")

            # Scroll down the screen to see the "OK" button just in case of smaller screens.
            MouseUtils.scroll_screen_from_home_button(-400)
            Game.find_and_click_button("ok")

            Game.wait(1)

            # Just in case, check for the "You retreated from the raid battle" popup.
            if ImageUtils.confirm_location(
                    "you_retreated_from_the_raid_battle", tries=1):
                Game.find_and_click_button("ok")

            MessageLog.print_message(
                f"\n[COOP] Selecting a Party for Coop mission: \"{Settings.mission_name}\"."
            )
            Game.find_and_click_button("coop_select_party")

        return None
    def start(first_run: bool) -> int:
        """Starts the process to complete a run for Coop Farming Mode and returns the number of items detected.

        Args:
            first_run (bool): Flag that determines whether or not to run the navigation process again. Should be False if the Farming Mode supports the "Play Again" feature for repeated runs.

        Returns:
            (int): Number of items detected.
        """
        from bot.game import Game

        number_of_items_dropped: int = 0

        # Start the navigation process.
        if first_run:
            Coop._navigate()
        else:
            # Head back to the Coop Room.
            Game.find_and_click_button("coop_room")

            Game.wait(1)

            # Check for "Daily Missions" popup for Coop.
            if ImageUtils.confirm_location("coop_daily_missions", tries=1):
                Game.find_and_click_button("close")

            Game.wait(1)

            # Now that the bot is back at the Coop Room/Lobby, check if it closed due to time running out.
            if ImageUtils.confirm_location("coop_room_closed", tries=1):
                MessageLog.print_message(
                    "\n[COOP] Coop room has closed due to time running out.")
                return -1

            # Start the Coop Mission again.
            Game.find_and_click_button("coop_start")

            Game.wait(1)

        # Check for AP.
        Game.check_for_ap()

        # Check if the bot is at the Party Selection screen. Note that the bot is hosting solo so no support summon selection.
        if first_run and ImageUtils.confirm_location(
                "coop_without_support_summon", tries=30):
            # Select the Party.
            Game.find_party_and_start_mission(Settings.group_number,
                                              Settings.party_number)

            # Now click the "Start" button to start the Coop Mission.
            Game.find_and_click_button("coop_start")

            # Now start Combat Mode and detect any item drops.
            if CombatMode.start_combat_mode():
                number_of_items_dropped = Game.collect_loot(is_completed=True)
        elif first_run is False:
            MessageLog.print_message("\n[COOP] Starting Coop Mission again.")

            # Now start Combat Mode and detect any item drops.
            if CombatMode.start_combat_mode():
                number_of_items_dropped = Game.collect_loot(is_completed=True)
        else:
            raise CoopException(
                "Failed to arrive at the Summon Selection screen.")

        return number_of_items_dropped
Пример #22
0
    def _navigate():
        """Navigates to the specified Quest mission.

        Returns:
            None
        """
        from bot.game import Game

        MessageLog.print_message(
            f"\n[QUEST] Beginning process to navigate to the mission: {Settings.mission_name}..."
        )

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        current_location = ""
        formatted_map_name = Settings.map_name.lower().replace(" ",
                                                               "_").replace(
                                                                   "-", "_")

        # Check which island the bot is at.
        if ImageUtils.confirm_location(f"map_{formatted_map_name}", tries=3):
            MessageLog.print_message(
                f"[QUEST] Bot is currently on the correct island.")
            check_location = True
        else:
            MessageLog.print_message(
                f"[QUEST] Bot is currently not on the correct island.")
            check_location = False

            location_list = [
                "Zinkenstill", "Port Breeze Archipelago", "Valtz Duchy",
                "Auguste Isles", "Lumacie Archipelago", "Albion Citadel",
                "Mist-Shrouded Isle", "Golonzo Island", "Amalthea Island",
                "Former Capital Mephorash", "Agastia"
            ]

            while len(location_list) > 0:
                temp_map_location = location_list.pop(0)
                temp_formatted_map_location = temp_map_location.lower(
                ).replace(" ", "_").replace("-", "_")

                if ImageUtils.confirm_location(
                        f"map_{temp_formatted_map_location}", tries=1):
                    MessageLog.print_message(
                        f"[QUEST] Bot's current location is at {temp_map_location}. Now moving to {Settings.map_name}..."
                    )
                    current_location = temp_map_location
                    break

        # Once the bot has determined where it is, go to the Quest screen.
        Game.find_and_click_button("quest")

        Game.wait(1)

        # Check for the "You retreated from the raid battle" popup.
        if ImageUtils.confirm_location("you_retreated_from_the_raid_battle",
                                       tries=3):
            Game.find_and_click_button("ok")

        if ImageUtils.confirm_location("quest"):
            # If the bot is currently not at the correct island, move to it.
            if not check_location:
                # Click the "World" button.
                Game.find_and_click_button("world")

                # On the World screen, click the specified coordinates on the window to move to the island. If the island is on a different world page, switch pages as necessary.
                Quest._navigate_to_map(Settings.map_name, current_location)

                # Click "Go" on the popup after clicking on the map node.
                Game.find_and_click_button("go")

            # Grab the location of the "World" button.
            world_location = ImageUtils.find_button("world", tries=5)
            if world_location is None:
                world_location = ImageUtils.find_button("world2", tries=5)

            # Now that the bot is on the correct island and is at the Quest screen, click the correct chapter node.
            if Settings.mission_name == "Scattered Cargo":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 1 (115) node at ({world_location[0] + 97}, {world_location[1] + 97})..."
                )
                MouseUtils.move_and_click_point(world_location[0] + 97,
                                                world_location[1] + 97,
                                                "template_node")
            elif Settings.mission_name == "Lucky Charm Hunt":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 6 (122) node...")
                MouseUtils.move_and_click_point(world_location[0] + 332,
                                                world_location[1] + 16,
                                                "template_node")
            elif Settings.mission_name == "Special Op's Request":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 8 node...")
                MouseUtils.move_and_click_point(world_location[0] + 258,
                                                world_location[1] + 151,
                                                "template_node")
            elif Settings.mission_name == "Threat to the Fisheries":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 9 node...")
                MouseUtils.move_and_click_point(world_location[0] + 216,
                                                world_location[1] + 113,
                                                "template_node")
            elif Settings.mission_name == "The Fruit of Lumacie" or Settings.mission_name == "Whiff of Danger":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 13 (39/52) node...")
                MouseUtils.move_and_click_point(world_location[0] + 78,
                                                world_location[1] + 92,
                                                "template_node")
            elif Settings.mission_name == "I Challenge You!":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 17 node...")
                MouseUtils.move_and_click_point(world_location[0] + 119,
                                                world_location[1] + 121,
                                                "template_node")
            elif Settings.mission_name == "For Whom the Bell Tolls":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 22 node...")
                MouseUtils.move_and_click_point(world_location[0] + 178,
                                                world_location[1] + 33,
                                                "template_node")
            elif Settings.mission_name == "Golonzo's Battles of Old":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 25 node...")
                MouseUtils.move_and_click_point(world_location[0] + 196,
                                                world_location[1] + 5,
                                                "template_node")
            elif Settings.mission_name == "The Dungeon Diet":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 30 (44/65) node...")
                MouseUtils.move_and_click_point(world_location[0] + 242,
                                                world_location[1] + 24,
                                                "template_node")
            elif Settings.mission_name == "Trust Busting Dustup":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 36 (123) node...")
                MouseUtils.move_and_click_point(world_location[0] + 319,
                                                world_location[1] + 13,
                                                "template_node")
            elif Settings.mission_name == "Erste Kingdom Episode 4":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 70 node...")
                MouseUtils.move_and_click_point(world_location[0] + 253,
                                                world_location[1] + 136,
                                                "template_node")
            elif Settings.mission_name == "Imperial Wanderer's Soul":
                MessageLog.print_message(
                    f"\n[QUEST] Moving to Chapter 55 node...")
                MouseUtils.move_and_click_point(world_location[0] + 162,
                                                world_location[1] + 143,
                                                "template_node")

            # After being on the correct chapter node, scroll down the screen as far as possible and then click the mission to start.
            MouseUtils.scroll_screen(Settings.home_button_location[0],
                                     Settings.home_button_location[1] - 50,
                                     -1000)
            Game.find_and_click_button(Settings.mission_name.replace(" ", "_"))

            # Apply special navigation for mission "Ch. 70 - Erste Kingdom".
            if Settings.mission_name == "Erste Kingdom Episode 4":
                Game.find_and_click_button("episode_4")
                Game.find_and_click_button("ok")

        return None
    def _navigate():
        """Navigates to the specified Guild Wars mission.

        Returns:
            None
        """
        from bot.game import Game

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check = True)

        MessageLog.print_message(f"\n[GUILD.WARS] Now navigating to Guild Wars...")

        # Go to the Event by clicking on the "Menu" button and then click the very first banner.
        Game.find_and_click_button("home_menu")
        banner_locations = ImageUtils.find_all("event_banner", custom_confidence = 0.7)
        if len(banner_locations) == 0:
            banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence = 0.7)
        MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner")

        Game.wait(1.0)

        difficulty = ""
        if Settings.mission_name == "Very Hard":
            difficulty = "Very Hard"
        elif Settings.mission_name == "Extreme":
            difficulty = "Extreme"
        elif Settings.mission_name == "Extreme+":
            difficulty = "Extreme+"
        elif Settings.mission_name == "NM90":
            difficulty = "NM90"
        elif Settings.mission_name == "NM95":
            difficulty = "NM95"
        elif Settings.mission_name == "NM100":
            difficulty = "NM100"
        elif Settings.mission_name == "NM150":
            difficulty = "NM150"

        if ImageUtils.confirm_location("guild_wars"):
            # Scroll the screen down a little bit.
            MouseUtils.scroll_screen_from_home_button(-200)

            Game.wait(1.0)

            raid_battle_locations = ImageUtils.find_all("event_raid_battle")

            # Perform different navigation actions based on whether the user wants to farm meat or to farm Nightmares.
            if difficulty == "Very Hard" or difficulty == "Extreme" or difficulty == "Extreme+":
                MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm meat.")

                # Click on the banner to farm meat.
                MouseUtils.move_and_click_point(raid_battle_locations[1][0], raid_battle_locations[1][1], "event_raid_battle")

                Game.wait(1.0)

                if ImageUtils.confirm_location("guild_wars_meat"):
                    # Now click on the specified Mission to start. Also attempt at fixing the deadzone issue by looping.
                    formatted_mission_name = difficulty.replace(" ", "_")
                    tries = 10
                    MessageLog.print_message(f"[GUILD.WARS] Now hosting {difficulty} now...")

                    ap_locations = ImageUtils.find_all("ap_30")

                    if difficulty == "Very Hard":
                        MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30")
                    elif difficulty == "Extreme":
                        MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30")
                    elif difficulty == "Extreme+":
                        MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30")

                    Game.wait(3.0)

                    while ImageUtils.wait_vanish("ap_30", timeout = 3) is False:
                        if difficulty == "Very Hard":
                            MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30")
                        elif difficulty == "Extreme":
                            MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30")
                        elif difficulty == "Extreme+":
                            MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30")

                        Game.wait(3.0)

                        tries -= 1
                        if tries <= 0:
                            if difficulty == "Extreme+":
                                ImageUtils.generate_alert("You did not unlock Extreme+ yet!")
                                raise GuildWarsException("You did not unlock Extreme+ yet!")
                            else:
                                raise GuildWarsException("There appears to be a deadzone issue that the bot failed 10 times to resolve. Please refresh the page and try again.")

                    return None
            else:
                MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm Nightmares.")

                # Click on the banner to farm Nightmares.
                if difficulty != "NM150":
                    MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle")
                    if not ImageUtils.wait_vanish("guild_wars_nightmare", timeout = 10):
                        MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle")
                else:
                    MessageLog.print_message(f"\n[GUILD.WARS] Now hosting NM150 now...")
                    Game.find_and_click_button("guild_wars_nightmare_150")
                    if not ImageUtils.wait_vanish("guild_wars_nightmare_150", timeout = 10):
                        Game.find_and_click_button("guild_wars_nightmare_150")

                    if ImageUtils.confirm_location("guild_wars_nightmare"):
                        Game.find_and_click_button("start")

                if difficulty != "NM150" and ImageUtils.confirm_location("guild_wars_nightmare"):
                    nightmare_locations = ImageUtils.find_all("guild_wars_nightmares")

                    # If today is the first/second day of Guild Wars, only NM90 will be available.
                    if ImageUtils.confirm_location("guild_wars_nightmare_first_day", tries = 3):
                        MessageLog.print_message(f"[GUILD.WARS] Today is the first/second day so hosting NM90.")
                        Game.find_and_click_button("ok")

                        # Alert the user if they lack the meat to host this and stop the bot.
                        if not ImageUtils.wait_vanish("ok", timeout = 30):
                            ImageUtils.generate_alert("You do not have enough meat to host this NM90!")
                            raise GuildWarsException("You do not have enough meat to host this NM90!")

                    # If it is not the first/second day of Guild Wars, that means that other difficulties are now available.
                    elif difficulty == "NM90":
                        MessageLog.print_message(f"[GUILD.WARS] Now hosting NM90 now...")
                        MouseUtils.move_and_click_point(nightmare_locations[0][0], nightmare_locations[0][1], "guild_wars_nightmares")
                    elif difficulty == "NM95":
                        MessageLog.print_message(f"[GUILD.WARS] Now hosting NM95 now...")
                        MouseUtils.move_and_click_point(nightmare_locations[1][0], nightmare_locations[1][1], "guild_wars_nightmares")
                    elif difficulty == "NM100":
                        MessageLog.print_message(f"[GUILD.WARS] Now hosting NM100 now...")
                        MouseUtils.move_and_click_point(nightmare_locations[2][0], nightmare_locations[2][1], "guild_wars_nightmares")

                else:
                    # If there is not enough meat to host, host Extreme+ instead.
                    MessageLog.print_message(f"\n[GUILD.WARS] User lacks meat to host the Nightmare. Hosting Extreme+ instead...")

                    if difficulty != "NM150":
                        Game.find_and_click_button("close")
                    else:
                        Game.find_and_click_button("cancel")

                    # Click on the banner to farm meat.
                    Game.find_and_click_button("guild_wars_meat")

                    if ImageUtils.confirm_location("guild_wars_meat"):
                        MessageLog.print_message(f"[GUILD.WARS] Now hosting Extreme+ now...")
                        Game.find_and_click_button("guild_wars_meat_extreme+")

                        # Alert the user if they did not unlock Extreme+ and stop the bot.
                        if not ImageUtils.wait_vanish("guild_wars_meat_extreme+", timeout = 30):
                            ImageUtils.generate_alert("You did not unlock Extreme+ yet!")
                            raise GuildWarsException("You did not unlock Extreme+ yet!")

        return None
    def _choose_action() -> str:
        """Chooses the next action to take for the current Arcarum expedition.

        Returns:
            (str): The action to take next.
        """
        from bot.game import Game

        # Determine what action to take.
        MessageLog.print_message(
            f"\n[ARCARUM] Now determining what action to take...")

        # Wait a second in case the "Do or Die" animation plays.
        Game.wait(1)

        tries = 3
        while tries > 0:
            # Prioritise any enemies/chests/thorns that are available on the current node.
            arcarum_actions = ImageUtils.find_all("arcarum_action")
            if len(arcarum_actions) > 0:
                MouseUtils.move_and_click_point(arcarum_actions[0][0],
                                                arcarum_actions[0][1],
                                                "arcarum_action")

                Game.wait(2)

                Game.check_for_captcha()

                if ImageUtils.confirm_location("arcarum_party_selection",
                                               tries=1):
                    return "Combat"
                elif Game.find_and_click_button("ok", tries=1):
                    return "Claimed Treasure/Keythorn"
                else:
                    return "Claimed Spirethorn/No Action"

            # Clear any detected Treasure popup after claiming a chest.
            MessageLog.print_message(
                f"[ARCARUM] No action found for the current node. Looking for Treasure popup..."
            )
            if ImageUtils.confirm_location("arcarum_treasure", tries=1):
                Game.find_and_click_button("ok")
                return "Claimed Treasure"

            # Next, determine if there is a available node to move to. Any bound monsters should have been destroyed by now.
            MessageLog.print_message(
                f"[ARCARUM] No Treasure popup detected. Looking for an available node to move to..."
            )
            if Game.find_and_click_button("arcarum_node", tries=1):
                Game.wait(1)
                return "Navigating"

            # Check if a Arcarum boss has appeared. This is after checking for available actions and before searching for a node to move to avoid false positives.
            if Arcarum._check_for_boss():
                return "Boss Detected"

            # Next, attempt to navigate to a node that is occupied by mob(s).
            MessageLog.print_message(
                f"[ARCARUM] No available node to move to. Looking for nodes with mobs on them..."
            )
            if Game.find_and_click_button(
                    "arcarum_mob", tries=1) or Game.find_and_click_button(
                        "arcarum_red_mob", tries=1):
                Game.wait(1)
                return "Navigating"

            # If all else fails, see if there are any unclaimed chests, like the ones spawned by a random special event that spawns chests on all nodes.
            MessageLog.print_message(
                f"[ARCARUM] No nodes with mobs on them. Looking for nodes with chests on them..."
            )
            if Game.find_and_click_button(
                    "arcarum_silver_chest",
                    tries=1) or Game.find_and_click_button(
                        "arcarum_gold_chest", tries=1):
                Game.wait(1)
                return "Navigating"

            tries -= 1

        MessageLog.print_message(
            f"[ARCARUM] No action can be taken. Defaulting to moving to the next area."
        )
        return "Next Area"
    def _navigate_token_drawboxes():
        """Navigates to the specified Event (Token Drawboxes) mission.

        Returns:
            None
        """
        from bot.game import Game

        MessageLog.print_message(
            f"[EVENT.TOKEN.DRAWBOXES] Now beginning process to navigate to the mission: {Settings.mission_name}..."
        )

        # Go to the Home screen.
        Game.go_back_home(confirm_location_check=True)

        # Go to the Event by clicking on the "Menu" button and then click the very first banner.
        Game.find_and_click_button("home_menu")
        banner_locations = ImageUtils.find_all("event_banner",
                                               custom_confidence=0.7)
        if len(banner_locations) == 0:
            banner_locations = ImageUtils.find_all("event_banner_blue",
                                                   custom_confidence=0.7)
            if len(banner_locations) == 0:
                raise EventException("Failed to find the Event banner.")
        MouseUtils.move_and_click_point(banner_locations[0][0],
                                        banner_locations[0][1], "event_banner")

        Game.wait(1)

        # Check and click away the "Daily Missions" popup.
        if ImageUtils.confirm_location("event_daily_missions", tries=1):
            MessageLog.print_message(
                f"\n[EVENT.TOKEN.DRAWBOXES] Detected \"Daily Missions\" popup. Clicking it away..."
            )
            Game.find_and_click_button("close")

        # Remove the difficulty prefix from the mission name.
        difficulty = ""
        formatted_mission_name = ""
        if Settings.mission_name.find("VH ") == 0:
            difficulty = "Very Hard"
            formatted_mission_name = Settings.mission_name[3:]
        elif Settings.mission_name.find("EX ") == 0:
            difficulty = "Extreme"
            formatted_mission_name = Settings.mission_name[3:]
        elif Settings.mission_name.find("EX+ ") == 0:
            difficulty = "Extreme+"
            formatted_mission_name = Settings.mission_name[4:]
        elif Settings.mission_name.find("IM ") == 0:
            difficulty = "Impossible"
            formatted_mission_name = Settings.mission_name[3:]

        # Scroll down the screen a little bit for this UI layout that has Token Drawboxes.
        MouseUtils.scroll_screen_from_home_button(-200)

        if formatted_mission_name == "Event Quest":
            MessageLog.print_message(
                f"[EVENT.TOKEN.DRAWBOXES] Now hosting Event Quest...")
            Game.find_and_click_button("event_quests")

            Game.wait(1)

            # Find all the round "Play" buttons.
            quest_play_locations = ImageUtils.find_all("play_round_button")

            # Only Extreme and Extreme+ difficulty is supported for farming efficiency.
            if difficulty == "Extreme":
                MouseUtils.move_and_click_point(quest_play_locations[3][0],
                                                quest_play_locations[3][1],
                                                "play_round_button")
            elif difficulty == "Extreme+":
                MouseUtils.move_and_click_point(quest_play_locations[4][0],
                                                quest_play_locations[4][1],
                                                "play_round_button")
        elif formatted_mission_name == "Event Raid":
            # Bring up the "Raid Battle" popup. Then scroll down the screen a bit for screens less than 1440p to see the entire popup.
            MessageLog.print_message(
                f"[EVENT.TOKEN.DRAWBOXES] Now hosting Event Raid...")
            if not Game.find_and_click_button("event_raid_battle"):
                ImageUtils.generate_alert(
                    "Failed to detect Token Drawbox layout for this Event. Are you sure this Event has Token Drawboxes? If not, switch to \"Event\" Farming Mode."
                )
                raise EventException(
                    "Failed to detect Token Drawbox layout for this Event. Are you sure this Event has Token Drawboxes? If not, switch to \"Event\" Farming Mode."
                )
            MouseUtils.scroll_screen_from_home_button(-200)

            Game.wait(1)

            ap_locations = ImageUtils.find_all("ap")

            if difficulty == "Very Hard":
                MouseUtils.move_and_click_point(ap_locations[0][0],
                                                ap_locations[0][1], "ap")
                if not ImageUtils.wait_vanish("close", timeout=10):
                    MouseUtils.move_and_click_point(ap_locations[0][0],
                                                    ap_locations[0][1], "ap")
                else:
                    return None
            elif difficulty == "Extreme":
                MouseUtils.move_and_click_point(ap_locations[1][0],
                                                ap_locations[1][1], "ap")
                if not ImageUtils.wait_vanish("close", timeout=10):
                    MouseUtils.move_and_click_point(ap_locations[1][0],
                                                    ap_locations[1][1], "ap")
                else:
                    return None
            elif difficulty == "Impossible":
                MouseUtils.move_and_click_point(ap_locations[2][0],
                                                ap_locations[2][1], "ap")
                if not ImageUtils.wait_vanish("close", timeout=10):
                    MouseUtils.move_and_click_point(ap_locations[2][0],
                                                    ap_locations[2][1], "ap")
                else:
                    return None

            # If the user does not have enough Treasures to host a Extreme or an Impossible Raid, host a Very Hard Raid instead.
            MessageLog.print_message(
                f"[EVENT.TOKEN.DRAWBOXES] Not enough materials to host {difficulty}. Hosting Very Hard instead..."
            )
            MouseUtils.move_and_click_point(ap_locations[0][0],
                                            ap_locations[0][1], "ap")
            if not ImageUtils.wait_vanish("close", timeout=10):
                MouseUtils.move_and_click_point(ap_locations[0][0],
                                                ap_locations[0][1], "ap")

        return None
Пример #26
0
    def _join_raid() -> bool:
        """Start the process to fetch a valid room code and join it.

        Returns:
            (bool): True if the bot arrived at the Summon Selection screen.
        """
        from bot.game import Game

        recovery_time = 15

        # Make preparations for farming raids by saving the location of the "Join Room" button and the "Room Code" textbox.
        join_room_button = ImageUtils.find_button("join_a_room")
        room_code_textbox = (join_room_button[0] - 185, join_room_button[1])

        # Loop and try to join a raid. If none of the room codes worked, wait before trying again with a new set of room codes for a maximum of 10 tries.
        tries = 10
        while tries > 0:
            room_code_tries = 5
            while room_code_tries > 0:
                # Attempt to find a room code.
                room_code = TwitterRoomFinder.get_room_code()

                if room_code != "":
                    # Select the "Room Code" textbox and then clear all text from it.
                    MouseUtils.move_and_click_point(
                        room_code_textbox[0],
                        room_code_textbox[1],
                        "template_room_code_textbox",
                        mouse_clicks=2)
                    MouseUtils.clear_textbox()

                    # Copy the room code to the clipboard and then paste it into the "Room Code" textbox.
                    MouseUtils.copy_to_clipboard(room_code)
                    MouseUtils.paste_from_clipboard()

                    # Now click on the "Join Room" button.
                    MouseUtils.move_and_click_point(join_room_button[0],
                                                    join_room_button[1],
                                                    "join_a_room")

                    # If the room code is valid and the raid is able to be joined, break out and head to the Summon Selection screen.
                    if Game.find_and_click_button(
                            "ok", suppress_error=True) is False:
                        # Check for EP.
                        Game.check_for_ep()

                        MessageLog.print_message(
                            f"[SUCCESS] Joining {room_code} was successful.")
                        Raid._raids_joined += 1

                        return ImageUtils.confirm_location("select_a_summon")
                    elif Game.check_for_pending() is False:
                        MessageLog.print_message(
                            f"[WARNING] {room_code} already ended or invalid.")
                    else:
                        # Move from the Home screen back to the Backup Requests screen after clearing out all the Pending Battles.
                        Game.find_and_click_button("quest")
                        Game.find_and_click_button("raid")
                        Game.find_and_click_button("enter_id")

                if Settings.enable_no_timeout is False:
                    room_code_tries -= 1

                Game.wait(1)

            tries -= 1
            MessageLog.print_message(
                f"\n[WARNING] Could not find any valid room codes. \nWaiting {recovery_time} seconds and then trying again with {tries} tries left before exiting."
            )
            Game.wait(recovery_time)

        raise RaidException(
            "Failed to find any valid room codes for 10 total times.")
    def _navigate():
        """Navigates to the specified Event mission.

        Returns:
            None
        """
        from bot.game import Game

        # Switch over to the navigation logic for Event (Token Drawboxes) if needed.
        if Settings.farming_mode == "Event (Token Drawboxes)":
            Event._navigate_token_drawboxes()
        else:
            MessageLog.print_message(
                f"[EVENT] Now beginning process to navigate to the mission: {Settings.mission_name}..."
            )

            # Go to the Home screen.
            Game.go_back_home(confirm_location_check=True)

            Game.find_and_click_button("quest")

            Game.wait(1)

            # Check for the "You retreated from the raid battle" popup.
            if ImageUtils.confirm_location(
                    "you_retreated_from_the_raid_battle", tries=3):
                Game.find_and_click_button("ok")

            # Go to the Special screen.
            Game.find_and_click_button("special")
            Game.wait(3.0)

            Game.find_and_click_button("special_event")

            # Remove the difficulty prefix from the mission name.
            difficulty = ""
            formatted_mission_name = ""
            if Settings.mission_name.find("N ") == 0:
                difficulty = "Normal"
                formatted_mission_name = Settings.mission_name[2:]
            elif Settings.mission_name.find("H ") == 0:
                difficulty = "Hard"
                formatted_mission_name = Settings.mission_name[2:]
            elif Settings.mission_name.find("VH ") == 0:
                difficulty = "Very Hard"
                formatted_mission_name = Settings.mission_name[3:]
            elif Settings.mission_name.find("EX ") == 0:
                difficulty = "Extreme"
                formatted_mission_name = Settings.mission_name[3:]
            elif Settings.mission_name.find("EX+ ") == 0:
                difficulty = "Extreme+"
                formatted_mission_name = Settings.mission_name[4:]

            if ImageUtils.confirm_location("special"):
                # Check to see if the user already has a Nightmare available.
                nightmare_is_available = 0
                if ImageUtils.find_button("event_nightmare",
                                          tries=1) is not None:
                    nightmare_is_available = 1

                # Find all the "Select" buttons.
                select_button_locations = ImageUtils.find_all("select")
                if Settings.enable_event_location_incrementation_by_one:
                    position = 1
                else:
                    position = 0

                # Select the Event Quest or Event Raid. Additionally, offset the locations by 1 if there is a Nightmare available.
                try:
                    if formatted_mission_name == "Event Quest":
                        MessageLog.print_message(
                            f"[EVENT] Now hosting Event Quest...")
                        MouseUtils.move_and_click_point(
                            select_button_locations[position +
                                                    nightmare_is_available][0],
                            select_button_locations[position +
                                                    nightmare_is_available][1],
                            "select")
                    elif formatted_mission_name == "Event Raid":
                        MessageLog.print_message(
                            f"[EVENT] Now hosting Event Raid...")
                        MouseUtils.move_and_click_point(
                            select_button_locations[(position + 1) +
                                                    nightmare_is_available][0],
                            select_button_locations[(position + 1) +
                                                    nightmare_is_available][1],
                            "play_round_button")
                except IndexError as e:
                    MessageLog.print_message(
                        f"\n[ERROR] Turn on/off the 'Enable Incrementation of Location by 1' and try again."
                    )
                    raise IndexError(e)

                Game.wait(1)

                # Find all the round "Play" buttons.
                round_play_button_locations = ImageUtils.find_all(
                    "play_round_button")

                # If Extreme+ was selected and only 3 locations were found for the play_round_button, that means Extreme+ is not available.
                if len(round_play_button_locations
                       ) == 3 and difficulty == "Extreme+":
                    MessageLog.print_message(
                        f"[EVENT] Extreme+ was selected but it seems it is not available. Defaulting to Extreme difficulty..."
                    )
                    difficulty = "Extreme"

                # Now select the chosen difficulty.
                if difficulty == "Very Hard":
                    MouseUtils.move_and_click_point(
                        round_play_button_locations[0][0],
                        round_play_button_locations[0][1], "play_round_button")
                elif difficulty == "Extreme":
                    MouseUtils.move_and_click_point(
                        round_play_button_locations[1][0],
                        round_play_button_locations[1][1], "play_round_button")
                elif difficulty == "Extreme+":
                    MouseUtils.move_and_click_point(
                        round_play_button_locations[2][0],
                        round_play_button_locations[2][1], "play_round_button")
            else:
                raise EventException(
                    "Failed to arrive at the Special Quest screen.")

        return None
 def test_twitter_connection(self):
     result: bool = TwitterRoomFinder.test_connection()
     Game.wait(5)
     self.assertTrue(result)
     TwitterRoomFinder.disconnect()
     return None