def check_stash_open(self, open_otherwise=False): # Check stash open if vh.is_stash_tab_open(): return True elif not open_otherwise: return False else: logger.debug("Stash is closed") # Try to open otherwise stash_pos = vh.find_stash() logger.debug("Found stash @ {}".format(stash_pos)) # Click on stash position autogui.moveTo(*stash_pos) time.sleep(0.5) autogui.click() # Reset mouse to avoid screen polution autogui.moveTo(1, 1) # Wait time.sleep(2) if not vh.is_stash_tab_open(): raise CouldNotOpenStashException else: logger.debug("Stash is open")
def set_foreground(self): """put the window in the foreground""" win32gui.SetForegroundWindow(self._handle) logger.debug( "POE window ({}) brought to foreground".format(self._handle)) # Click at 0,0 to unlock game autogui.moveTo(1, 1)
def clean_inventory(self, to_tab, force_sync=False, expected_items=None): ''' Transfer back all items from inventory to stash. Move any trash item to recycle bin. ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.check_stash_open(open_otherwise=True) # Go to the currency stash tab self.go_to_tab(to_tab, check_stash_open=False) # Check if the inventory is synchronized if not inventory.synchronzed or force_sync: self.sync_inventory() # Clear clipboard text self.clear_clipboard_text() autogui.keyDown('ctrl') for slot in inventory.iter(): # Get item stack currency_stack = copy.deepcopy(inventory.get(*slot)) # Request bank diposit if not bank.deposit(currency_stack): # bank is full or something went wrong raise CouldNotClearInventoryException else: # Transfer (point_x, point_y) = inventory.to_screen_position(*slot) logger.debug( "Stashing item at ({},{})".format(*slot)) autogui.moveTo(point_x, point_y) autogui.click() # Attempt to get item text at current position autogui.press('c') # If clipboard is not empty, the item didn't get transfered if self.get_clipboard_text() != "": logger.error( 'Could not remove item from inventory at position [{},{}]'.format(*slot)) raise Exception # Clear item from inventory inventory.clear(*slot) autogui.keyUp('ctrl') # Reset mouse to avoid screen polution autogui.moveTo(1, 1) return True
def get_text_at_position(self, pos, reset_mouse=True): autogui.moveTo(*pos) autogui.hotkey('ctrl', 'c') # Reset mouse to avoid screen polution if reset_mouse: autogui.moveTo(1, 1) return self.get_clipboard_text()
def cancel_trade(self, ensure=False): ''' click the cancel trade button ''' if not self.check_trade_win_open(): logger.warning( 'Attempted to close trade winow but it is not open !') autogui.moveTo(*config.TRADE_WIN_CANCEL_BUTTON_POS) autogui.click() autogui.moveTo(1, 1) return self.check_trade_win_open()
def list_currency_trade_window(self): ''' generate a list of all the currencies in the trade window ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if trade window is open if not self.check_trade_win_open(): logger.warning( 'Attempted to list trade window contents, but trade window is not open !') return {} # Find empty slots in inventory empty_slots = vh.find_empty_slots_in_trade_win() full_slots = [] # Find the non-empty slots for row in range(client_trade_window.num_rows): for col in range(client_trade_window.num_cols): if (row, col) not in empty_slots: full_slots += [[row, col]] currencies = {} for slot in full_slots: # get item description item_description = self.get_text_at_position( client_trade_window.to_screen_position(*slot), reset_mouse=False) # classify description (curr, ammount) = self.process_item_description(item_description) if curr == "" and ammount == "": # Empty slot pass elif curr and ammount: if curr.name in currencies: currencies[curr.name] += ammount else: currencies[curr.name] = ammount else: if 'unknown' in currencies: currencies['unknown'] += 1 else: currencies['unknown'] = 1 # Reset Mouse Position autogui.moveTo(1, 1) logger.debug("Trade window scan:{}".format(currencies)) return currencies
def sync_inventory(self): ''' Read inventory and sinchronize it ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.check_stash_open(open_otherwise=True) logger.info("Starting inventory sync ...") # Find empty slots in inventory empty_slots = vh.find_empty_slots_in_inventory() # Mark as empty for row, col in empty_slots: inventory.clear(row, col) full_slots = [] # Find the non-empty slots for row in range(inventory.num_rows): for col in range(inventory.num_cols): if (row, col) not in empty_slots: full_slots += [[row, col]] for slot in full_slots: # get item description item_description = self.get_text_at_position( inventory.to_screen_position(*slot), reset_mouse=False) # classify description (curr, ammount) = self.process_item_description(item_description) if curr == "" and ammount == "": # Empty slot inventory.clear(*slot) elif curr and ammount: new_stack = currency.CurrencyStack(curr, ammount) inventory.set(new_stack, slot[0], slot[1]) else: raise CouldNotIdentifyItemException # Reset Mouse Position autogui.moveTo(1, 1) inventory.synchronzed = True logger.info("Inventory sync finished ...")
def sync_bank(self): ''' Read inventory and sinchronize it ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.check_stash_open(open_otherwise=True) # Go to the currency stash tab self.go_to_tab(currency_tab, check_stash_open=False) logger.info("Starting bank sync ...") # Find currencies in stash tab matches = vh.find_currency_in_stash_tab( currency.CURRENCY_LIST, currency_tab) # For every currency kind for curr in currency.CURRENCY_LIST: if curr.name in matches: # Every location where this curr was found for match in matches[curr.name]: item_description = self.get_text_at_position( match, reset_mouse=False) # classify description (found_curr, found_ammount) = self.process_item_description( item_description) # assert(curr == found_curr) # Image Capture is not 100% reliable # If there is a missmtach ctrl+c wins if found_curr != None and found_curr != "" and curr == found_curr: temmp_stack = currency.CurrencyStack( found_curr, found_ammount) assert(bank.deposit(temmp_stack)) # Reset Mouse Position autogui.moveTo(1, 1) bank.synchronzed = True logger.info("Bank sync finished ...")
def accept_trade(self): ''' click the accept trade button ''' if not self.check_trade_win_open(): logger.error( 'Attempted to accept trade but trade window is not open !') raise Exception if vh.get_trade_win_accept_status() == "ACCEPTED": logger.info( 'Attempted to accept trade but trade is already accepted !') return True autogui.moveTo(*config.TRADE_WIN_ACCEPT_BUTTON_POS) autogui.click() autogui.moveTo(1, 1) return True
def identify_currencies_in_stash(self): ''' Find position of all available currencies in stash. Make sure they can be identified via Ctrl+c ''' # Check we are in foreground, set otherwise self.ah.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.ah.check_stash_open(open_otherwise=True) # Go to the currency stash tab self.ah.go_to_tab(currency_tab, check_stash_open=False) matches = vh.find_currency_in_stash_tab( currency.CURRENCY_LIST, currency_tab) for curr in currency.CURRENCY_LIST: if curr.name in matches and matches[curr.name]: text = self.ah.get_text_at_position(matches[curr.name][0]) if text is None or text == "": logger.debug( 'Could not read item properties through Ctrl+C for {} @ {}'.format(curr.pretty_name, *matches[curr.name][0])) (found_curr, _) = self.ah.process_item_description(text) self.assertEqual( curr, found_curr, "\n\tLooking for {} but found {}".format(curr, found_curr)) logger.info("Found {} == {}".format( curr.pretty_name, found_curr.pretty_name)) else: logger.debug( 'Currency {} could not be found in stash.'.format(curr.pretty_name)) # Reset mouse to avoid screen pollution autogui.moveTo(1, 1)
def identify_currencies_in_inv(self): ''' Find position of all available currencies in stash. Make sure they can be identified via Ctrl+c ''' # Check we are in foreground, set otherwise self.ah.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.ah.check_stash_open(open_otherwise=True) matches = vh.find_currency_in_inventory(currency.CURRENCY_LIST) for curr in currency.CURRENCY_LIST: if curr.name in matches and matches[curr.name]: autogui.moveTo(*matches[curr.name][0]) autogui.hotkey('ctrl', 'c') # Get txt from clipboard text = self.ah.get_clipboard_text() if text is None or text == "": logger.debug( 'Could not read item properties through Ctrl+C for {} @ {}'.format( curr.pretty_name, *matches[curr.name][0])) (found_curr, _) = self.ah.process_item_description(text) self.assertEqual( curr, found_curr, "\n\tLooking for {} but found {}".format(curr, found_curr)) logger.info("Found {} == {}".format( curr.pretty_name, found_curr.pretty_name)) else: logger.debug( 'Currency {} could not be found in stash.'.format(curr.pretty_name))
def transfer_currency_inv_trade(self, ensure=False): ''' Takes a list of positions in the inventory. The items in that positions will be ctrl + clicked to the trade window. ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise if not self.check_trade_win_open(): logger.error( 'Attempted to transfer from inventory to trade but trade window is not open !') raise Exception autogui.keyDown('ctrl') for item in inventory.iter(): pos = inventory.to_screen_position(*item) autogui.moveTo(*pos) autogui.click() autogui.keyUp('ctrl') autogui.moveTo(1, 1)
def browse_over_customer_items(self): ''' move mouse over customer items so trade can be performed ''' autogui.moveTo(*config.TRADE_WIN_POS_0_0) for col in range(config.INV_NUM_COL): autogui.moveTo( config.TRADE_WIN_POS_0_0[0], config.TRADE_WIN_POS_0_0[1] + col * config.NORMAL_TAB_Y_OFFSET + config.NORMAL_TAB_Y_OFFSET/2, 0.3) autogui.moveTo( config.TRADE_WIN_POS_0_0[0] + config.NORMAL_TAB_X_OFFSET * config.INV_NUM_ROW, config.TRADE_WIN_POS_0_0[1] + col * config.NORMAL_TAB_Y_OFFSET + config.NORMAL_TAB_Y_OFFSET/2, 0.3) autogui.moveTo(1, 1)
def set_currency_rates(self, rates): ''' set the rate for the requested currency ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.check_stash_open(open_otherwise=True) # Go to the currency stash tab self.go_to_tab(listing_tab, check_stash_open=False) for (curr, texts) in rates: # Find all currency curr and the messages in text to each indiviudal currency positions = vh.find_currency_in_stash_tab( [curr], listing_tab)[curr.name] # Assign a diferent text to each position for pos, txt in zip(positions, texts): autogui.moveTo(*pos) # Double check we found the right currency autogui.hotkey('ctrl', 'c') found_curr, _ = self.process_item_description( self.get_clipboard_text()) if curr != found_curr: continue autogui.click(button='right') retries = 0 pos = None while not pos and retries < 3: autogui.press('backspace') pos = vh.find_set_price_window() retries += 1 if not pos: logger.error( 'Could not find price set window for {}'.format(curr.pretty_name)) # reset mouse autogui.moveTo(1, 1) # click anywhere else to close the set currency window # just in case it was left open and couldn't be detected autogui.click() continue set_price_win_x = pos[0][0][0] set_price_win_y = pos[0][0][1] set_price_win_w = pos[0][1][0] - set_price_win_x set_price_win_h = pos[0][1][1] - set_price_win_y text_field_pos = [set_price_win_x + set_price_win_w * config.PRICE_SET_WINDOW_TEXT_FIELD_REL_POS[0], set_price_win_y + set_price_win_h * config.PRICE_SET_WINDOW_TEXT_FIELD_REL_POS[1]] autogui.moveTo(*text_field_pos) autogui.click() autogui.typewrite(txt) autogui.press('enter') # reset mouse autogui.moveTo(1, 1) # click anywhere else to close the set currency window # just in case it was left open and couldn't be detected autogui.click()
def wiggle_mouse(self): (x, y) = autogui.position() autogui.moveTo(x+1, y+1)
def transfer_currency_stash_inv(self, curr, ammount, from_tab): ''' Takes a list of currencies to be transfered into the inventory. Will take care of ammounts that are not aligned with stack size. ''' # Check we are in foreground, set otherwise self.is_foreground(set_foreground=True) # Check if stash is open, open it otherwise self.check_stash_open(open_otherwise=True) # Go to the currency stash tab self.go_to_tab(from_tab, check_stash_open=False) # Find the position of this currency in stash matches = vh.find_currency_in_stash_tab([curr], currency_tab) matches = matches[curr.name] # Check if it is possible if not bank.withdraw(currency.CurrencyStack(curr, ammount)): raise Exception t_ammount_left = ammount for match in matches: # Read at that position (found_curr, f_ammount_left) = self.process_item_description( self.get_text_at_position(match, reset_mouse=False)) if found_curr != curr: logger.error( "Find mismatch ! Expected {} found {}".format(curr, found_curr)) raise Exception # While we didnt finish or we didn't run out of currency here while (t_ammount_left > 0) and (f_ammount_left > 0): transfer_size = 0 # Eg 5c left here and need to transfer 6c (stack size is 10) # Eg 11c left here and need to transfer 16c (stack size is 10) - Wouldn't work if (f_ammount_left < t_ammount_left) and (f_ammount_left < curr.stack_size): transfer_size = f_ammount_left # Eg 50c left here and need to transfer 60c (stack size is 10) elif t_ammount_left > curr.stack_size: transfer_size = curr.stack_size # Eg 50c left here and need to transfer 6c (stack size is 10) elif t_ammount_left <= curr.stack_size: transfer_size = t_ammount_left # The transfer function will asume that if we are transfering less than a full stack # we will do it 'by hand' and not by control + click. Since it # This is the case most of the time. There is a corner case where we are transfering # less than a full stack and exactly the ammount left on the stash. In that case we have to # ctrl + click. force_ctrl_click = (transfer_size == f_ammount_left) (result, new_cell) = inventory.transfer( currency.CurrencyStack(found_curr, transfer_size), force_ctrl_click=force_ctrl_click) if not result: print(result) print(new_cell) print(inventory.dump()) print(bank.contents) raise Exception # Can ctrl+click to transfer full stack if transfer_size == curr.stack_size or transfer_size == f_ammount_left: # Transfer found_ammount of found_curr into inv autogui.moveTo(*match) autogui.keyDown('ctrl') autogui.click() autogui.keyUp('ctrl') # Need to split the stack else: autogui.moveTo(*match) autogui.keyDown('shift') autogui.click() autogui.keyUp('shift') time.sleep(0.2) # Split currency autogui.typewrite(str(transfer_size)) time.sleep(0.2) # Confirm autogui.press('enter') # Find next empty slot autogui.moveTo( *inventory.to_screen_position(*new_cell)) # Drop the currency autogui.click() # Update remaining t_ammount_left -= transfer_size if t_ammount_left != 0: raise Exception