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 start() -> int: """Starts the process of completing Arcarum expeditions. Returns: (int): Number of runs completed. """ from bot.game import Game runs_completed = 0 while runs_completed < Settings.item_amount_to_farm: Arcarum._navigate_to_map() while True: action = Arcarum._choose_action() MessageLog.print_message( f"[ARCARUM] Action to take will be: {action}") if action == "Combat": # Start Combat Mode. if Game.find_party_and_start_mission( Settings.group_number, Settings.party_number): if ImageUtils.confirm_location("elemental_damage", tries=1): raise ArcarumException( "Encountered an important mob for Arcarum and the selected party does not conform to the enemy's weakness. Perhaps you would like to do this battle yourself?" ) elif ImageUtils.confirm_location("arcarum_restriction", tries=1): raise ArcarumException( "Encountered a party restriction for Arcarum. Perhaps you would like to complete this section by yourself?" ) if CombatMode.start_combat_mode(): Game.collect_loot(is_completed=False, skip_info=True) Game.find_and_click_button("expedition") elif action == "Navigating": # Move to the next available node. Game.find_and_click_button("move") elif action == "Next Area": # Either navigate to the next area or confirm the expedition's conclusion. if Game.find_and_click_button("arcarum_next_stage"): Game.find_and_click_button("ok") MessageLog.print_message( f"[ARCARUM] Moving to the next area...") elif Game.find_and_click_button("arcarum_checkpoint"): Game.find_and_click_button("arcarum") MessageLog.print_message( f"[ARCARUM] Expedition is complete.") runs_completed += 1 Game.wait(1) Game.check_for_skyscope() break elif action == "Boss Detected": MessageLog.print_message( f"[ARCARUM] Boss has been detected. Stopping the bot.") raise ArcarumException( "Boss has been detected. Stopping the bot.") Game.wait(1) return runs_completed
def _navigate_to_map() -> bool: """Navigates to the specified Arcarum expedition. Returns: (bool): True if the bot was able to start/resume the expedition. False otherwise. """ from bot.game import Game if Arcarum._first_run: MessageLog.print_message( f"\n[ARCARUM] Now beginning navigation to {Arcarum._expedition}." ) Game.go_back_home() # Navigate to the Arcarum banner. tries = 5 while tries > 0: if Game.find_and_click_button("arcarum_banner", tries=1) is False: MouseUtils.scroll_screen_from_home_button(-300) tries -= 1 if tries <= 0: raise ArcarumException( "Failed to navigate to Arcarum from the Home screen." ) else: break Arcarum._first_run = False else: Game.wait(4) # Now make sure that the Extreme difficulty is selected. Game.wait(1) # Confirm the completion popup if it shows up. if ImageUtils.confirm_location("arcarum_expedition", tries=1): Game.find_and_click_button("ok") Game.find_and_click_button("arcarum_extreme") # Finally, navigate to the specified map to start it. MessageLog.print_message( f"[ARCARUM] Now starting the specified expedition: {Arcarum._expedition}." ) formatted_map_name = Arcarum._expedition.lower().replace(" ", "_") if Game.find_and_click_button(f"arcarum_{formatted_map_name}", tries=5) is False: # Resume the expedition if it is already in-progress. Game.find_and_click_button("arcarum_exploring") elif ImageUtils.confirm_location("arcarum_departure_check"): MessageLog.print_message( f"[ARCARUM] Now using 1 Arcarum ticket to start this expedition..." ) result_check = Game.find_and_click_button("start_expedition") Game.wait(6) return result_check elif Game.find_and_click_button("resume"): Game.wait(3) return True else: raise ArcarumException( "Failed to encounter the Departure Check to confirm starting the expedition." )
def start(first_run: bool) -> int: """Starts the process to complete a run for Proving Grounds Farming Mode and returns the number of items detected. Args: first_run (bool): Flag that determines whether or not to run the navigation process again. Should be False if the Farming Mode supports the "Play Again" feature for repeated runs. Returns: (int): Number of runs completed. """ from bot.game import Game runs_completed: int = 0 # Start the navigation process. if first_run and ProvingGrounds._first_time: ProvingGrounds._navigate() elif ProvingGrounds._first_time and Game.find_and_click_button( "play_again"): MessageLog.print_message( "\n[PROVING.GROUNDS] Starting Proving Grounds Mission again..." ) # Check for AP. Game.check_for_ap() # Check if the bot is at the Summon Selection screen. if (first_run or ProvingGrounds._first_time) and ImageUtils.confirm_location( "proving_grounds_summon_selection", tries=30): summon_check = Game.select_summon(Settings.summon_list, Settings.summon_element_list) if summon_check: Game.wait(2.0) # No need to select a Party. Just click "OK" to start the mission and confirming the selected summon. Game.find_and_click_button("ok") Game.wait(2.0) MessageLog.print_message( "\n[PROVING.GROUNDS] Now starting Mission for Proving Grounds..." ) Game.find_and_click_button("proving_grounds_start") # Now start Combat Mode and detect any item drops. if CombatMode.start_combat_mode(): runs_completed = Game.collect_loot(is_completed=False) # Click the "Next Battle" button if there are any battles left. if Game.find_and_click_button( "proving_grounds_next_battle"): MessageLog.print_message( "\n[PROVING.GROUNDS] Moving onto the next battle for Proving Grounds..." ) Game.find_and_click_button("ok") ProvingGrounds._first_time = False elif first_run is False and ProvingGrounds._first_time is False: # No need to select a Summon again as it is reused. if CombatMode.start_combat_mode(): runs_completed = Game.collect_loot(is_completed=False) # Click the "Next Battle" button if there are any battles left. if Game.find_and_click_button("proving_grounds_next_battle"): MessageLog.print_message( "\n[PROVING.GROUNDS] Moving onto the next battle for Proving Grounds..." ) Game.find_and_click_button("ok") else: # Otherwise, all battles for the Mission has been completed. Collect the completion rewards at the end. MessageLog.print_message( "\n[PROVING.GROUNDS] Proving Grounds Mission has been completed." ) Game.find_and_click_button("event") # Check for friend request. Game.find_and_click_button("cancel", tries=1, suppress_error=True) # Check for trophy. Game.find_and_click_button("close", tries=1, suppress_error=True) Game.wait(2.0) Game.find_and_click_button("proving_grounds_open_chest") if ImageUtils.confirm_location( "proving_grounds_completion_loot"): MessageLog.print_message( "\n[PROVING.GROUNDS] Completion rewards has been acquired." ) runs_completed = Game.collect_loot( is_completed=True, skip_popup_check=True) # Reset the First Time flag so the bot can select a Summon and select the Mission again. if Settings.item_amount_farmed < Settings.item_amount_to_farm: ProvingGrounds._first_time = True else: raise ProvingGroundsException( "Failed to detect the Completion Loot screen for completing this Proving Grounds mission." ) else: raise ProvingGroundsException( "Failed to arrive at the Summon Selection screen.") return runs_completed