Пример #1
0
    def start(first_run: bool) -> int:
        """Starts the process to complete a run for Raid 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:
            Raid._navigate()
        else:
            # Check for Pending Battles and then perform navigation again.
            Game.check_for_pending()
            Raid._navigate()

        # Check for EP.
        Game.check_for_ep()

        # Check if the bot is at the Summon Selection screen.
        if ImageUtils.confirm_location("select_a_summon", tries=30):
            summon_check = Game.select_summon(Settings.summon_list,
                                              Settings.summon_element_list)

            if summon_check:
                # Select the Party.
                if Game.find_party_and_start_mission(Settings.group_number,
                                                     Settings.party_number):
                    # Handle the rare case where joining the Raid after selecting the Summon and Party led the bot to the Quest Results screen with no loot to collect.
                    if ImageUtils.confirm_location("no_loot", tries=2):
                        MessageLog.print_message(
                            "\n[RAID] Seems that the Raid just ended. Moving back to the Home screen and joining another Raid..."
                        )
                    elif CombatMode.start_combat_mode():
                        number_of_items_dropped = Game.collect_loot(
                            is_completed=True)
                else:
                    MessageLog.print_message(
                        "\n[RAID] Seems that the Raid ended before the bot was able to join. Now looking for another Raid to join..."
                    )
        else:
            raise RaidException(
                "Failed to arrive at the Summon Selection screen.")

        return number_of_items_dropped
Пример #2
0
    def start(first_run: bool) -> int:
        """Starts the process to complete a run for Quest 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:
            Quest._navigate()
        elif Game.find_and_click_button("play_again"):
            Game.check_for_popups()
        else:
            # If the bot cannot find the "Play Again" button, check for Pending Battles and then perform navigation again.
            Game.check_for_pending()
            Quest._navigate()

        # Check for AP.
        Game.check_for_ap()

        # Check if the bot is at the Summon Selection screen.
        if ImageUtils.confirm_location("select_a_summon", tries=30):
            summon_check = Game.select_summon(Settings.summon_list,
                                              Settings.summon_element_list)
            if summon_check:
                # Select the Party.
                Game.find_party_and_start_mission(Settings.group_number,
                                                  Settings.party_number)

                # Close the "Item Picked Up" popup.
                if ImageUtils.confirm_location("items_picked_up"):
                    Game.find_and_click_button("ok")

                # 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 QuestException(
                "Failed to arrive at the Summon Selection screen.")

        return number_of_items_dropped
Пример #3
0
    def start() -> int:
        """Starts the process of completing a generic setup that supports the 'Play Again' logic.

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

        runs_completed = 0

        MessageLog.print_message(
            f"\n[GENERIC] Now checking for run eligibility...")

        # Bot can start either at the Combat screen with the "Attack" button visible or the Loot Collection screen with the "Play Again" button visible.
        if ImageUtils.find_button("attack", tries=5):
            MessageLog.print_message(
                f"[GENERIC] Bot is at the Combat screen. Starting Combat Mode now..."
            )
            if CombatMode.start_combat_mode():
                runs_completed = Game.collect_loot(is_completed=True)
        else:
            MessageLog.print_message(
                f"[GENERIC] Bot is not at the Combat screen. Checking for the Loot Collection screen now..."
            )

            # Press the "Play Again" button if necessary, otherwise start Combat Mode.
            if Game.find_and_click_button("play_again"):
                Game.check_for_popups()
            else:
                raise GenericException(
                    "Failed to detect the 'Play Again' button. Bot can start either at the Combat screen with the 'Attack' button visible or the Loot Collection screen with the 'Play Again' button visible.."
                )

            # Check for AP.
            Game.check_for_ap()

            # Check if the bot is at the Summon Selection screen.
            if ImageUtils.confirm_location("select_a_summon", tries=30):
                summon_check = Game.select_summon(Settings.summon_list,
                                                  Settings.summon_element_list)
                if summon_check:
                    # Do not select party and just commence the mission.
                    MessageLog.print_message(
                        f"[GENERIC] Skipping party selection and immediately commencing mission..."
                    )
                    if Game.find_and_click_button("ok", tries=10):
                        # Now start Combat Mode and detect any item drops.
                        if CombatMode.start_combat_mode():
                            runs_completed = Game.collect_loot(
                                is_completed=True)
                    else:
                        raise GenericException(
                            "Failed to skip party selection.")
            else:
                raise GenericException(
                    "Failed to arrive at the Summon Selection screen.")

        return runs_completed
    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
Пример #5
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.")
    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
    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
Пример #8
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)
Пример #9
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 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 _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 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
Пример #13
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
Пример #14
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 _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 test_item_detection3(self):
     self.assertTrue(ImageUtils.confirm_location("loot_collected"))
     result = ImageUtils.find_farmed_items("Sagittarius Omega Anima",
                                           take_screenshot=False)
     self.assertEqual(result, 4)
     return None
 def test_item_detection2(self):
     self.assertTrue(ImageUtils.confirm_location("loot_collected"))
     result = ImageUtils.find_farmed_items("Wind Orb",
                                           take_screenshot=False)
     self.assertEqual(result, 1)
     return None
    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 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
Пример #20
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 _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
    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
    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():
        """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