def _navigate(): """Navigates to the specified Proving Grounds mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check=True) MessageLog.print_message( f"\n[PROVING.GROUNDS] Now navigating to Proving Grounds...") # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") banner_locations = ImageUtils.find_all("event_banner", custom_confidence=0.7) if len(banner_locations) == 0: banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence=0.7) if len(banner_locations) == 0: raise ProvingGroundsException( "Failed to find the Event banner.") MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner") Game.wait(1) difficulty = "" if Settings.mission_name == "Extreme": difficulty = "Extreme" elif Settings.mission_name == "Extreme+": difficulty = "Extreme+" # Select the difficulty. if ImageUtils.confirm_location("proving_grounds"): if Game.find_and_click_button("proving_grounds_missions"): difficulty_button_locations = ImageUtils.find_all( "play_round_button") if difficulty == "Extreme": MouseUtils.move_and_click_point( difficulty_button_locations[1][0], difficulty_button_locations[1][1], "play_round_button") elif difficulty == "Extreme+": MouseUtils.move_and_click_point( difficulty_button_locations[2][0], difficulty_button_locations[2][1], "play_round_button") # After the difficulty has been selected, click "Play" to land the bot at the Proving Grounds' Summon Selection screen. Game.find_and_click_button("play") else: raise ProvingGroundsException( "Failed to arrive at the main screen for Proving Grounds.") return None
def _navigate(): """Navigates to the specified Xeno Clash mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check = True) MessageLog.print_message(f"\n[XENO.CLASH] Now navigating to Xeno Clash...") # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") event_banner_locations = ImageUtils.find_all("event_banner", custom_confidence = 0.7) if len(event_banner_locations) == 0: event_banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence = 0.7) MouseUtils.move_and_click_point(event_banner_locations[0][0], event_banner_locations[0][1], "event_banner") Game.wait(2.0) if Game.find_and_click_button("xeno_special", tries = 30): # Check to see if the user already has a Nightmare available. nightmare_is_available = 0 if ImageUtils.find_button("event_nightmare", tries = 1) is not None: nightmare_is_available = 1 # Find all the "Select" buttons. select_button_locations = ImageUtils.find_all("select") if Settings.mission_name == "Xeno Clash Extreme": MessageLog.print_message(f"[XENO.CLASH] Now hosting Xeno Clash Extreme...") MouseUtils.move_and_click_point(select_button_locations[1 + nightmare_is_available][0], select_button_locations[1 + nightmare_is_available][1], "select") difficulty_button_locations = ImageUtils.find_all("play_round_button") MouseUtils.move_and_click_point(difficulty_button_locations[0][0], difficulty_button_locations[0][1], "play_round_button") elif Settings.mission_name == "Xeno Clash Raid": MessageLog.print_message(f"[XENO.CLASH] Now hosting Xeno Clash Raid...") MouseUtils.move_and_click_point(select_button_locations[2 + nightmare_is_available][0], select_button_locations[2 + nightmare_is_available][1], "select") Game.wait(2.0) Game.find_and_click_button("play") else: raise(XenoClashException("Failed to open the Xeno Special tab.")) return None
def _check_for_joined_raids(): """Check and update the number of raids currently joined. Returns: None """ from bot.game import Game # Find out the number of currently joined raids. Game.wait(1) joined_locations = ImageUtils.find_all("joined") if joined_locations is not None: Raid._raids_joined = len(joined_locations) MessageLog.print_message( f"\n[RAID] There are currently {Raid._raids_joined} raids joined." ) return None
def _navigate(): """Navigates to the specified Event mission. Returns: None """ from bot.game import Game # Switch over to the navigation logic for Event (Token Drawboxes) if needed. if Settings.farming_mode == "Event (Token Drawboxes)": Event._navigate_token_drawboxes() else: MessageLog.print_message( f"[EVENT] Now beginning process to navigate to the mission: {Settings.mission_name}..." ) # Go to the Home screen. Game.go_back_home(confirm_location_check=True) Game.find_and_click_button("quest") Game.wait(1) # Check for the "You retreated from the raid battle" popup. if ImageUtils.confirm_location( "you_retreated_from_the_raid_battle", tries=3): Game.find_and_click_button("ok") # Go to the Special screen. Game.find_and_click_button("special") Game.wait(3.0) Game.find_and_click_button("special_event") # Remove the difficulty prefix from the mission name. difficulty = "" formatted_mission_name = "" if Settings.mission_name.find("N ") == 0: difficulty = "Normal" formatted_mission_name = Settings.mission_name[2:] elif Settings.mission_name.find("H ") == 0: difficulty = "Hard" formatted_mission_name = Settings.mission_name[2:] elif Settings.mission_name.find("VH ") == 0: difficulty = "Very Hard" formatted_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX ") == 0: difficulty = "Extreme" formatted_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX+ ") == 0: difficulty = "Extreme+" formatted_mission_name = Settings.mission_name[4:] if ImageUtils.confirm_location("special"): # Check to see if the user already has a Nightmare available. nightmare_is_available = 0 if ImageUtils.find_button("event_nightmare", tries=1) is not None: nightmare_is_available = 1 # Find all the "Select" buttons. select_button_locations = ImageUtils.find_all("select") if Settings.enable_event_location_incrementation_by_one: position = 1 else: position = 0 # Select the Event Quest or Event Raid. Additionally, offset the locations by 1 if there is a Nightmare available. try: if formatted_mission_name == "Event Quest": MessageLog.print_message( f"[EVENT] Now hosting Event Quest...") MouseUtils.move_and_click_point( select_button_locations[position + nightmare_is_available][0], select_button_locations[position + nightmare_is_available][1], "select") elif formatted_mission_name == "Event Raid": MessageLog.print_message( f"[EVENT] Now hosting Event Raid...") MouseUtils.move_and_click_point( select_button_locations[(position + 1) + nightmare_is_available][0], select_button_locations[(position + 1) + nightmare_is_available][1], "play_round_button") except IndexError as e: MessageLog.print_message( f"\n[ERROR] Turn on/off the 'Enable Incrementation of Location by 1' and try again." ) raise IndexError(e) Game.wait(1) # Find all the round "Play" buttons. round_play_button_locations = ImageUtils.find_all( "play_round_button") # If Extreme+ was selected and only 3 locations were found for the play_round_button, that means Extreme+ is not available. if len(round_play_button_locations ) == 3 and difficulty == "Extreme+": MessageLog.print_message( f"[EVENT] Extreme+ was selected but it seems it is not available. Defaulting to Extreme difficulty..." ) difficulty = "Extreme" # Now select the chosen difficulty. if difficulty == "Very Hard": MouseUtils.move_and_click_point( round_play_button_locations[0][0], round_play_button_locations[0][1], "play_round_button") elif difficulty == "Extreme": MouseUtils.move_and_click_point( round_play_button_locations[1][0], round_play_button_locations[1][1], "play_round_button") elif difficulty == "Extreme+": MouseUtils.move_and_click_point( round_play_button_locations[2][0], round_play_button_locations[2][1], "play_round_button") else: raise EventException( "Failed to arrive at the Special Quest screen.") return None
def _navigate_token_drawboxes(): """Navigates to the specified Event (Token Drawboxes) mission. Returns: None """ from bot.game import Game MessageLog.print_message( f"[EVENT.TOKEN.DRAWBOXES] Now beginning process to navigate to the mission: {Settings.mission_name}..." ) # Go to the Home screen. Game.go_back_home(confirm_location_check=True) # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") banner_locations = ImageUtils.find_all("event_banner", custom_confidence=0.7) if len(banner_locations) == 0: banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence=0.7) if len(banner_locations) == 0: raise EventException("Failed to find the Event banner.") MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner") Game.wait(1) # Check and click away the "Daily Missions" popup. if ImageUtils.confirm_location("event_daily_missions", tries=1): MessageLog.print_message( f"\n[EVENT.TOKEN.DRAWBOXES] Detected \"Daily Missions\" popup. Clicking it away..." ) Game.find_and_click_button("close") # Remove the difficulty prefix from the mission name. difficulty = "" formatted_mission_name = "" if Settings.mission_name.find("VH ") == 0: difficulty = "Very Hard" formatted_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX ") == 0: difficulty = "Extreme" formatted_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX+ ") == 0: difficulty = "Extreme+" formatted_mission_name = Settings.mission_name[4:] elif Settings.mission_name.find("IM ") == 0: difficulty = "Impossible" formatted_mission_name = Settings.mission_name[3:] # Scroll down the screen a little bit for this UI layout that has Token Drawboxes. MouseUtils.scroll_screen_from_home_button(-200) if formatted_mission_name == "Event Quest": MessageLog.print_message( f"[EVENT.TOKEN.DRAWBOXES] Now hosting Event Quest...") Game.find_and_click_button("event_quests") Game.wait(1) # Find all the round "Play" buttons. quest_play_locations = ImageUtils.find_all("play_round_button") # Only Extreme and Extreme+ difficulty is supported for farming efficiency. if difficulty == "Extreme": MouseUtils.move_and_click_point(quest_play_locations[3][0], quest_play_locations[3][1], "play_round_button") elif difficulty == "Extreme+": MouseUtils.move_and_click_point(quest_play_locations[4][0], quest_play_locations[4][1], "play_round_button") elif formatted_mission_name == "Event Raid": # Bring up the "Raid Battle" popup. Then scroll down the screen a bit for screens less than 1440p to see the entire popup. MessageLog.print_message( f"[EVENT.TOKEN.DRAWBOXES] Now hosting Event Raid...") if not Game.find_and_click_button("event_raid_battle"): ImageUtils.generate_alert( "Failed to detect Token Drawbox layout for this Event. Are you sure this Event has Token Drawboxes? If not, switch to \"Event\" Farming Mode." ) raise EventException( "Failed to detect Token Drawbox layout for this Event. Are you sure this Event has Token Drawboxes? If not, switch to \"Event\" Farming Mode." ) MouseUtils.scroll_screen_from_home_button(-200) Game.wait(1) ap_locations = ImageUtils.find_all("ap") if difficulty == "Very Hard": MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap") if not ImageUtils.wait_vanish("close", timeout=10): MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap") else: return None elif difficulty == "Extreme": MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap") if not ImageUtils.wait_vanish("close", timeout=10): MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap") else: return None elif difficulty == "Impossible": MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap") if not ImageUtils.wait_vanish("close", timeout=10): MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap") else: return None # If the user does not have enough Treasures to host a Extreme or an Impossible Raid, host a Very Hard Raid instead. MessageLog.print_message( f"[EVENT.TOKEN.DRAWBOXES] Not enough materials to host {difficulty}. Hosting Very Hard instead..." ) MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap") if not ImageUtils.wait_vanish("close", timeout=10): MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap") return None
def _navigate(): """Navigates to the specified Special mission. Returns: None """ from bot.game import Game MessageLog.print_message( f"\n[SPECIAL] Beginning process to navigate to the mission: {Settings.mission_name}..." ) # Go to the Home screen. Game.go_back_home(confirm_location_check=True) # Go to the Quest screen. Game.find_and_click_button("quest", suppress_error=True) # Check for the "You retreated from the raid battle" popup. Game.wait(1) if ImageUtils.confirm_location("you_retreated_from_the_raid_battle", tries=1): Game.find_and_click_button("ok") if ImageUtils.confirm_location("quest"): # Go to the Special screen. Game.find_and_click_button("special") # Remove the difficulty prefix from the mission name. difficulty = "" if Settings.mission_name.find("N ") == 0: difficulty = "Normal" formatted_mission_name = Settings.mission_name[2:] elif Settings.mission_name.find("H ") == 0: difficulty = "Hard" formatted_mission_name = Settings.mission_name[2:] elif Settings.mission_name.find("VH ") == 0: difficulty = "Very Hard" formatted_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX ") == 0: difficulty = "Extreme" formatted_mission_name = Settings.mission_name[3:] else: formatted_mission_name = Settings.mission_name if ImageUtils.confirm_location("special"): tries = 2 # Try to select the specified Special mission for a number of tries. while tries != 0: # Scroll the screen down if its any of the Special Quests that are more towards the bottom of the page to alleviate problems for smaller screens. if Settings.map_name != "Campaign-Exclusive Quest" and Settings.map_name != "Basic Treasure Quests" and Settings.map_name != "Shiny Slime Search!" and Settings.map_name != "Six Dragon Trial": MouseUtils.scroll_screen_from_home_button(-500) mission_select_button = ImageUtils.find_button( Settings.map_name.lower().replace(" ", "_").replace( "-", "_")) if mission_select_button is not None: MessageLog.print_message( f"[SPECIAL] Navigating to {Settings.map_name}...") # Move to the specified Special by clicking its "Select" button. special_quest_select_button = ( mission_select_button[0] + 145, mission_select_button[1] + 75) MouseUtils.move_and_click_point( special_quest_select_button[0], special_quest_select_button[1], "select") Game.wait(1) if Settings.map_name == "Basic Treasure Quests": locations = ImageUtils.find_all( "play_round_button") if formatted_mission_name == "Scarlet Trial": # Navigate to Scarlet Trial. MessageLog.print_message( f"[SPECIAL] Selecting Scarlet Trial...") MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif formatted_mission_name == "Cerulean Trial": # Navigate to Cerulean Trial. MessageLog.print_message( f"[SPECIAL] Selecting Cerulean Trial...") MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif formatted_mission_name == "Violet Trial": # Navigate to Violet Trial. MessageLog.print_message( f"[SPECIAL] Selecting Violet Trial...") MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") Game.wait(1) # Now start the Trial with the specified difficulty. MessageLog.print_message( f"[SPECIAL] Now navigating to {difficulty}...") locations = ImageUtils.find_all( "play_round_button") if difficulty == "Normal": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif difficulty == "Hard": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif difficulty == "Very Hard": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif Settings.map_name == "Shiny Slime Search!": # Start up the Shiny Slime Search! mission by selecting its difficulty. MessageLog.print_message( f"[SPECIAL] Selecting {difficulty} Shiny Slime Search!..." ) locations = ImageUtils.find_all( "play_round_button") if difficulty == "Normal": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif difficulty == "Hard": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif difficulty == "Very Hard": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif Settings.map_name == "Six Dragon Trial": # Start up the Six Dragon Trial mission by selecting its difficulty. MessageLog.print_message( f"[SPECIAL] Selecting {difficulty} Six Dragon Trial..." ) locations = ImageUtils.find_all( "play_round_button") if difficulty == "Normal": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif difficulty == "Hard": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif difficulty == "Very Hard": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif Settings.map_name == "Elemental Treasure Quests": # Start up the specified Elemental Treasure Quest mission. MessageLog.print_message( f"[SPECIAL] Selecting {Settings.mission_name}..." ) locations = ImageUtils.find_all( "play_round_button") if formatted_mission_name == "The Hellfire Trial": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif formatted_mission_name == "The Deluge Trial": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif formatted_mission_name == "The Wasteland Trial": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif formatted_mission_name == "The Typhoon Trial": MouseUtils.move_and_click_point( locations[3][0], locations[3][1], "play_round_button") elif formatted_mission_name == "The Aurora Trial": MouseUtils.move_and_click_point( locations[4][0], locations[4][1], "play_round_button") elif formatted_mission_name == "The Oblivion Trial": MouseUtils.move_and_click_point( locations[5][0], locations[5][1], "play_round_button") elif Settings.map_name == "Showdowns": locations = ImageUtils.find_all( "play_round_button") if formatted_mission_name == "Ifrit Showdown": # Navigate to Ifrit Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Ifrit Showdown...") MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif formatted_mission_name == "Cocytus Showdown": # Navigate to Cocytus Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Cocytus Showdown...") MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif formatted_mission_name == "Vohu Manah Showdown": # Navigate to Vohu Manah Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Vohu Manah Showdown..." ) MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif formatted_mission_name == "Sagittarius Showdown": # Navigate to Sagittarius Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Sagittarius Showdown..." ) MouseUtils.move_and_click_point( locations[3][0], locations[3][1], "play_round_button") elif formatted_mission_name == "Corow Showdown": # Navigate to Corow Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Corow Showdown...") MouseUtils.move_and_click_point( locations[4][0], locations[4][1], "play_round_button") elif formatted_mission_name == "Diablo Showdown": # Navigate to Diablo Showdown. MessageLog.print_message( f"[SPECIAL] Selecting Diablo Showdown...") MouseUtils.move_and_click_point( locations[5][0], locations[5][1], "play_round_button") # Now start the Showdown with the specified difficulty. Game.wait(1) MessageLog.print_message( f"[SPECIAL] Now navigating to {difficulty}...") locations = ImageUtils.find_all( "play_round_button") if difficulty == "Hard": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif difficulty == "Very Hard": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif difficulty == "Extreme": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") elif Settings.map_name == "Campaign-Exclusive Quest": MessageLog.print_message( f"[SPECIAL] Selecting Campaign-Exclusive Quest..." ) locations = ImageUtils.find_all( "play_round_button") # There is only one round "Play" button for this time-limited quest. MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") else: # Start up the Angel Halo mission by selecting its difficulty. MessageLog.print_message( f"[SPECIAL] Selecting {difficulty} Angel Halo..." ) locations = ImageUtils.find_all( "play_round_button") if difficulty == "Normal": MouseUtils.move_and_click_point( locations[0][0], locations[0][1], "play_round_button") elif difficulty == "Hard": MouseUtils.move_and_click_point( locations[1][0], locations[1][1], "play_round_button") elif difficulty == "Very Hard": MouseUtils.move_and_click_point( locations[2][0], locations[2][1], "play_round_button") break else: # Scroll the screen down more if on a smaller screen and it obscures the targeted mission. MouseUtils.scroll_screen( Settings.home_button_location[0], Settings.home_button_location[1] - 50, -500) tries -= 1 return None
def check_for_xeno_clash_nightmare(): """Checks for Xeno Clash Nightmare and if it appears and the user enabled it in user settings, start it. Returns: (bool): Return True if Xeno Clash Nightmare was detected and successfully completed. Otherwise, return False. """ from bot.game import Game if Settings.enable_nightmare and ImageUtils.confirm_location("limited_time_quests", tries = 1): # First check if the Xeno Clash Nightmare is skippable. event_claim_loot_location = ImageUtils.find_button("event_claim_loot", tries = 1, suppress_error = True) if event_claim_loot_location is not None: MessageLog.print_message("\n[XENO] Skippable Xeno Clash Nightmare detected. Claiming it now...") MouseUtils.move_and_click_point(event_claim_loot_location[0], event_claim_loot_location[1], "event_claim_loot") Game.collect_loot(is_completed = False, is_event_nightmare = True) return True else: MessageLog.print_message("\n[XENO] Detected Xeno Clash Nightmare. Starting it now...") MessageLog.print_message("\n********************************************************************************") MessageLog.print_message("********************************************************************************") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Summon Elements: {Settings.nightmare_summon_elements_list}") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Summons: {Settings.nightmare_summon_list}") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Group Number: {Settings.nightmare_group_number}") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Party Number: {Settings.nightmare_party_number}") MessageLog.print_message(f"[XENO] Xeno Clash Nightmare Combat Script: {Settings.nightmare_combat_script_name}") MessageLog.print_message("********************************************************************************") MessageLog.print_message("********************************************************************************\n") # Click the "Play Next" button to head to the Summon Selection screen. Game.find_and_click_button("play_next") Game.wait(1) # Select only the first Nightmare. play_round_buttons = ImageUtils.find_all("play_round_button") MouseUtils.move_and_click_point(play_round_buttons[0][0], play_round_buttons[0][1], "play_round_button") Game.wait(1) # Once the bot is at the Summon Selection screen, select your Summon and Party and start the mission. if ImageUtils.confirm_location("select_a_summon"): Game.select_summon(Settings.nightmare_summon_list, Settings.nightmare_summon_elements_list) start_check = Game.find_party_and_start_mission(int(Settings.nightmare_group_number), int(Settings.nightmare_party_number)) # Once preparations are completed, start Combat Mode. if start_check and CombatMode.start_combat_mode(is_nightmare = True): Game.collect_loot(is_completed = False, is_event_nightmare = True) return True elif not Settings.enable_nightmare and ImageUtils.confirm_location("limited_time_quests", tries = 1): # First check if the Xeno Clash Nightmare is skippable. event_claim_loot_location = ImageUtils.find_button("event_claim_loot", tries = 1, suppress_error = True) if event_claim_loot_location is not None: MessageLog.print_message("\n[XENO] Skippable Xeno Clash Nightmare detected but user opted to not run it. Claiming it regardless...") MouseUtils.move_and_click_point(event_claim_loot_location[0], event_claim_loot_location[1], "event_claim_loot") Game.collect_loot(is_completed = False, is_event_nightmare = True) return True else: MessageLog.print_message("\n[XENO] Xeno Clash Nightmare detected but user opted to not run it. Moving on...") Game.find_and_click_button("close") else: MessageLog.print_message("\n[XENO] No Xeno Clash Nightmare detected. Moving on...") return False
def _navigate(): """Navigates to the specified Rise of the Beasts mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check=True) MessageLog.print_message( f"\n[ROTB] Now navigating to Rise of the Beasts...") # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") banner_locations = ImageUtils.find_all("event_banner", custom_confidence=0.7) if len(banner_locations) == 0: banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence=0.7) MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner") Game.wait(1) if ImageUtils.confirm_location("rotb"): # Remove the difficulty prefix from the mission name. difficulty = "" temp_mission_name = "" if Settings.mission_name.find("VH ") == 0: difficulty = "Very Hard" temp_mission_name = Settings.mission_name[3:] elif Settings.mission_name.find("EX ") == 0: difficulty = "Extreme" temp_mission_name = Settings.mission_name[3:] # Only Raids are marked with Extreme difficulty. if difficulty == "Extreme": # Click on the Raid banner. MessageLog.print_message( f"[ROTB] Now hosting {temp_mission_name} Raid...") Game.find_and_click_button("rotb_extreme") if ImageUtils.confirm_location("rotb_battle_the_beasts", tries=30): if temp_mission_name == "Zhuque": MessageLog.print_message( f"[ROTB] Now starting EX Zhuque Raid...") Game.find_and_click_button("rotb_raid_zhuque") elif temp_mission_name == "Xuanwu": MessageLog.print_message( f"[ROTB] Now starting EX Xuanwu Raid...") Game.find_and_click_button("rotb_raid_xuanwu") elif temp_mission_name == "Baihu": MessageLog.print_message( f"[ROTB] Now starting EX Baihu Raid...") Game.find_and_click_button("rotb_raid_baihu") elif temp_mission_name == "Qinglong": MessageLog.print_message( f"[ROTB] Now starting EX Qinglong Raid...") Game.find_and_click_button("rotb_raid_qinglong") else: raise (RiseOfTheBeastsException( "Failed to open the ROTB Battle the Beasts popup.")) elif Settings.mission_name == "Lvl 100 Shenxian": # Click on Shenxian to host. MessageLog.print_message( f"[ROTB] Now hosting Shenxian Raid...") Game.find_and_click_button("rotb_shenxian_host") if ImageUtils.wait_vanish("rotb_shenxian_host", timeout=10) is False: MessageLog.print_message( f"[ROTB] There are no more Shenxian hosts left. Alerting user..." ) raise RiseOfTheBeastsException( "There are no more Shenxian hosts left.") else: MessageLog.print_message( f"[ROTB] Now hosting {temp_mission_name} Quest...") # Scroll the screen down to make way for smaller screens. MouseUtils.scroll_screen_from_home_button(-400) # Find all instances of the "Select" button on the screen and click on the first instance. select_button_locations = ImageUtils.find_all("select") MouseUtils.move_and_click_point(select_button_locations[0][0], select_button_locations[0][1], "select") if ImageUtils.confirm_location("rotb_rising_beasts_showdown", tries=30): # Find all the round "Play" buttons. round_play_button_locations = ImageUtils.find_all( "play_round_button") if temp_mission_name == "Zhuque": MouseUtils.move_and_click_point( round_play_button_locations[0][0], round_play_button_locations[0][1], "play_round_button") elif temp_mission_name == "Xuanwu": MouseUtils.move_and_click_point( round_play_button_locations[1][0], round_play_button_locations[1][1], "play_round_button") elif temp_mission_name == "Baihu": MouseUtils.move_and_click_point( round_play_button_locations[2][0], round_play_button_locations[2][1], "play_round_button") elif temp_mission_name == "Qinglong": MouseUtils.move_and_click_point( round_play_button_locations[3][0], round_play_button_locations[3][1], "play_round_button") Game.wait(2.0) # Find all the round "Play" buttons again. round_play_button_locations = ImageUtils.find_all( "play_round_button") # Only Very Hard difficulty will be supported for farming efficiency MouseUtils.move_and_click_point( round_play_button_locations[2][0], round_play_button_locations[2][1], "play_round_button") else: raise (RiseOfTheBeastsException( "Failed to open the ROTB Rising Beasts Showdown popup." )) return None
def _navigate(): """Navigates to the specified Dread Barrage mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check = True) # Scroll down the screen a little bit and then click the Dread Barrage banner. MessageLog.print_message(f"\n[DREAD.BARRAGE] Now navigating to Dread Barrage...") MouseUtils.scroll_screen_from_home_button(-400) Game.find_and_click_button("dread_barrage") Game.wait(2) if ImageUtils.confirm_location("dread_barrage"): # Check if there is already a hosted Dread Barrage mission. if ImageUtils.confirm_location("resume_quests", tries = 1): MessageLog.print_message(f"\n[WARNING] Detected that there is already a hosted Dread Barrage mission.") expiry_time_in_seconds = 0 while ImageUtils.confirm_location("resume_quests", tries = 1): # If there is already a hosted Dread Barrage mission, the bot will wait for a total of 1 hour and 30 minutes # for either the raid to expire or for anyone in the room to clear it. MessageLog.print_message(f"\n[WARNING] The bot will now either wait for the expiry time of 1 hour and 30 minutes or for someone else in the room to clear it.") MessageLog.print_message(f"[WARNING] The bot will now refresh the page every 30 seconds to check if it is still there before proceeding.") MessageLog.print_message(f"[WARNING] User can either wait it out, revive and fight it to completion, or retreat from the mission manually.") Game.wait(30) Game.find_and_click_button("reload") Game.wait(2) expiry_time_in_seconds += 30 if expiry_time_in_seconds >= 5400: break MessageLog.print_message(f"\n[SUCCESS] Hosted Dread Barrage mission is now gone either because of timeout or someone else in the room killed it. Moving on...\n") # Find all the "Play" buttons at the top of the window. dread_barrage_play_button_locations = ImageUtils.find_all("dread_barrage_play") difficulty = "" if Settings.mission_name.find("1 Star") == 0: difficulty = "1 Star" elif Settings.mission_name.find("2 Star") == 0: difficulty = "2 Star" elif Settings.mission_name.find("3 Star") == 0: difficulty = "3 Star" elif Settings.mission_name.find("4 Star") == 0: difficulty = "4 Star" elif Settings.mission_name.find("5 Star") == 0: difficulty = "5 Star" # Navigate to the specified difficulty. if difficulty == "1 Star": MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 1 Star Dread Barrage Raid...") MouseUtils.move_and_click_point(dread_barrage_play_button_locations[0][0], dread_barrage_play_button_locations[0][1], "dread_barrage_play") elif difficulty == "2 Star": MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 2 Star Dread Barrage Raid...") MouseUtils.move_and_click_point(dread_barrage_play_button_locations[1][0], dread_barrage_play_button_locations[1][1], "dread_barrage_play") elif difficulty == "3 Star": MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 3 Star Dread Barrage Raid...") MouseUtils.move_and_click_point(dread_barrage_play_button_locations[2][0], dread_barrage_play_button_locations[2][1], "dread_barrage_play") elif difficulty == "4 Star": MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 4 Star Dread Barrage Raid...") MouseUtils.move_and_click_point(dread_barrage_play_button_locations[3][0], dread_barrage_play_button_locations[3][1], "dread_barrage_play") elif difficulty == "5 Star": MessageLog.print_message(f"[DREAD.BARRAGE] Now starting 5 Star Dread Barrage Raid...") MouseUtils.move_and_click_point(dread_barrage_play_button_locations[4][0], dread_barrage_play_button_locations[4][1], "dread_barrage_play") Game.wait(2)
def _navigate(): """Navigates to the specified Coop mission. Returns: None """ from bot.game import Game MessageLog.print_message( f"\n[COOP] Beginning process to navigate to the mission: {Settings.mission_name}..." ) # Go to the Home screen. Game.go_back_home(confirm_location_check=True) # Click the "Menu" button on the Home screen and then go to the Coop screen. Game.find_and_click_button("home_menu") Game.find_and_click_button("coop") if ImageUtils.confirm_location("coop"): # Scroll down the screen to see more of the Coop missions on smaller screens. MouseUtils.scroll_screen_from_home_button(-400) # Find the locations of all of the "Host Quest" buttons. host_quest_button_locations = ImageUtils.find_all( "coop_host_quest") # Select the difficulty of the mission that it is under. if Settings.mission_name == "H3-1 In a Dusk Dream": # Check if Hard difficulty is already selected. If not, make it active. if ImageUtils.find_button("coop_hard_selected") is None: Game.find_and_click_button("coop_hard") MessageLog.print_message( f"\n[COOP] Hard difficulty for Coop is now selected.") # Select the category, "Save the Oceans", which should be the 3rd category. MessageLog.print_message( f"[COOP] Now navigating to \"{Settings.mission_name}\" for Hard difficulty." ) MouseUtils.move_and_click_point( host_quest_button_locations[2][0], host_quest_button_locations[2][1], "coop_host_quest") if ImageUtils.confirm_location("coop_save_the_oceans"): # Now click "In a Dusk Dream". host_quests_circle_buttons = ImageUtils.find_all( "coop_host_quest_circle") MouseUtils.move_and_click_point( host_quests_circle_buttons[0][0], host_quests_circle_buttons[0][1], "coop_host_quest") else: # Check if Extra difficulty is already selected. If not, make it active. if ImageUtils.find_button("coop_extra_selected") is None: Game.find_and_click_button("coop_extra") MessageLog.print_message( f"\n[COOP] Extra difficulty for Coop is now selected.") # Make the specified EX category active. Then click the mission's button while making sure that the first mission in each category is skipped. if Settings.mission_name in Coop._coop_ex1_list: MessageLog.print_message( f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX1..." ) MouseUtils.move_and_click_point( host_quest_button_locations[0][0], host_quest_button_locations[0][1], "coop_host_quest") if ImageUtils.confirm_location("coop_ex1"): MessageLog.print_message( f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\"" ) coop_host_locations = ImageUtils.find_all( "coop_host_quest_circle") MouseUtils.move_and_click_point( coop_host_locations[Coop._coop_ex1_list.index( Settings.mission_name)][0], coop_host_locations[Coop._coop_ex1_list.index( Settings.mission_name)][1], "coop_host_quest") elif Settings.mission_name in Coop._coop_ex2_list: MessageLog.print_message( f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX2..." ) MouseUtils.move_and_click_point( host_quest_button_locations[1][0], host_quest_button_locations[1][1], "coop_host_quest") if ImageUtils.confirm_location("coop_ex2"): MessageLog.print_message( f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\"" ) coop_host_locations = ImageUtils.find_all( "coop_host_quest_circle") MouseUtils.move_and_click_point( coop_host_locations[Coop._coop_ex2_list.index( Settings.mission_name) + 1][0], coop_host_locations[Coop._coop_ex2_list.index( Settings.mission_name) + 1][1], "coop_host_quest") elif Settings.mission_name in Coop._coop_ex3_list: MessageLog.print_message( f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX3." ) MouseUtils.move_and_click_point( host_quest_button_locations[2][0], host_quest_button_locations[2][1], "coop_host_quest") if ImageUtils.confirm_location("coop_ex3"): MessageLog.print_message( f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\"" ) coop_host_locations = ImageUtils.find_all( "coop_host_quest_circle") MouseUtils.move_and_click_point( coop_host_locations[Coop._coop_ex3_list.index( Settings.mission_name) + 1][0], coop_host_locations[Coop._coop_ex3_list.index( Settings.mission_name) + 1][1], "coop_host_quest") elif Settings.mission_name in Coop._coop_ex4_list: MessageLog.print_message( f"\n[COOP] Now navigating to \"{Settings.mission_name}\" from EX4." ) MouseUtils.move_and_click_point( host_quest_button_locations[3][0], host_quest_button_locations[3][1], "coop_host_quest") if ImageUtils.confirm_location("coop_ex4"): MessageLog.print_message( f"\n[COOP] Now selecting Coop mission: \"{Settings.mission_name}\"" ) coop_host_locations = ImageUtils.find_all( "coop_host_quest_circle") MouseUtils.move_and_click_point( coop_host_locations[Coop._coop_ex4_list.index( Settings.mission_name) + 1][0], coop_host_locations[Coop._coop_ex4_list.index( Settings.mission_name) + 1][1], "coop_host_quest") # After clicking on the Coop mission, create a new Room. MessageLog.print_message(f"\n[COOP] Opening up a new Coop room...") Game.find_and_click_button("coop_post_to_crew_chat") # Scroll down the screen to see the "OK" button just in case of smaller screens. MouseUtils.scroll_screen_from_home_button(-400) Game.find_and_click_button("ok") Game.wait(1) # Just in case, check for the "You retreated from the raid battle" popup. if ImageUtils.confirm_location( "you_retreated_from_the_raid_battle", tries=1): Game.find_and_click_button("ok") MessageLog.print_message( f"\n[COOP] Selecting a Party for Coop mission: \"{Settings.mission_name}\"." ) Game.find_and_click_button("coop_select_party") return None
def _navigate(): """Navigates to the specified Guild Wars mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check = True) MessageLog.print_message(f"\n[GUILD.WARS] Now navigating to Guild Wars...") # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") banner_locations = ImageUtils.find_all("event_banner", custom_confidence = 0.7) if len(banner_locations) == 0: banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence = 0.7) MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner") Game.wait(1.0) difficulty = "" if Settings.mission_name == "Very Hard": difficulty = "Very Hard" elif Settings.mission_name == "Extreme": difficulty = "Extreme" elif Settings.mission_name == "Extreme+": difficulty = "Extreme+" elif Settings.mission_name == "NM90": difficulty = "NM90" elif Settings.mission_name == "NM95": difficulty = "NM95" elif Settings.mission_name == "NM100": difficulty = "NM100" elif Settings.mission_name == "NM150": difficulty = "NM150" if ImageUtils.confirm_location("guild_wars"): # Scroll the screen down a little bit. MouseUtils.scroll_screen_from_home_button(-200) Game.wait(1.0) raid_battle_locations = ImageUtils.find_all("event_raid_battle") # Perform different navigation actions based on whether the user wants to farm meat or to farm Nightmares. if difficulty == "Very Hard" or difficulty == "Extreme" or difficulty == "Extreme+": MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm meat.") # Click on the banner to farm meat. MouseUtils.move_and_click_point(raid_battle_locations[1][0], raid_battle_locations[1][1], "event_raid_battle") Game.wait(1.0) if ImageUtils.confirm_location("guild_wars_meat"): # Now click on the specified Mission to start. Also attempt at fixing the deadzone issue by looping. formatted_mission_name = difficulty.replace(" ", "_") tries = 10 MessageLog.print_message(f"[GUILD.WARS] Now hosting {difficulty} now...") ap_locations = ImageUtils.find_all("ap_30") if difficulty == "Very Hard": MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30") elif difficulty == "Extreme": MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30") elif difficulty == "Extreme+": MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30") Game.wait(3.0) while ImageUtils.wait_vanish("ap_30", timeout = 3) is False: if difficulty == "Very Hard": MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30") elif difficulty == "Extreme": MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30") elif difficulty == "Extreme+": MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30") Game.wait(3.0) tries -= 1 if tries <= 0: if difficulty == "Extreme+": ImageUtils.generate_alert("You did not unlock Extreme+ yet!") raise GuildWarsException("You did not unlock Extreme+ yet!") else: raise GuildWarsException("There appears to be a deadzone issue that the bot failed 10 times to resolve. Please refresh the page and try again.") return None else: MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm Nightmares.") # Click on the banner to farm Nightmares. if difficulty != "NM150": MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle") if not ImageUtils.wait_vanish("guild_wars_nightmare", timeout = 10): MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle") else: MessageLog.print_message(f"\n[GUILD.WARS] Now hosting NM150 now...") Game.find_and_click_button("guild_wars_nightmare_150") if not ImageUtils.wait_vanish("guild_wars_nightmare_150", timeout = 10): Game.find_and_click_button("guild_wars_nightmare_150") if ImageUtils.confirm_location("guild_wars_nightmare"): Game.find_and_click_button("start") if difficulty != "NM150" and ImageUtils.confirm_location("guild_wars_nightmare"): nightmare_locations = ImageUtils.find_all("guild_wars_nightmares") # If today is the first/second day of Guild Wars, only NM90 will be available. if ImageUtils.confirm_location("guild_wars_nightmare_first_day", tries = 3): MessageLog.print_message(f"[GUILD.WARS] Today is the first/second day so hosting NM90.") Game.find_and_click_button("ok") # Alert the user if they lack the meat to host this and stop the bot. if not ImageUtils.wait_vanish("ok", timeout = 30): ImageUtils.generate_alert("You do not have enough meat to host this NM90!") raise GuildWarsException("You do not have enough meat to host this NM90!") # If it is not the first/second day of Guild Wars, that means that other difficulties are now available. elif difficulty == "NM90": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM90 now...") MouseUtils.move_and_click_point(nightmare_locations[0][0], nightmare_locations[0][1], "guild_wars_nightmares") elif difficulty == "NM95": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM95 now...") MouseUtils.move_and_click_point(nightmare_locations[1][0], nightmare_locations[1][1], "guild_wars_nightmares") elif difficulty == "NM100": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM100 now...") MouseUtils.move_and_click_point(nightmare_locations[2][0], nightmare_locations[2][1], "guild_wars_nightmares") else: # If there is not enough meat to host, host Extreme+ instead. MessageLog.print_message(f"\n[GUILD.WARS] User lacks meat to host the Nightmare. Hosting Extreme+ instead...") if difficulty != "NM150": Game.find_and_click_button("close") else: Game.find_and_click_button("cancel") # Click on the banner to farm meat. Game.find_and_click_button("guild_wars_meat") if ImageUtils.confirm_location("guild_wars_meat"): MessageLog.print_message(f"[GUILD.WARS] Now hosting Extreme+ now...") Game.find_and_click_button("guild_wars_meat_extreme+") # Alert the user if they did not unlock Extreme+ and stop the bot. if not ImageUtils.wait_vanish("guild_wars_meat_extreme+", timeout = 30): ImageUtils.generate_alert("You did not unlock Extreme+ yet!") raise GuildWarsException("You did not unlock Extreme+ yet!") return None
def _choose_action() -> str: """Chooses the next action to take for the current Arcarum expedition. Returns: (str): The action to take next. """ from bot.game import Game # Determine what action to take. MessageLog.print_message( f"\n[ARCARUM] Now determining what action to take...") # Wait a second in case the "Do or Die" animation plays. Game.wait(1) tries = 3 while tries > 0: # Prioritise any enemies/chests/thorns that are available on the current node. arcarum_actions = ImageUtils.find_all("arcarum_action") if len(arcarum_actions) > 0: MouseUtils.move_and_click_point(arcarum_actions[0][0], arcarum_actions[0][1], "arcarum_action") Game.wait(2) Game.check_for_captcha() if ImageUtils.confirm_location("arcarum_party_selection", tries=1): return "Combat" elif Game.find_and_click_button("ok", tries=1): return "Claimed Treasure/Keythorn" else: return "Claimed Spirethorn/No Action" # Clear any detected Treasure popup after claiming a chest. MessageLog.print_message( f"[ARCARUM] No action found for the current node. Looking for Treasure popup..." ) if ImageUtils.confirm_location("arcarum_treasure", tries=1): Game.find_and_click_button("ok") return "Claimed Treasure" # Next, determine if there is a available node to move to. Any bound monsters should have been destroyed by now. MessageLog.print_message( f"[ARCARUM] No Treasure popup detected. Looking for an available node to move to..." ) if Game.find_and_click_button("arcarum_node", tries=1): Game.wait(1) return "Navigating" # Check if a Arcarum boss has appeared. This is after checking for available actions and before searching for a node to move to avoid false positives. if Arcarum._check_for_boss(): return "Boss Detected" # Next, attempt to navigate to a node that is occupied by mob(s). MessageLog.print_message( f"[ARCARUM] No available node to move to. Looking for nodes with mobs on them..." ) if Game.find_and_click_button( "arcarum_mob", tries=1) or Game.find_and_click_button( "arcarum_red_mob", tries=1): Game.wait(1) return "Navigating" # If all else fails, see if there are any unclaimed chests, like the ones spawned by a random special event that spawns chests on all nodes. MessageLog.print_message( f"[ARCARUM] No nodes with mobs on them. Looking for nodes with chests on them..." ) if Game.find_and_click_button( "arcarum_silver_chest", tries=1) or Game.find_and_click_button( "arcarum_gold_chest", tries=1): Game.wait(1) return "Navigating" tries -= 1 MessageLog.print_message( f"[ARCARUM] No action can be taken. Defaulting to moving to the next area." ) return "Next Area"