diff --git a/.gitignore b/.gitignore index 58533cd..56cec46 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ DQconfig.ini PARconfig.ini +PyAutoRaid.log diff --git a/Modules/PyAutoRaid.py b/Modules/PyAutoRaid.py index 3daf878..660c14f 100644 --- a/Modules/PyAutoRaid.py +++ b/Modules/PyAutoRaid.py @@ -12,10 +12,15 @@ import threading from screeninfo import get_monitors from tkinter import messagebox +from tkinter import scrolledtext from tkinter import ttk from tkinter import * from ttkthemes import ThemedTk import pyscreeze +from faction_wars.FactionWars import FactionWarsCommand +from dungeons.IronTwins import IronTwinsCommand +from doom_tower.DoomTower import DoomTowerCommand + pyscreeze.USE_IMAGE_NOT_FOUND_EXCEPTION = False # Configure logging logging.basicConfig( @@ -773,11 +778,14 @@ def __init__(self, master): self.AS_bought = 0 self.MS_bought = 0 self.manual_run_triggered = False - + self.command_registry = { 'rewards': RewardsCommand(self), 'daily_ten_classic_arena': DailyTenClassicArenaCommand(self), 'clanboss': ClanBossCommand(self), + 'faction_wars': FactionWarsCommand(self, logger), + 'iron_twins': IronTwinsCommand(self, logger), + 'doom_tower': DoomTowerCommand(self, logger) # Add other commands as needed } @@ -865,20 +873,43 @@ def Check_os(self): def find_raid_path(self): try: + logger.info("Starting focused search for Raid.exe...") appdata_local = os.path.join(os.environ['LOCALAPPDATA']) raid_feature = "Raid.exe" - for root, dirs, files in os.walk(appdata_local): - if raid_feature in dirs or raid_feature in files: + + # Most specific likely path + current_path = os.path.join(appdata_local, "PlariumPlay", "StandAloneApps", "raid-shadow-legends") + + # Step 1: Check if the likely path exists; move backward if it doesn't + while not os.path.exists(current_path) and current_path != appdata_local: + logger.debug(f"Path not found: {current_path}. Moving to parent directory.") + current_path = os.path.dirname(current_path) + + if not os.path.exists(current_path): + logger.error("No valid path found starting from likely paths.") + self.steps["Raid_path"] = "False" + sys.exit(1) + + logger.debug(f"Valid path found: {current_path}. Starting recursive search here.") + + # Step 2: Perform a recursive search starting from the valid path + for root, dirs, files in os.walk(current_path, topdown=True): + # Check for the target file + if raid_feature in files: raidloc = os.path.join(root, raid_feature) - logging.debug(f"Found Raid.exe installed at {raidloc}") + logger.debug(f"Found Raid.exe at {raidloc}") self.steps["Raid_path"] = "True" return raidloc + + # Step 3: If not found, log an error self.steps["Raid_path"] = "False" - logging.error("Raid.exe was not found.") + logger.error("Raid.exe was not found after recursive search.") sys.exit(1) + except Exception as e: logger.error(f"Error in find_raid_path: {e}") + def get_asset_path(self): try: # Start with the directory of the current script @@ -1009,19 +1040,33 @@ def get_screen_info(self): self.width = m.width self.height = m.height main = m.is_primary - if self.width != 1920 or self.height != 1080: - tkinter.messagebox.showerror( - "Warning", - "Your Screen pixel is not 1920 by 1080. This may cause issues", - ) - logger.warning("Screen resolution is not 1920x1080.") - if main == True: + + # Log screen resolution + logger.info(f"Detected screen resolution: width={self.width}, height={self.height}, primary={main}") + + if main: # Only consider the primary monitor + if self.width != 1920 or self.height != 1080: + logger.warning("Screen resolution is not 1920x1080. This may cause issues.") + tkinter.messagebox.showerror( + "Warning", + "Your screen resolution is not 1920x1080. This may cause issues.", + ) + else: + logger.info("Screen resolution is 1920x1080.") + center_width = int((self.width / 2) - 450) center_height = int((self.height / 2) - 300) - logger.info(f"Screen info obtained: width={self.width}, height={self.height}") + logger.info(f"Screen info obtained: center_width={center_width}, center_height={center_height}") return (center_width, center_height) + + # If no primary monitor was detected + logger.error("No primary monitor detected.") + raise RuntimeError("No primary monitor detected.") + except Exception as e: logger.error(f"Error in get_screen_info: {e}") + raise + def window_sizing_centering(self): try: @@ -1044,10 +1089,12 @@ def initiate_raid(self, not_open): try: self.window_sizing_centering() exit_add_image = os.path.join(self.asset_path, "exitAdd.png") + home_battle_button = os.path.join(self.asset_path, "battleBTN.png") + while True: try: # Attempt to locate the image - if pyautogui.locateOnScreen(exit_add_image, confidence=0.7) is not None: + if pyautogui.locateOnScreen(exit_add_image, confidence=0.7) is not None or pyautogui.locateOnScreen(home_battle_button, confidence=0.7): logger.info("Image found. Breaking the loop.") break else: @@ -1137,7 +1184,6 @@ def run(self): os.system("taskkill /f /im Raid.exe") break -# GUI class with error handling and logging class GUI: def __init__(self, master): try: @@ -1156,7 +1202,7 @@ def __init__(self, master): # Creating a ttk Frame which will contain all other widgets main_frame = ttk.Frame(master) main_frame.pack(fill=tkinter.BOTH, expand=True) - config_keys = ['rewards', 'daily_ten_classic_arena', 'clanboss'] + config_keys = ['rewards', 'daily_ten_classic_arena', 'clanboss', 'faction_wars', 'iron_twins', 'doom_tower'] # Automated Mode Checkbox self.automated_mode = tkinter.IntVar() if settings_config.get("automated_mode") == 'True': @@ -1177,7 +1223,7 @@ def checkbox_callback(var_name, index, mode, config_key, var): # Other Checkboxes self.checkbox_texts = [ - "Collect Rewards", "Ten Classic Arena Battles", "Clan Boss", + "Collect Rewards", "Ten Classic Arena Battles", "Clan Boss", "Faction Wars", "Iron Twins", "Doom Tower" ] self.checkboxes = [] self.vars = [] @@ -1200,6 +1246,18 @@ def checkbox_callback(var_name, index, mode, config_key, var): self.btn_quit_all = ttk.Button(main_frame, text="Quit All", command=self.quit_all) self.btn_quit_all.grid(row=len(self.checkbox_texts) + 3, column=1, padx=10, pady=(5, 5), sticky="E") + + # Separator above the log box + self.separator2 = ttk.Separator(main_frame, orient='horizontal') + self.separator2.grid(row=len(self.checkbox_texts) + 4, column=0, columnspan=2, padx=10, pady=5, sticky="EW") + + # Log Text Box + self.log_text = scrolledtext.ScrolledText(main_frame, wrap=tkinter.WORD, height=10, state="disabled") + self.log_text.grid(row=len(self.checkbox_texts) + 5, column=0, columnspan=2, padx=10, pady=(5, 10), sticky="EW") + + # Redirect logs to the text box + self.redirect_logs() + logger.info("GUI initialized successfully.") except Exception as e: logger.error(f"Error initializing GUI: {e}") @@ -1237,6 +1295,24 @@ def timer_thread(self): logger.info("Timer thread started.") except Exception as e: logger.error(f"Error in timer_thread: {e}") + + def redirect_logs(self): + """Redirect log output to the text box.""" + class TextHandler(logging.Handler): + def __init__(self, widget): + super().__init__() + self.widget = widget + + def emit(self, record): + msg = self.format(record) + self.widget.config(state="normal") + self.widget.insert(tkinter.END, msg + "\n") + self.widget.config(state="disabled") + self.widget.see(tkinter.END) + + handler = TextHandler(self.log_text) + handler.setFormatter(logging.Formatter("%(asctime)s - %(levelname)s - %(message)s")) + logger.addHandler(handler) def on_closing(): try: diff --git a/Modules/doom_tower/DoomTower.py b/Modules/doom_tower/DoomTower.py new file mode 100644 index 0000000..f8a2e8a --- /dev/null +++ b/Modules/doom_tower/DoomTower.py @@ -0,0 +1,118 @@ +import os +import time +import pyautogui + +class Command: + def execute(self): + pass + +class DoomTowerCommand(Command): + def __init__(self, app, logger): + self.app = app + self.logger = logger + + def execute(self): + try: + self.logger.info("Starting Doom Tower task.") + + # Define image paths + battle_btn_image = os.path.join(self.app.asset_path, "battleBTN.png") + doom_tower_image = os.path.join(self.app.asset_path, "doomTower.png") + doom_tower_next_stage = os.path.join(self.app.asset_path, "doomTowerNextStage.png") + doom_tower_start_battle = os.path.join(self.app.asset_path, "doomTowerStartBattle.png") + doom_tower_stages_screen = os.path.join(self.app.asset_path, "doomTowerScreen.png") + in_battle_image = os.path.join(self.app.asset_path, "inBattle.png") + in_mutli_battle_image = os.path.join(self.app.asset_path, "turnOffMultiBattle.png") + mutli_battle_complete_image = os.path.join(self.app.asset_path, "mutliBattleComplete.png") + + self.logger.info("Attempting to close any existing pop-ups.") + self.app.delete_popup() + + # Navigate to battle screen + time.sleep(2) + self.click_image(battle_btn_image, "Battle button") + + # Navigate to Doom Tower + pyautogui.moveTo(960, 540) + pyautogui.dragRel(-600, 0, duration=0.5) + time.sleep(2) + self.click_image(doom_tower_image, "Doom Tower button") + time.sleep(2) + + # Loop through this to complete Auto Climb and then Tower - Or replay failed stages + while pyautogui.locateOnScreen(doom_tower_next_stage, confidence=0.8): + self.click_image(doom_tower_next_stage, "Doom Tower Next Stage") + + # If Wave stage Start Multi Battle + x, y = pyautogui.locateCenterOnScreen(doom_tower_start_battle, confidence=0.8) + pyautogui.click(x, y) + self.logger.info(f"Clicked on Doom Tower Start Battle at coordinates ({x}, {y}).") + time.sleep(2) + + if pyautogui.locateOnScreen(doom_tower_start_battle, confidence=0.8): + self.logger.info("Must not have enough keys. Doom Tower Comlete") + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(1) + + + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8) or pyautogui.locateOnScreen(in_mutli_battle_image, confidence=0.8): + self.logger.info("Waiting for the battle results.") + time.sleep(10) + while pyautogui.locateOnScreen(mutli_battle_complete_image, confidence=0.8): + # Back to doom tower to check if the boss is ready or failed run + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(1) + + if not pyautogui.locateOnScreen(doom_tower_stages_screen, confidence=0.7): + self.logger.info("Can't find doom tower stages screen.") + + # If Boss Stage Click Boss Right Hand Side + if pyautogui.locateOnScreen(doom_tower_stages_screen, confidence=0.7): + self.logger.info("Found doom tower stages screen. Clicking Right Side") + pyautogui.click(1250, 500) + time.sleep(2) + + # Click on boss that is stage 120 + if pyautogui.locateOnScreen(doom_tower_stages_screen, confidence=0.7): + self.logger.info("Found doom tower stages screen. Clicking Middle (for stage 120)") + pyautogui.click(950, 500) + time.sleep(2) + + self.click_image(doom_tower_start_battle, "Doom Tower Start Battle") + time.sleep(5) + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8): + self.logger.info("Waiting for the battle results.") + time.sleep(10) + + pyautogui.press("esc") + self.app.back_to_bastion() + self.logger.info("Doom Tower task completed successfully.") + except Exception as e: + self.logger.error(f"Error in DoomTowerCommand: {e}", exc_info=True) + self.app.back_to_bastion() + + def click_image(self, imagePath, description, retry=True): + """Helper to click an image on screen.""" + if retry: + # Retry until the image is found and clicked + while pyautogui.locateOnScreen(imagePath, confidence=0.8): + x, y = pyautogui.locateCenterOnScreen(imagePath, confidence=0.8) + pyautogui.click(x, y) + self.logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + time.sleep(2) + else: + # Single attempt to click the image + location = pyautogui.locateOnScreen(imagePath, confidence=0.8) + if location: + x, y = pyautogui.locateCenterOnScreen(imagePath, confidence=0.8) + pyautogui.click(x, y) + time.sleep(2) + self.logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + else: + self.logger.warning(f"{description} not found for a single click attempt.") diff --git a/Modules/dungeons/IronTwins.py b/Modules/dungeons/IronTwins.py new file mode 100644 index 0000000..4ff341b --- /dev/null +++ b/Modules/dungeons/IronTwins.py @@ -0,0 +1,96 @@ +import os +import time +import pyautogui + +class Command: + def execute(self): + pass + +class IronTwinsCommand(Command): + def __init__(self, app, logger): + self.app = app + self.logger = logger + + def execute(self): + try: + self.logger.info("Starting Iron Twinstask.") + + # Define image paths + battle_btn_image = os.path.join(self.app.asset_path, "battleBTN.png") + dungeons_image = os.path.join(self.app.asset_path, "dungeons.png") + iron_twins_image = os.path.join(self.app.asset_path, "ironTwinsDungeon.png") + iron_twins_stage_15_image = os.path.join(self.app.asset_path, "ironTwinsStage15.png") + multi_battle_image = os.path.join(self.app.asset_path, "multiBattleButton.png") + start_stage_multi_battle_image = os.path.join(self.app.asset_path, "startMultiBattle.png") + in_battle_image = os.path.join(self.app.asset_path, "inBattle.png") + in_mutli_battle_image = os.path.join(self.app.asset_path, "turnOffMultiBattle.png") + mutli_battle_complete_image = os.path.join(self.app.asset_path, "mutliBattleComplete.png") + + self.logger.info("Attempting to close any existing pop-ups.") + self.app.delete_popup() + + # Navigate to battle screen + self.click_image(battle_btn_image, "Battle button") + + # Navigate to Dungeons + self.click_image(dungeons_image, "Dungeons button") + + # Open Iron Twins dungeon + self.click_image(iron_twins_image, "Iron Twins dungeon button") + + # Select Stage 15 + while pyautogui.locateOnScreen(iron_twins_stage_15_image, confidence=0.8): + buttons = list(pyautogui.locateAllOnScreen(iron_twins_stage_15_image, confidence=0.8)) + if buttons: + # Find the button with the largest y-coordinate + bottom_button = max(buttons, key=lambda b: b.top) + bottom_x, bottom_y = pyautogui.center(bottom_button) + + # Click the battle button + pyautogui.click(bottom_x, bottom_y) + self.logger.info(f"Clicked on the highest stage Battle button at coordinates: ({bottom_x}, {bottom_y}).") + time.sleep(1) + + # Check if the battle button is still visible + if pyautogui.locateOnScreen(iron_twins_stage_15_image, confidence=0.8): + self.logger.warning("Battle button is still visible. Pressing escape to go back.") + pyautogui.press("esc") + time.sleep(1) + break + else: + self.logger.warning("No Battle button found.") + break + # Start Multi Battle + while pyautogui.locateOnScreen(multi_battle_image, confidence=0.8): + self.logger.info("Multi-battle option detected. Starting multi-battle.") + x, y = pyautogui.locateCenterOnScreen(multi_battle_image, confidence=0.8) + pyautogui.click(x, y) + time.sleep(1) + x, y = pyautogui.locateCenterOnScreen(start_stage_multi_battle_image, confidence=0.8) + pyautogui.click(x, y) + time.sleep(1) + + + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8) or pyautogui.locateOnScreen(in_mutli_battle_image, confidence=0.8): + self.logger.info("Waiting for the battle results.") + time.sleep(10) + + while pyautogui.locateOnScreen(mutli_battle_complete_image, confidence=0.8): + self.app.back_to_bastion() + + + + self.app.back_to_bastion() + self.logger.info("Iron Twins task completed successfully.") + except Exception as e: + self.logger.error(f"Error in IronTwinsCommand: {e}", exc_info=True) + self.app.back_to_bastion() + + def click_image(self, image_path, description): + """Helper to click an image on screen.""" + while pyautogui.locateOnScreen(image_path, confidence=0.8): + x, y = pyautogui.locateCenterOnScreen(image_path, confidence=0.8) + pyautogui.click(x, y) + self.logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + time.sleep(2) \ No newline at end of file diff --git a/Modules/faction_wars/FactionWars.py b/Modules/faction_wars/FactionWars.py new file mode 100644 index 0000000..77b3d5a --- /dev/null +++ b/Modules/faction_wars/FactionWars.py @@ -0,0 +1,179 @@ +import os +import time +import pyautogui +import logging + +class Command: + def execute(self): + pass + +class FactionWarsCommand(Command): + def __init__(self, app, logger): + self.app = app + self.logger = logger + + def execute(self): + try: + self.logger.info("Starting Faction Wars task.") + faction_positions_right = [ + {"name": "Dark Elf", "x": 560, "y": 650}, + {"name": "High Elf", "x": 680, "y": 415}, + {"name": "Sacred Order", "x": 760, "y": 520}, + {"name": "Barbarian", "x": 870, "y": 660}, + {"name": "Banner Lords", "x": 960, "y": 430}, + {"name": "Dwarves", "x": 1080, "y": 530}, + {"name": "Shadowkin", "x": 1250, "y": 650}, + {"name": "Sylvan Watchers", "x": 1350, "y": 510}, + ] + faction_position_two = [ + {"name": "Lizardmen", "x": 670, "y": 530}, + {"name": "Knight Revenant", "x": 800, "y": 660}, + {"name": "Skinwalkers", "x": 800, "y": 400}, + {"name": "Undead Hordes", "x": 950, "y": 520}, + {"name": "Demonspawn", "x": 1060, "y": 420}, + {"name": "Ogryn Tribes", "x": 1180, "y": 650}, + {"name": "Orcs", "x": 1260, "y": 530}, + ] + + # Define image paths + battle_btn_image = os.path.join(self.app.asset_path, "battleBTN.png") + faction_wars_image = os.path.join(self.app.asset_path, "factionWars.png") + stage_open_image = os.path.join(self.app.asset_path, "stageStart.png") + faction_wars_multi_battle_image = os.path.join(self.app.asset_path, "multiBattleButton.png") + start_stage_multi_battle_image = os.path.join(self.app.asset_path, "startMultiBattle.png") + mutli_battle_complete_image = os.path.join(self.app.asset_path, "mutliBattleComplete.png") + in_battle_image = os.path.join(self.app.asset_path, "inBattle.png") + in_mutli_battle_image = os.path.join(self.app.asset_path, "turnOffMultiBattle.png") + + self.logger.info("Attempting to close any existing pop-ups.") + self.app.delete_popup() + + # Go to battle screen + self.click_image(battle_btn_image, "Battle button") + + # Click on Faction Wars + self.click_image(faction_wars_image, "Faction Wars option") + + # Process factions on the right + self.logger.info("Swiping all the way to the right.") + pyautogui.moveTo(960, 540) + pyautogui.dragRel(-600, 0, duration=0.5) + time.sleep(1) + + for position in faction_positions_right: + x, y, name = position["x"], position["y"], position["name"] + self.logger.debug(f"Attempting to click on faction {name} at ({x}, {y}).") + pyautogui.click(x, y) + time.sleep(1) + self.start_stage( + stage_open_image, + faction_wars_multi_battle_image, + start_stage_multi_battle_image, + in_battle_image, + in_mutli_battle_image, + mutli_battle_complete_image, + ) + + # Swipe all the way to the left and process remaining factions + self.logger.info("Swiping all the way to the left.") + pyautogui.moveTo(960, 540) + pyautogui.dragRel(1600, 0, duration=0.5) + time.sleep(1) + + for position in faction_position_two: + x, y, name = position["x"], position["y"], position["name"] + self.logger.debug(f"Attempting to click on faction {name} at ({x}, {y}).") + pyautogui.click(x, y) + time.sleep(1) + self.start_stage( + stage_open_image, + faction_wars_multi_battle_image, + start_stage_multi_battle_image, + in_battle_image, + in_mutli_battle_image, + mutli_battle_complete_image, + ) + + self.app.back_to_bastion() + self.logger.info("Faction Wars task completed successfully.") + except Exception as e: + self.logger.error(f"Error in FactionWarsCommand: {e}", exc_info=True) + self.app.back_to_bastion() + + def click_image(self, imagePath, description, retry=True): + """Helper to click an image on screen.""" + if retry: + # Retry until the image is found and clicked + while pyautogui.locateOnScreen(imagePath, confidence=0.8): + x, y = pyautogui.locateCenterOnScreen(imagePath, confidence=0.8) + pyautogui.click(x, y) + self.logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + time.sleep(2) + else: + # Single attempt to click the image + location = pyautogui.locateOnScreen(imagePath, confidence=0.8) + if location: + x, y = pyautogui.locateCenterOnScreen(imagePath, confidence=0.8) + pyautogui.click(x, y) + time.sleep(2) + self.logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + else: + self.logger.warning(f"{description} not found for a single click attempt.") + + def start_stage( + self, + stage_open_image, + faction_wars_multi_battle_image, + start_stage_multi_battle_image, + in_battle_image, + in_mutli_battle_image, + mutli_battle_complete_image, + ): + """Logic to start a stage.""" + while pyautogui.locateOnScreen(stage_open_image, confidence=0.8): + self.logger.info("Stage start button detected. Preparing to select stage.") + buttons = list(pyautogui.locateAllOnScreen(stage_open_image, confidence=0.8)) + if buttons: + # Find the button with the largest y-coordinate + bottom_button = max(buttons, key=lambda b: b.top) + bottom_x, bottom_y = pyautogui.center(bottom_button) + + # Click the battle button + pyautogui.click(bottom_x, bottom_y) + self.logger.info(f"Clicked on the highest stage Battle button at coordinates: ({bottom_x}, {bottom_y}).") + time.sleep(1) + + # Check if the battle button is still visible + if pyautogui.locateOnScreen(stage_open_image, confidence=0.8): + self.logger.warning("Battle button is still visible. Pressing escape to go back.") + pyautogui.press("esc") + time.sleep(1) + break + else: + self.logger.warning("No Battle button found.") + break + + # Check for the multi-battle option + while pyautogui.locateOnScreen(faction_wars_multi_battle_image, confidence=0.8): + self.logger.info("Multi-battle option detected. Starting multi-battle.") + self.click_image(faction_wars_multi_battle_image, "Multi-battle button", False) + self.click_image(start_stage_multi_battle_image, "Start Multi-battle") + time.sleep(1) + + else: + self.logger.error("Multi-battle option not detected.") + + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8) or pyautogui.locateOnScreen(in_mutli_battle_image, confidence=0.8): + self.logger.info("Waiting for the battle results.") + time.sleep(10) + + # Exit multi-battle and return to faction selection + while pyautogui.locateOnScreen(mutli_battle_complete_image, confidence=0.8): + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(2) + self.logger.info("Returning to faction selection.") \ No newline at end of file diff --git a/assets/doomTower.png b/assets/doomTower.png new file mode 100644 index 0000000..b64277e Binary files /dev/null and b/assets/doomTower.png differ diff --git a/assets/doomTowerNextStage.png b/assets/doomTowerNextStage.png new file mode 100644 index 0000000..b4bb829 Binary files /dev/null and b/assets/doomTowerNextStage.png differ diff --git a/assets/doomTowerScreen.png b/assets/doomTowerScreen.png new file mode 100644 index 0000000..93e983a Binary files /dev/null and b/assets/doomTowerScreen.png differ diff --git a/assets/doomTowerStartBattle.png b/assets/doomTowerStartBattle.png new file mode 100644 index 0000000..b3da080 Binary files /dev/null and b/assets/doomTowerStartBattle.png differ diff --git a/assets/dungeons.png b/assets/dungeons.png new file mode 100644 index 0000000..d32eadf Binary files /dev/null and b/assets/dungeons.png differ diff --git a/assets/factionWars.png b/assets/factionWars.png new file mode 100644 index 0000000..f1c4c67 Binary files /dev/null and b/assets/factionWars.png differ diff --git a/assets/inBattle.png b/assets/inBattle.png new file mode 100644 index 0000000..5bddf17 Binary files /dev/null and b/assets/inBattle.png differ diff --git a/assets/ironTwinsBattleComplete.png b/assets/ironTwinsBattleComplete.png new file mode 100644 index 0000000..a91e20a Binary files /dev/null and b/assets/ironTwinsBattleComplete.png differ diff --git a/assets/ironTwinsDungeon.png b/assets/ironTwinsDungeon.png new file mode 100644 index 0000000..71ff459 Binary files /dev/null and b/assets/ironTwinsDungeon.png differ diff --git a/assets/ironTwinsStage15.png b/assets/ironTwinsStage15.png new file mode 100644 index 0000000..2e2e135 Binary files /dev/null and b/assets/ironTwinsStage15.png differ diff --git a/assets/ironTwinsStage15Battle.png b/assets/ironTwinsStage15Battle.png new file mode 100644 index 0000000..fbbfda7 Binary files /dev/null and b/assets/ironTwinsStage15Battle.png differ diff --git a/assets/multiBattleButton.png b/assets/multiBattleButton.png new file mode 100644 index 0000000..439af7b Binary files /dev/null and b/assets/multiBattleButton.png differ diff --git a/assets/mutliBattleComplete.png b/assets/mutliBattleComplete.png new file mode 100644 index 0000000..34239ff Binary files /dev/null and b/assets/mutliBattleComplete.png differ diff --git a/assets/stageStart.png b/assets/stageStart.png new file mode 100644 index 0000000..60750de Binary files /dev/null and b/assets/stageStart.png differ diff --git a/assets/startMultiBattle.png b/assets/startMultiBattle.png new file mode 100644 index 0000000..74e409e Binary files /dev/null and b/assets/startMultiBattle.png differ diff --git a/assets/theMarket.png b/assets/theMarket.png index 0dbf974..5a7e228 100644 Binary files a/assets/theMarket.png and b/assets/theMarket.png differ diff --git a/assets/turnOffMultiBattle.png b/assets/turnOffMultiBattle.png new file mode 100644 index 0000000..546af9a Binary files /dev/null and b/assets/turnOffMultiBattle.png differ diff --git a/helper_scripts/basicAutoClickerScript.py b/helper_scripts/basicAutoClickerScript.py new file mode 100644 index 0000000..64cf3e3 --- /dev/null +++ b/helper_scripts/basicAutoClickerScript.py @@ -0,0 +1,133 @@ +import os +import time +import pyautogui +import logging +import pygetwindow + +### This file helps to make Commands on the fly by itself +logging.basicConfig( + filename='PyAutoRaid.log', + format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', + filemode='w', + level=logging.DEBUG +) +logger = logging.getLogger(__name__) + +class App: + def __init__(self, asset_path): + self.asset_path = asset_path + + def delete_popup(self): + logger.info("Simulating popup deletion.") + + def back_to_bastion(self): + logger.info("Simulating returning to bastion.") + +class Command: + def execute(self): + pass + +class IronTwinsCommand(Command): + def __init__(self, app): + self.app = app + + def execute(self): + try: + logger.info("Starting Faction Wars task.") + + # Define image paths + battle_btn_image = os.path.join(self.app.asset_path, "battleBTN.png") + doom_tower_image = os.path.join(self.app.asset_path, "doomTower.png") + doom_tower_next_stage = os.path.join(self.app.asset_path, "doomTowerNextStage.png") + doom_tower_start_battle = os.path.join(self.app.asset_path, "doomTowerStartBattle.png") + doom_tower_stages_screen = os.path.join(self.app.asset_path, "doomTowerScreen.png") + in_battle_image = os.path.join(self.app.asset_path, "inBattle.png") + in_mutli_battle_image = os.path.join(self.app.asset_path, "turnOffMultiBattle.png") + mutli_battle_complete_image = os.path.join(self.app.asset_path, "mutliBattleComplete.png") + + logger.info("Attempting to close any existing pop-ups.") + self.app.delete_popup() + + # Navigate to battle screen + time.sleep(2) + self.click_image(battle_btn_image, "Battle button") + + # Navigate to Doom Tower + pyautogui.moveTo(960, 540) + pyautogui.dragRel(-600, 0, duration=0.5) + time.sleep(2) + self.click_image(doom_tower_image, "Doom Tower button") + time.sleep(2) + + # Loop through this to complete Auto Climb and then Tower - Or replay failed stages + while pyautogui.locateOnScreen(doom_tower_next_stage, confidence=0.8): + self.click_image(doom_tower_next_stage, "Doom Tower Next Stage") + + # If Wave stage Start Multi Battle + x, y = pyautogui.locateCenterOnScreen(doom_tower_start_battle, confidence=0.8) + pyautogui.click(x, y) + logger.info(f"Clicked on Doom Tower Start Battle at coordinates ({x}, {y}).") + time.sleep(2) + + if pyautogui.locateOnScreen(doom_tower_start_battle, confidence=0.8): + logger.info("Must not have enough keys. Doom Tower Comlete") + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(1) + + + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8) or pyautogui.locateOnScreen(in_mutli_battle_image, confidence=0.8): + logger.info("Waiting for the battle results.") + time.sleep(10) + while pyautogui.locateOnScreen(mutli_battle_complete_image, confidence=0.8): + # Back to doom tower to check if the boss is ready or failed run + pyautogui.press("esc") + time.sleep(1) + pyautogui.press("esc") + time.sleep(1) + + # If Boss Stage Click Boss Right Hand Side + if pyautogui.locateOnScreen(doom_tower_stages_screen, confidence=0.8): + pyautogui.click(540, 1270) + time.sleep(2) + + # Click on boss that is stage 120 + if pyautogui.locateOnScreen(doom_tower_stages_screen, confidence=0.8): + pyautogui.click(950, 500) + time.sleep(2) + + self.click_image(doom_tower_start_battle, "Doom Tower Start Battle") + time.sleep(5) + # Wait for battle to complete + while pyautogui.locateOnScreen(in_battle_image, confidence=0.8): + logger.info("Waiting for the battle results.") + time.sleep(10) + + self.app.back_to_bastion() + logger.info("Faction Wars task completed successfully.") + except Exception as e: + logger.error(f"Error in IronTwinsCommand: {e}", exc_info=True) + self.app.back_to_bastion() + + def click_image(self, imagePath, description): + """Helper to click an image on screen.""" + while pyautogui.locateOnScreen(imagePath, confidence=0.8): + x, y = pyautogui.locateCenterOnScreen(imagePath, confidence=0.8) + pyautogui.click(x, y) + logger.info(f"Clicked on {description} at coordinates ({x}, {y}).") + time.sleep(2) + + +# Main logic to run the command +if __name__ == "__main__": + # Provide the path to the folder containing the image assets + current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) + asset_path = os.path.join(current_dir, 'assets') + app = App(asset_path) + command = IronTwinsCommand(app) + win_list = pygetwindow.getWindowsWithTitle("Raid: Shadow Legends") + win_list[0].activate() + + command.execute() diff --git a/helper_scripts/mouseXY.py b/helper_scripts/mouseXY.py new file mode 100644 index 0000000..7cf7417 --- /dev/null +++ b/helper_scripts/mouseXY.py @@ -0,0 +1,34 @@ +import pygetwindow as gw +import pyautogui +import time + +print("Move your mouse to see the coordinates relative to the active window. Press Ctrl+C to stop.") + +try: + while True: + # Get the active window + active_window = gw.getActiveWindow() + if active_window: + # Get the top-left corner of the active window + window_left = active_window.left + window_top = active_window.top + + # Get the current mouse position + x, y = pyautogui.position() + + # Calculate coordinates relative to the active window + relative_x = x - window_left + relative_y = y - window_top + + print( + f"Mouse position (screen): x={x}, y={y} | " + f"(relative): x={relative_x}, y={relative_y} | " + f"Window: {active_window.title}", + end="\r", + flush=True, + ) + time.sleep(0.1) + else: + print("No active window detected.", end="\r", flush=True) +except KeyboardInterrupt: + print("\nExiting...")