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 _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 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 _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 _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 _join_raid() -> bool: """Start the process to fetch a valid room code and join it. Returns: (bool): True if the bot arrived at the Summon Selection screen. """ from bot.game import Game recovery_time = 15 # Make preparations for farming raids by saving the location of the "Join Room" button and the "Room Code" textbox. join_room_button = ImageUtils.find_button("join_a_room") room_code_textbox = (join_room_button[0] - 185, join_room_button[1]) # Loop and try to join a raid. If none of the room codes worked, wait before trying again with a new set of room codes for a maximum of 10 tries. tries = 10 while tries > 0: room_code_tries = 5 while room_code_tries > 0: # Attempt to find a room code. room_code = TwitterRoomFinder.get_room_code() if room_code != "": # Select the "Room Code" textbox and then clear all text from it. MouseUtils.move_and_click_point( room_code_textbox[0], room_code_textbox[1], "template_room_code_textbox", mouse_clicks=2) MouseUtils.clear_textbox() # Copy the room code to the clipboard and then paste it into the "Room Code" textbox. MouseUtils.copy_to_clipboard(room_code) MouseUtils.paste_from_clipboard() # Now click on the "Join Room" button. MouseUtils.move_and_click_point(join_room_button[0], join_room_button[1], "join_a_room") # If the room code is valid and the raid is able to be joined, break out and head to the Summon Selection screen. if Game.find_and_click_button( "ok", suppress_error=True) is False: # Check for EP. Game.check_for_ep() MessageLog.print_message( f"[SUCCESS] Joining {room_code} was successful.") Raid._raids_joined += 1 return ImageUtils.confirm_location("select_a_summon") elif Game.check_for_pending() is False: MessageLog.print_message( f"[WARNING] {room_code} already ended or invalid.") else: # Move from the Home screen back to the Backup Requests screen after clearing out all the Pending Battles. Game.find_and_click_button("quest") Game.find_and_click_button("raid") Game.find_and_click_button("enter_id") if Settings.enable_no_timeout is False: room_code_tries -= 1 Game.wait(1) tries -= 1 MessageLog.print_message( f"\n[WARNING] Could not find any valid room codes. \nWaiting {recovery_time} seconds and then trying again with {tries} tries left before exiting." ) Game.wait(recovery_time) raise RaidException( "Failed to find any valid room codes for 10 total times.")
def _navigate_to_map() -> bool: """Navigates to the specified Arcarum expedition. Returns: (bool): True if the bot was able to start/resume the expedition. False otherwise. """ from bot.game import Game if Arcarum._first_run: MessageLog.print_message( f"\n[ARCARUM] Now beginning navigation to {Arcarum._expedition}." ) Game.go_back_home() # Navigate to the Arcarum banner. tries = 5 while tries > 0: if Game.find_and_click_button("arcarum_banner", tries=1) is False: MouseUtils.scroll_screen_from_home_button(-300) tries -= 1 if tries <= 0: raise ArcarumException( "Failed to navigate to Arcarum from the Home screen." ) else: break Arcarum._first_run = False else: Game.wait(4) # Now make sure that the Extreme difficulty is selected. Game.wait(1) # Confirm the completion popup if it shows up. if ImageUtils.confirm_location("arcarum_expedition", tries=1): Game.find_and_click_button("ok") Game.find_and_click_button("arcarum_extreme") # Finally, navigate to the specified map to start it. MessageLog.print_message( f"[ARCARUM] Now starting the specified expedition: {Arcarum._expedition}." ) formatted_map_name = Arcarum._expedition.lower().replace(" ", "_") if Game.find_and_click_button(f"arcarum_{formatted_map_name}", tries=5) is False: # Resume the expedition if it is already in-progress. Game.find_and_click_button("arcarum_exploring") elif ImageUtils.confirm_location("arcarum_departure_check"): MessageLog.print_message( f"[ARCARUM] Now using 1 Arcarum ticket to start this expedition..." ) result_check = Game.find_and_click_button("start_expedition") Game.wait(6) return result_check elif Game.find_and_click_button("resume"): Game.wait(3) return True else: raise ArcarumException( "Failed to encounter the Departure Check to confirm starting the expedition." )
def _navigate(): """Navigates to the specified 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_to_map(map_name: str, current_location: str) -> bool: """Navigates the bot to the specified Map for Quest Farming Mode. Args: map_name (str): Name of the Map to navigate to. current_location (str): Name of the Map that the bot is currently at. Returns: (bool): Return True if the bot reached the Summon Selection screen. Otherwise, return False. """ from bot.game import Game MessageLog.print_message( f"\n[QUEST] Beginning process to navigate to the island: {map_name}..." ) # Phantagrande Skydom Page 1 if Quest._page_1_list.__contains__(map_name): # Switch pages if needed. if Quest._page_2_list.__contains__(current_location): Game.find_and_click_button("world_left_arrow") # Click on the Map to move to it. if not Game.find_and_click_button(map_name.lower().replace( " ", "_").replace("-", "_")): # If the name of the island is obscured, like by the "Next" text indicating that the user's next quest is there, fallback to a manual method. arrow_location = ImageUtils.find_button("world_right_arrow") if map_name == "Port Breeze Archipelago": MouseUtils.move_and_click_point(arrow_location[0] - 320, arrow_location[1] - 159, "world_right_arrow") elif map_name == "Valtz Duchy": MouseUtils.move_and_click_point(arrow_location[0] - 150, arrow_location[1] - 85, "world_right_arrow") elif map_name == "Auguste Isles": MouseUtils.move_and_click_point(arrow_location[0] - 374, arrow_location[1] - 5, "world_right_arrow") elif map_name == "Lumacie Archipelago": MouseUtils.move_and_click_point(arrow_location[0] - 84, arrow_location[1] + 39, "world_right_arrow") elif map_name == "Albion Citadel": MouseUtils.move_and_click_point(arrow_location[0] - 267, arrow_location[1] + 121, "world_right_arrow") return True # Phantagrande Skydom Page 2 elif Quest._page_2_list.__contains__(map_name): if Quest._page_1_list.__contains__(current_location): Game.find_and_click_button("world_right_arrow") if not Game.find_and_click_button(map_name.lower().replace( " ", "_").replace("-", "_")): arrow_location = ImageUtils.find_button("world_left_arrow") if map_name == "Mist-Shrouded Isle": MouseUtils.move_and_click_point(arrow_location[0] + 162, arrow_location[1] + 114, "world_left_arrow") elif map_name == "Golonzo Island": MouseUtils.move_and_click_point(arrow_location[0] + 362, arrow_location[1] + 85, "world_left_arrow") elif map_name == "Amalthea Island": MouseUtils.move_and_click_point(arrow_location[0] + 127, arrow_location[1] - 14, "world_left_arrow") elif map_name == "Former Capital Mephorash": MouseUtils.move_and_click_point(arrow_location[0] + 352, arrow_location[1] - 51, "world_left_arrow") elif map_name == "Agastia": MouseUtils.move_and_click_point(arrow_location[0] + 190, arrow_location[1] - 148, "world_left_arrow") return True return False
def _navigate(): """Navigates to the specified Quest mission. Returns: None """ from bot.game import Game MessageLog.print_message( f"\n[QUEST] Beginning process to navigate to the mission: {Settings.mission_name}..." ) # Go to the Home screen. Game.go_back_home(confirm_location_check=True) current_location = "" formatted_map_name = Settings.map_name.lower().replace(" ", "_").replace( "-", "_") # Check which island the bot is at. if ImageUtils.confirm_location(f"map_{formatted_map_name}", tries=3): MessageLog.print_message( f"[QUEST] Bot is currently on the correct island.") check_location = True else: MessageLog.print_message( f"[QUEST] Bot is currently not on the correct island.") check_location = False location_list = [ "Zinkenstill", "Port Breeze Archipelago", "Valtz Duchy", "Auguste Isles", "Lumacie Archipelago", "Albion Citadel", "Mist-Shrouded Isle", "Golonzo Island", "Amalthea Island", "Former Capital Mephorash", "Agastia" ] while len(location_list) > 0: temp_map_location = location_list.pop(0) temp_formatted_map_location = temp_map_location.lower( ).replace(" ", "_").replace("-", "_") if ImageUtils.confirm_location( f"map_{temp_formatted_map_location}", tries=1): MessageLog.print_message( f"[QUEST] Bot's current location is at {temp_map_location}. Now moving to {Settings.map_name}..." ) current_location = temp_map_location break # Once the bot has determined where it is, go to the Quest screen. Game.find_and_click_button("quest") Game.wait(1) # Check for the "You retreated from the raid battle" popup. if ImageUtils.confirm_location("you_retreated_from_the_raid_battle", tries=3): Game.find_and_click_button("ok") if ImageUtils.confirm_location("quest"): # If the bot is currently not at the correct island, move to it. if not check_location: # Click the "World" button. Game.find_and_click_button("world") # On the World screen, click the specified coordinates on the window to move to the island. If the island is on a different world page, switch pages as necessary. Quest._navigate_to_map(Settings.map_name, current_location) # Click "Go" on the popup after clicking on the map node. Game.find_and_click_button("go") # Grab the location of the "World" button. world_location = ImageUtils.find_button("world", tries=5) if world_location is None: world_location = ImageUtils.find_button("world2", tries=5) # Now that the bot is on the correct island and is at the Quest screen, click the correct chapter node. if Settings.mission_name == "Scattered Cargo": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 1 (115) node at ({world_location[0] + 97}, {world_location[1] + 97})..." ) MouseUtils.move_and_click_point(world_location[0] + 97, world_location[1] + 97, "template_node") elif Settings.mission_name == "Lucky Charm Hunt": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 6 (122) node...") MouseUtils.move_and_click_point(world_location[0] + 332, world_location[1] + 16, "template_node") elif Settings.mission_name == "Special Op's Request": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 8 node...") MouseUtils.move_and_click_point(world_location[0] + 258, world_location[1] + 151, "template_node") elif Settings.mission_name == "Threat to the Fisheries": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 9 node...") MouseUtils.move_and_click_point(world_location[0] + 216, world_location[1] + 113, "template_node") elif Settings.mission_name == "The Fruit of Lumacie" or Settings.mission_name == "Whiff of Danger": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 13 (39/52) node...") MouseUtils.move_and_click_point(world_location[0] + 78, world_location[1] + 92, "template_node") elif Settings.mission_name == "I Challenge You!": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 17 node...") MouseUtils.move_and_click_point(world_location[0] + 119, world_location[1] + 121, "template_node") elif Settings.mission_name == "For Whom the Bell Tolls": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 22 node...") MouseUtils.move_and_click_point(world_location[0] + 178, world_location[1] + 33, "template_node") elif Settings.mission_name == "Golonzo's Battles of Old": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 25 node...") MouseUtils.move_and_click_point(world_location[0] + 196, world_location[1] + 5, "template_node") elif Settings.mission_name == "The Dungeon Diet": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 30 (44/65) node...") MouseUtils.move_and_click_point(world_location[0] + 242, world_location[1] + 24, "template_node") elif Settings.mission_name == "Trust Busting Dustup": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 36 (123) node...") MouseUtils.move_and_click_point(world_location[0] + 319, world_location[1] + 13, "template_node") elif Settings.mission_name == "Erste Kingdom Episode 4": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 70 node...") MouseUtils.move_and_click_point(world_location[0] + 253, world_location[1] + 136, "template_node") elif Settings.mission_name == "Imperial Wanderer's Soul": MessageLog.print_message( f"\n[QUEST] Moving to Chapter 55 node...") MouseUtils.move_and_click_point(world_location[0] + 162, world_location[1] + 143, "template_node") # After being on the correct chapter node, scroll down the screen as far as possible and then click the mission to start. MouseUtils.scroll_screen(Settings.home_button_location[0], Settings.home_button_location[1] - 50, -1000) Game.find_and_click_button(Settings.mission_name.replace(" ", "_")) # Apply special navigation for mission "Ch. 70 - Erste Kingdom". if Settings.mission_name == "Erste Kingdom Episode 4": Game.find_and_click_button("episode_4") Game.find_and_click_button("ok") return None
def _navigate(): """Navigates to the specified Guild Wars mission. Returns: None """ from bot.game import Game # Go to the Home screen. Game.go_back_home(confirm_location_check = True) MessageLog.print_message(f"\n[GUILD.WARS] Now navigating to Guild Wars...") # Go to the Event by clicking on the "Menu" button and then click the very first banner. Game.find_and_click_button("home_menu") banner_locations = ImageUtils.find_all("event_banner", custom_confidence = 0.7) if len(banner_locations) == 0: banner_locations = ImageUtils.find_all("event_banner_blue", custom_confidence = 0.7) MouseUtils.move_and_click_point(banner_locations[0][0], banner_locations[0][1], "event_banner") Game.wait(1.0) difficulty = "" if Settings.mission_name == "Very Hard": difficulty = "Very Hard" elif Settings.mission_name == "Extreme": difficulty = "Extreme" elif Settings.mission_name == "Extreme+": difficulty = "Extreme+" elif Settings.mission_name == "NM90": difficulty = "NM90" elif Settings.mission_name == "NM95": difficulty = "NM95" elif Settings.mission_name == "NM100": difficulty = "NM100" elif Settings.mission_name == "NM150": difficulty = "NM150" if ImageUtils.confirm_location("guild_wars"): # Scroll the screen down a little bit. MouseUtils.scroll_screen_from_home_button(-200) Game.wait(1.0) raid_battle_locations = ImageUtils.find_all("event_raid_battle") # Perform different navigation actions based on whether the user wants to farm meat or to farm Nightmares. if difficulty == "Very Hard" or difficulty == "Extreme" or difficulty == "Extreme+": MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm meat.") # Click on the banner to farm meat. MouseUtils.move_and_click_point(raid_battle_locations[1][0], raid_battle_locations[1][1], "event_raid_battle") Game.wait(1.0) if ImageUtils.confirm_location("guild_wars_meat"): # Now click on the specified Mission to start. Also attempt at fixing the deadzone issue by looping. formatted_mission_name = difficulty.replace(" ", "_") tries = 10 MessageLog.print_message(f"[GUILD.WARS] Now hosting {difficulty} now...") ap_locations = ImageUtils.find_all("ap_30") if difficulty == "Very Hard": MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30") elif difficulty == "Extreme": MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30") elif difficulty == "Extreme+": MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30") Game.wait(3.0) while ImageUtils.wait_vanish("ap_30", timeout = 3) is False: if difficulty == "Very Hard": MouseUtils.move_and_click_point(ap_locations[0][0], ap_locations[0][1], "ap_30") elif difficulty == "Extreme": MouseUtils.move_and_click_point(ap_locations[1][0], ap_locations[1][1], "ap_30") elif difficulty == "Extreme+": MouseUtils.move_and_click_point(ap_locations[2][0], ap_locations[2][1], "ap_30") Game.wait(3.0) tries -= 1 if tries <= 0: if difficulty == "Extreme+": ImageUtils.generate_alert("You did not unlock Extreme+ yet!") raise GuildWarsException("You did not unlock Extreme+ yet!") else: raise GuildWarsException("There appears to be a deadzone issue that the bot failed 10 times to resolve. Please refresh the page and try again.") return None else: MessageLog.print_message(f"\n[GUILD.WARS] Now proceeding to farm Nightmares.") # Click on the banner to farm Nightmares. if difficulty != "NM150": MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle") if not ImageUtils.wait_vanish("guild_wars_nightmare", timeout = 10): MouseUtils.move_and_click_point(raid_battle_locations[0][0], raid_battle_locations[0][1], "event_raid_battle") else: MessageLog.print_message(f"\n[GUILD.WARS] Now hosting NM150 now...") Game.find_and_click_button("guild_wars_nightmare_150") if not ImageUtils.wait_vanish("guild_wars_nightmare_150", timeout = 10): Game.find_and_click_button("guild_wars_nightmare_150") if ImageUtils.confirm_location("guild_wars_nightmare"): Game.find_and_click_button("start") if difficulty != "NM150" and ImageUtils.confirm_location("guild_wars_nightmare"): nightmare_locations = ImageUtils.find_all("guild_wars_nightmares") # If today is the first/second day of Guild Wars, only NM90 will be available. if ImageUtils.confirm_location("guild_wars_nightmare_first_day", tries = 3): MessageLog.print_message(f"[GUILD.WARS] Today is the first/second day so hosting NM90.") Game.find_and_click_button("ok") # Alert the user if they lack the meat to host this and stop the bot. if not ImageUtils.wait_vanish("ok", timeout = 30): ImageUtils.generate_alert("You do not have enough meat to host this NM90!") raise GuildWarsException("You do not have enough meat to host this NM90!") # If it is not the first/second day of Guild Wars, that means that other difficulties are now available. elif difficulty == "NM90": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM90 now...") MouseUtils.move_and_click_point(nightmare_locations[0][0], nightmare_locations[0][1], "guild_wars_nightmares") elif difficulty == "NM95": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM95 now...") MouseUtils.move_and_click_point(nightmare_locations[1][0], nightmare_locations[1][1], "guild_wars_nightmares") elif difficulty == "NM100": MessageLog.print_message(f"[GUILD.WARS] Now hosting NM100 now...") MouseUtils.move_and_click_point(nightmare_locations[2][0], nightmare_locations[2][1], "guild_wars_nightmares") else: # If there is not enough meat to host, host Extreme+ instead. MessageLog.print_message(f"\n[GUILD.WARS] User lacks meat to host the Nightmare. Hosting Extreme+ instead...") if difficulty != "NM150": Game.find_and_click_button("close") else: Game.find_and_click_button("cancel") # Click on the banner to farm meat. Game.find_and_click_button("guild_wars_meat") if ImageUtils.confirm_location("guild_wars_meat"): MessageLog.print_message(f"[GUILD.WARS] Now hosting Extreme+ now...") Game.find_and_click_button("guild_wars_meat_extreme+") # Alert the user if they did not unlock Extreme+ and stop the bot. if not ImageUtils.wait_vanish("guild_wars_meat_extreme+", timeout = 30): ImageUtils.generate_alert("You did not unlock Extreme+ yet!") raise GuildWarsException("You did not unlock Extreme+ yet!") return None
def _choose_action() -> str: """Chooses the next action to take for the current Arcarum expedition. Returns: (str): The action to take next. """ from bot.game import Game # Determine what action to take. MessageLog.print_message( f"\n[ARCARUM] Now determining what action to take...") # Wait a second in case the "Do or Die" animation plays. Game.wait(1) tries = 3 while tries > 0: # Prioritise any enemies/chests/thorns that are available on the current node. arcarum_actions = ImageUtils.find_all("arcarum_action") if len(arcarum_actions) > 0: MouseUtils.move_and_click_point(arcarum_actions[0][0], arcarum_actions[0][1], "arcarum_action") Game.wait(2) Game.check_for_captcha() if ImageUtils.confirm_location("arcarum_party_selection", tries=1): return "Combat" elif Game.find_and_click_button("ok", tries=1): return "Claimed Treasure/Keythorn" else: return "Claimed Spirethorn/No Action" # Clear any detected Treasure popup after claiming a chest. MessageLog.print_message( f"[ARCARUM] No action found for the current node. Looking for Treasure popup..." ) if ImageUtils.confirm_location("arcarum_treasure", tries=1): Game.find_and_click_button("ok") return "Claimed Treasure" # Next, determine if there is a available node to move to. Any bound monsters should have been destroyed by now. MessageLog.print_message( f"[ARCARUM] No Treasure popup detected. Looking for an available node to move to..." ) if Game.find_and_click_button("arcarum_node", tries=1): Game.wait(1) return "Navigating" # Check if a Arcarum boss has appeared. This is after checking for available actions and before searching for a node to move to avoid false positives. if Arcarum._check_for_boss(): return "Boss Detected" # Next, attempt to navigate to a node that is occupied by mob(s). MessageLog.print_message( f"[ARCARUM] No available node to move to. Looking for nodes with mobs on them..." ) if Game.find_and_click_button( "arcarum_mob", tries=1) or Game.find_and_click_button( "arcarum_red_mob", tries=1): Game.wait(1) return "Navigating" # If all else fails, see if there are any unclaimed chests, like the ones spawned by a random special event that spawns chests on all nodes. MessageLog.print_message( f"[ARCARUM] No nodes with mobs on them. Looking for nodes with chests on them..." ) if Game.find_and_click_button( "arcarum_silver_chest", tries=1) or Game.find_and_click_button( "arcarum_gold_chest", tries=1): Game.wait(1) return "Navigating" tries -= 1 MessageLog.print_message( f"[ARCARUM] No action can be taken. Defaulting to moving to the next area." ) return "Next Area"
def 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
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 find_summon(summon_list: List[str], summon_element_list: List[str], home_button_x: int, home_button_y: int, custom_confidence: float = 0.8, suppress_error: bool = False): """Find the location of the specified Summon. Will attempt to scroll the screen down to see more Summons if the initial screen position yielded no matches. Args: summon_list (List[str]): List of names of the Summon image's file name in /images/summons/ folder. summon_element_list (List[str]): List of names of the Summon element image file in the /images/buttons/ folder. home_button_x (int): X coordinate of where the center of the Home Button is. home_button_y (int): Y coordinate of where the center of the Home Button is. custom_confidence (float, optional): Accuracy threshold for matching. Defaults to 0.8. suppress_error (bool, optional): Suppresses template matching error if True. Defaults to False. Returns: (Tuple[int, int]): Tuple of coordinates of where the center of the Summon is located if image matching was successful. Otherwise, return None. """ from bot.game import Game if Settings.debug_mode: MessageLog.print_message( f"[DEBUG] Received the following list of Summons to search for: {str(summon_list)}" ) MessageLog.print_message( f"[DEBUG] Received the following list of Elements: {str(summon_element_list)}" ) last_summon_element = "" summon_index = 0 # Make sure that the bot is at the Summon Selection screen. tries = 10 while not ImageUtils.confirm_location("select_a_summon"): Game.find_and_click_button('reload') tries -= 1 if tries <= 0 and ImageUtils.confirm_location("select_a_summon", tries=1) is False: raise Exception("Could not reach the Summon Selection screen.") # Determine if all the summon elements are the same or not. This will influence whether or not the bot needs to change elements in repeated runs. ImageUtils._summon_selection_same_element = all( element == summon_element_list[0] for element in summon_element_list) while True: # Perform first time setup by selecting the correct summon element. if ImageUtils._summon_selection_first_run or ImageUtils._summon_selection_same_element is False: current_summon_element: str = summon_element_list[summon_index] if current_summon_element != last_summon_element: Game.find_and_click_button( f"summon_{current_summon_element}") last_summon_element = current_summon_element ImageUtils._summon_selection_first_run = False summon_index = 0 while summon_index < len(summon_list): # Now try and find the Summon at the current index. template: numpy.ndarray = cv2.imread( f"{ImageUtils._current_dir}/images/summons/{summon_list[summon_index]}.jpg", 0) # Crop the summon template image so that plus marks would not potentially obscure any match. height, width = template.shape template = template[0:height, 0:width - 40] result_flag: bool = ImageUtils._match(template, custom_confidence) if result_flag: if Settings.debug_mode: MessageLog.print_message( f"[SUCCESS] Found {summon_list[summon_index].upper()} Summon at {ImageUtils._match_location}." ) return ImageUtils._match_location else: if suppress_error is False: MessageLog.print_message( f"[WARNING] Could not locate {summon_list[summon_index].upper()} Summon." ) summon_index += 1 # If the bot reached the bottom of the page, scroll back up to the top and start searching for the next Summon. if ImageUtils.find_button("bottom_of_summon_selection", tries=1) is not None: MessageLog.print_message( f"[WARNING] Bot has reached the bottom of the page and found no suitable Summons. Resetting Summons now..." ) return None # If matching failed, scroll the screen down to see more Summons. from utils.mouse_utils import MouseUtils MouseUtils.scroll_screen(home_button_x, home_button_y - 50, -700) Game.wait(1.0)