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 _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
示例#3
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
    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 _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
示例#6
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
    def check_for_xeno_clash_nightmare():
        """Checks for Xeno Clash Nightmare and if it appears and the user enabled it in user settings, start it.

        Returns:
            (bool): Return True if Xeno Clash 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 Xeno Clash 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[XENO] Skippable Xeno Clash 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[XENO] Detected Xeno Clash Nightmare. Starting it now...")

                MessageLog.print_message("\n********************************************************************************")
                MessageLog.print_message("********************************************************************************")
                MessageLog.print_message(f"[XENO] Xeno Clash Nightmare")
                MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Summon Elements: {Settings.nightmare_summon_elements_list}")
                MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Summons: {Settings.nightmare_summon_list}")
                MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Group Number: {Settings.nightmare_group_number}")
                MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Party Number: {Settings.nightmare_party_number}")
                MessageLog.print_message(f"[XENO] Xeno Clash 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)

                # Select only the first Nightmare.
                play_round_buttons = ImageUtils.find_all("play_round_button")
                MouseUtils.move_and_click_point(play_round_buttons[0][0], play_round_buttons[0][1], "play_round_button")

                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 Xeno Clash 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[XENO] Skippable Xeno Clash 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[XENO] Xeno Clash Nightmare detected but user opted to not run it. Moving on...")
                Game.find_and_click_button("close")
        else:
            MessageLog.print_message("\n[XENO] No Xeno Clash Nightmare detected. Moving on...")

        return False
    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
示例#9
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 _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 _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"