POE(패스오브엑자일) 인벤 자동 정리 !!! [2]


* 경고 *

해당 포스팅은 교육적인 목적입니다. 절대 악용, 남용 하면 아니되옵니다.

 

안녕하세요 라이프온룸입니다. ~

오늘은 인벤토리 정리 두번째 시간인데요 오늘 할일은 Onclick으로 아이템을 확인하고 상점에 아이템을 팔아 보겠습니다. 

어떻게 동작하는지는 영상을 참조해 주세요 ㅎㅎ

 

추가적으로 저번 포스팅 대비 개선사항이 있습니다. 

  1. findImage 함수에서 인벤토리의 빈 그리드를 찾을 시 인벤토리의 색 정보를 비교하여 빈 공간을 검출하도록 했습니다. 
  2. 코드만 실행시키면 config.cfg의 내용을 채우도록 했습니다. 
  3. 마우스 이동 시 아이템 사이즈를 적용하여 같은 아이템에 중복으로 이동하는 루틴을 줄였습니다. 

넵 그러하구요 ㅎㅎㅎ 

자 그럼 라이브러리 부터 보고 가지요 

1. 필요 라이브러리

pip install pywinauto

POE(패스오브엑자일) 인벤 자동 정리 !!! [1] 에 쓰이는 라이브러리 이외에 위 라이브러리가 추가적으로 필요합니다. pywinauto 는 Window GUI 컨트롤을 좀 더 쉽게 하기 위한 라이브러리 입니다. mouse, keyboard 이벤트를 지원하며 윈도우에 떠있는 창들을 쉽게 관리하도록 도와줍니다. 

본 포스팅에서는 POE의 window를 Active 윈도우로 만들기 위해 사용합니다. 

2. 코드

inventoryFunc.py

import win32clipboard
import pyautogui as pa
import mouse as mo
import keyboard as keys
import time
import numpy as np
import pprint
import cv2.cv2 as cv2
import mss
import os
from PIL import Image
import codecs
import json
import pywinauto as pwa
import copy

K_RARENESS = '희귀도'
K_ITEMNAME = 'item_name'
K_ITEMBASENAME = 'item_base_name'
K_ISSELL = 'isSell'

V_CURRENCY = '화폐'
V_NORMAL = '보통'
V_MAGIC = '마법'
V_RARE = '희귀'
V_UNIQUE = '고유'

K_CHECK = '미확인여부'
CHECK_ITME = '감정 주문서'

EXCEPT_CURRENCY = ['감정 주문서', '포탈 주문서']
EXCEPT_SELLING = ['고유']

# Make Active PoE window
def setActivePoe():
    app = pwa.application.Application()
    app.connect(title_re='Path of Exile')
    app_dialog = app.window()
    app_dialog.set_focus()

class InventoryTool():

    def __init__(self, inventorySize, listexceptCurr):
        # inventorySize x, y, w, h
        self.itemInfoInInven = {}
        self.inventorySize = inventorySize
        self.inven = np.empty(shape=(12, 5), dtype=tuple)
        self.invenUnitSize = (int(inventorySize[2] / 12), int(inventorySize[2] / 12))
        self.invenUnitBox = (inventorySize[0] + 5, inventorySize[1] + 5, \
                               self.invenUnitSize[0]-5, self.invenUnitSize[1]-5)
        self.listexceptCurr = listexceptCurr
        for xunit in range(12):
            for yunit in range(5):
                x = self.inventorySize[0] + xunit * self.invenUnitSize[0]
                y = self.inventorySize[1] + yunit * self.invenUnitSize[0]
                cord = pa.center((x, y, self.invenUnitSize[0], self.invenUnitSize[1]))
                self.inven[xunit][yunit] = cord

    # init Data of inventory
    def initItemInfoInven(self):
        self.itemInfoInInven = {}

    # make unitPoint(0, 0) to realPoint(1200, 700)
    def realPoint(self, unitPointX, unitPointY):
        return (self.inven[unitPointX][unitPointY][0], self.inven[unitPointX][unitPointY][1])

    # make realPoint(1200, 700) to unitPoint(0, 0)
    def makeUnitPoint(self, realPointX, realPointY):
        a = [(ix, iy) for ix, row in enumerate(it.inven) for iy, i in enumerate(row) if i == (realPointX, realPointY)]
        return a[0]

    # clipboard string to dict
    def makeItemInfoOfClipboard(self, cText):
        itemInfo = {}
        infoList = cText.split('\n')
        infoList = [i.strip() for i in infoList]
        # 확인 여부에 따라 아이템 Base 이름이 달라짐
        # -- 희귀도
        rareness = infoList.pop(0)
        rareness_key, rareness_value = rareness.split(':')

        rareness_key = rareness_key.strip()
        rareness_value = rareness_value.strip()
        itemInfo[rareness_key] = rareness_value
        # -- 확인여부
        try:
            if infoList.index('미확인') >= 0:
                isCheck = True
            else:
                isCheck = False
            itemInfo[K_CHECK] = isCheck
        except Exception as e:
            isCheck = False
            itemInfo[K_CHECK] = isCheck

        # 미확인 Item
        if isCheck == True:
            itemInfo[K_CHECK] = isCheck
            # -- 아이템 Base 이름
            itemName = infoList.pop(0)
            itemInfo[K_ITEMBASENAME] = itemName
        # 확인 아이템
        else:
            # 희귀 혹은 고유 아이템의 경우 아이템 이름 존재
            if rareness_value == V_RARE or rareness_value == V_UNIQUE:
                itemName = infoList.pop(0)
                itemInfo[K_ITEMNAME] = itemName
                itemName = infoList.pop(0)
                itemInfo[K_ITEMBASENAME] = itemName
            else:
                # -- 아이템 Base 이름만 존재
                # -- 마법아이템의 경우 아이템 Base 이름에 Prefix, Suffix 붙음
                itemName = infoList.pop(0)
                itemInfo[K_ITEMBASENAME] = itemName

        for idx, specs in enumerate(infoList):
            spec = specs.split(':')
            if len(spec) >= 2:
                itemInfo[spec[0]] = spec[1]
            else:
                if spec[0].find('-') >= 0:
                    continue

                prop = 'spec' + str(idx)
                itemInfo[prop] = spec[0]
        #pprint.pprint(itemInfo, indent=2)
        return itemInfo

    def getItemSize(self, itemSpec):
        try:
            return (itemSpec['Width'], itemSpec['Height'])
        except:
            return (1, 1)

    # 현제 좌표에서 아이템 영역
    def makeItemUnitSize(self, itemSize, CurrentCoord):
        x, y = itemSize
        coord = []
        for xi in range(x):
            for yi in range(y):

                coord.append((CurrentCoord[0] + xi, CurrentCoord[1] + yi))
        return coord

    # .json 파일의 결과인 itemDB 에서 item base name 검색
    def findItemOnDB(self, itemDB, invenItemDict):
        try:
            itemName = invenItemDict[K_ITEMBASENAME]
            itemRareness = invenItemDict[K_RARENESS]
        except Exception as e:
            print (e, 'Not Found',invenItemDict)
            return None, None

        for itemSubClass in itemDB:
            pkey = [*itemSubClass][0]

            for key, itemSpec in itemSubClass[pkey].items():
                # if itemRareness == V_MAGIC or itemRareness == V_NORMAL:
                if itemName.find(key) >=0:
                    print('Found On DB: ', key, ', Found On Inventory: ',itemName)
                    return key, self.getItemSize(itemSpec)
                # else:
                #     if key == itemName:
                #         print ('Found ', key)
                #         return key, self.getItemSize(itemSpec)
        return None, None

    # get clipboard data
    def getItemInfoFromClipboard(self, unitPoint):
        itemInfo = {}
        keys.send("ctrl+c")
        time.sleep(0.05)
        try:
            win32clipboard.OpenClipboard()

            itemData = win32clipboard.GetClipboardData()
            win32clipboard.EmptyClipboard()
            win32clipboard.CloseClipboard()
            itemInfo = self.makeItemInfoOfClipboard(itemData)
            self.itemInfoInInven[unitPoint] = itemInfo
            return itemInfo

        except:
            print('No Item ', unitPoint)
            return None


    def checkItemInInvertory(self, boxRegions):

        for x in range(np.shape(self.inven)[0]):
            for y in range(np.shape(self.inven)[1]):

                rpoint = self.realPoint(x, y)
                if self.checkEmptyUnitPoint(boxRegions, rpoint):
                    mo.move(rpoint[0], rpoint[1])
                    time.sleep(0.03)
                    self.getItemInfoFromClipboard((x, y))

    def checkItemInInventoryWithInfo(self, boxRegions, itemDB = []):
        oned_array = np.reshape(self.inven, (np.prod(self.inven.shape),))
        exceptUnitCoord = []
        for coord in oned_array:
            if self.checkEmptyUnitPoint(boxRegions, coord):
                unitPoint = self.makeUnitPoint(coord[0], coord[1])
                if (unitPoint in exceptUnitCoord) == False:
                    mo.move(coord[0], coord[1])
                    time.sleep(0.03)

                    itemInfo = self.getItemInfoFromClipboard(unitPoint)
                    if itemDB != [] and itemInfo != None:
                        itemName, itemSize = self.findItemOnDB(itemDB, itemInfo)
                        # inventory item이 DB에 있을 시
                        if itemSize != None:
                            exceptUnitCoord = exceptUnitCoord + self.makeItemUnitSize(itemSize, unitPoint)

                            if self.itemInfoInInven[unitPoint][K_RARENESS] in EXCEPT_SELLING:
                                self.itemInfoInInven[unitPoint][K_ISSELL] = False
                            else:
                                self.itemInfoInInven[unitPoint][K_ISSELL] = True
                        else:
                            self.itemInfoInInven[unitPoint][K_ISSELL] = False



    def moveCurrencyToStash(self):
        print('---moveCurrencyToStash---')
        keys.press('ctrl')
        for unitPoint, iteminfo in self.itemInfoInInven.items():
            rpoint = self.realPoint(unitPoint[0], unitPoint[1])
            try:
                # print('move', iteminfo[K_ITEMBASENAME])
                if iteminfo[K_RARENESS] == V_CURRENCY \
                        and not iteminfo[K_ITEMBASENAME] in self.listexceptCurr:

                    mo.move(rpoint[0], rpoint[1])
                    time.sleep(0.05)
                    mo.click()
                    print('Move Inven To Stash: ', iteminfo[K_ITEMBASENAME])
            except:
                pass

        keys.release('ctrl')
        print('--------------------')
        self.itemInfoInInven = {}


    def findItemOnInventory(self, itemName):
        for key, item in self.itemInfoInInven.items():
            if item[K_ITEMBASENAME] == itemName:
                return key
        return None

    def itemConfirm(self):
        checkItemUnitCoord = self.findItemOnInventory(CHECK_ITME)
        if checkItemUnitCoord == None:
            return

        checkItemPoint = self.realPoint(checkItemUnitCoord[0], checkItemUnitCoord[1])

        print('-----itemConfirm-----')
        for key, item in self.itemInfoInInven.items():
            if item[K_CHECK] == True:
                # -- 감정주문서로 이동 후 우클릭
                mo.move(checkItemPoint[0], checkItemPoint[1])
                time.sleep(0.05)
                mo.click(mo.RIGHT)
                time.sleep(0.05)
                # -- 감정할 아이템이로 가서 클릭
                itemPoint = self.realPoint(key[0], key[1])
                mo.move(itemPoint[0], itemPoint[1])
                time.sleep(0.05)
                mo.click()
                time.sleep(0.05)
                print('Item Confirmed : ', item[K_ITEMBASENAME])
        print('--------------------')

    def itemSell(self):

        print('-----itemSell-----')
        keys.press('ctrl')
        for key, item in self.itemInfoInInven.items():
            if item[K_ISSELL] == True:
                itemPoint = self.realPoint(key[0], key[1])
                mo.move(itemPoint[0], itemPoint[1])
                time.sleep(0.05)
                mo.click()
                time.sleep(0.05)
                print('Item On Sell : ', item[K_ITEMBASENAME])
        self.itemInfoInInven = {}
        keys.release('ctrl')
        print('--------------------')

    def checkEmptyUnitPoint(self, boxRegions, centerRpoint):
        for br in boxRegions:
            x, y, w, h = br
            if (x < centerRpoint[0] < x + w) and (y < centerRpoint[1] < y + h):
                # nothing on inven
                return False
        # something on inven
        return True

    # img's bgr min, max
    def getBGRMinMax(self, img):

        # frame = cv2.GaussianBlur(frame, (5, 5), 0)
        min_ch = (np.amin(img[:, :, 0]), np.amin(img[:, :, 1]), np.amin(img[:, :, 2]))
        max_ch = (np.amax(img[:, :, 0]), np.amax(img[:, :, 1]), np.amax(img[:, :, 2]))


        #print("max_ch = ", max_ch, min_ch)
        return min_ch, max_ch

    def findImage(self, templateName, show=0, confidence=0.6):
        boxRegions = []
        x, y, w, h = self.inventorySize
        mon = {'top': y, 'left': x, 'width': w, 'height': h}
        sct = mss.mss()
        sct.grab(mon)

        img = Image.frombytes('RGB', (w, h), sct.grab(mon).rgb)
        frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)

        copyImg = copy.copy(frame)

        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

        imgPath = os.path.dirname(os.path.realpath(__file__)) + '\\' + templateName
        template = cv2.imread(imgPath)
        tmin, tmax = self.getBGRMinMax(template)

        template = cv2.cvtColor(template, cv2.COLOR_BGR2GRAY)


        w, h = template.shape[::-1]
        # 입력된 templateName 과 같은 그림을 이벤토리 에서 찾음
        res = cv2.matchTemplate(gray, template, cv2.TM_CCOEFF_NORMED)
        threshold = confidence
        loc = np.where(res >= threshold)

        for pt in zip(*loc[::-1]):

            cropedImg = copyImg[pt[1]:pt[1] + h, pt[0]:pt[0] + w]
            dmin, dmax = self.getBGRMinMax(cropedImg)
            # compare only min
            if dmin[0] <= tmin[0] and dmin[1] <= tmin[1] and dmin[2] <= tmin[2]:
                if show == 1:
                    cv2.rectangle(frame, pt, (pt[0] + w, pt[1] + h), (0, 0, 255), 2)
                realX = self.inventorySize[0] + pt[0]
                realY = self.inventorySize[1] + pt[1]
                boxRegions.append((realX, realY, w, h))

        if show == 1:
            cv2.imshow('image', frame)
            cv2.waitKey(0)
            cv2.destroyAllWindows()

        return boxRegions

    def makeTemplate(self, templateName, templatePoint):
        x, y, w, h = templatePoint
        mon = {'top': y, 'left': x, 'width': w, 'height': h}
        sct = mss.mss()
        sct.grab(mon)
        img = Image.frombytes('RGB', (w, h), sct.grab(mon).rgb)
        frame = cv2.cvtColor(np.array(img), cv2.COLOR_RGB2BGR)


        imgPath = os.path.dirname(os.path.realpath(__file__)) + '\\' + templateName
        cv2.imwrite(imgPath, frame)

if __name__=="__main__":
    import configparser
    import cvFunc as cvf
    from ast import literal_eval

    SECTION = 'inventory'
    EDITED = 0

    configFile = os.path.dirname(os.path.realpath(__file__)) + '\\' + 'config.cfg'
    config = configparser.ConfigParser()
    config.read(configFile)

    result = SECTION in config.sections()
    if result == False:
        config.add_section(SECTION)

    if config.has_option(SECTION, 'inven_region'):
        inventory_size = literal_eval(config[SECTION]['inven_region'])
    else:
        print('"'"inven_region"'" Option Not Exist Take a Screenshot on Inventory')
        time.sleep(1)
        ip = cvf.ScreenShot()
        inventory_size = ip.partScreenShot()
        config[SECTION]['inven_region'] = str(inventory_size)
        EDITED = 1

    if config.has_option(SECTION, 'confidence'):
        templateConfidence = float(config[SECTION]['confidence'])
    else:
        templateConfidence = 0.8
        print('"'"confidence"'" Option Not Exist Set 0.8')
        config[SECTION]['confidence'] = str(templateConfidence)
        EDITED = 1
        pass

    if config.has_option(SECTION, 'inven_unit_empty_pic'):
        templateName = config[SECTION]['inven_unit_empty_pic']
    else:
        a = input(""'"inven_unit_empty_pic"'" Option Not Exist, Make empty first grid of inventory ! Then Enter !")
        templateName = "invenUnitEmpty.png"
        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        it.makeTemplate(templateName, it.invenUnitBox)
        config[SECTION]['inven_unit_empty_pic'] = templateName

        EDITED = 1

    if EDITED == 1:
        a = input("want test ? (Y/N)")
        if a.strip() == 'Y':
            it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
            it.findImage(templateName, show=1, confidence=templateConfidence)
        else:
            pass

    if config.has_option(SECTION, 'key_currency_to_stash') and \
        config.has_option(SECTION, 'key_item_confirm') and \
            config.has_option(SECTION, 'key_item_sell'):
        keyCurToStash = config[SECTION]['key_currency_to_stash']
        keyItemConfirm = config[SECTION]['key_item_confirm']
        keyItemSell = config[SECTION]['key_item_sell']
    else:
        keyCurToStash = 'F2'
        keyItemConfirm = 'F3'
        keyItemSell = 'F4'
        config[SECTION]['key_currency_to_stash'] = keyCurToStash
        config[SECTION]['key_item_confirm'] = keyItemConfirm
        config[SECTION]['key_item_sell'] = keyItemSell
        EDITED = 1

    keyboardKey = [keyCurToStash, keyItemConfirm, keyItemSell]

    if EDITED == 1:
        with open(configFile, 'w') as config_file:
            config.write(config_file)

    run = 1
    # -- run forever
    if run == 1:
        jsonFileDBs = ['item_bases_weapon_kr', 'item_bases_kr', 'item_bases_armour_kr']
        itemDB = []
        for jDB in jsonFileDBs:
            path = os.path.dirname(os.path.realpath(__file__)) + '\\' + 'data' + '\\' + jDB + '.json'
            with codecs.open(path, 'r', 'utf-8-sig') as f:
                json_data = json.load(f)
                itemDB.append(json_data)
            f.close()

        listKeyState = [0] * len(keyboardKey)


        print('-Inven Organize Start')
        def checkInventory(invenTool):
            boxRegions = invenTool.findImage(templateName, 0, confidence=templateConfidence)
            setActivePoe()

            invenTool.checkItemInInventoryWithInfo(boxRegions, itemDB)
            # inventory 에 아이템 출력
            pprint.pprint(invenTool.itemInfoInInven, indent=4)

        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)

        while True:
            time.sleep(0.001)
            for idx, pressedKey in enumerate(keyboardKey):
                value = keys.is_pressed(pressedKey)
                if value == True:
                    if idx == 0 and listKeyState[idx] != value:
                        print('press', pressedKey)

                        it.initItemInfoInven()
                        checkInventory(it)

                        it.moveCurrencyToStash()
                        listKeyState[idx] = value
                    elif idx == 1 and listKeyState[idx] != value:
                        print('press', pressedKey)

                        it.initItemInfoInven()
                        checkInventory(it)

                        it.itemConfirm()
                        listKeyState[idx] = value
                    elif idx == 2 and listKeyState[idx] != value:
                        print('press', pressedKey)
                        if it.itemInfoInInven == {}:
                            checkInventory(it)
                        else:
                            setActivePoe()
                            pprint.pprint(it.itemInfoInInven, indent=4)

                        it.itemSell()
                        listKeyState[idx] = value

                else:
                    if listKeyState[idx] != value:
                        listKeyState[idx] = value

    # -- run currency to stash  1 time
    elif run == 2:
        setActivePoe()
        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        boxRegions = it.findImage(templateName, 0, confidence=templateConfidence)
        # print(boxRegions)
        it.checkItemInInvertory(boxRegions)

        #pprint.pprint(it.itemInfoInInven, indent=4)
        it.moveCurrencyToStash()

    # -- check item DB
    elif run == 3:

        setActivePoe()
        jsonFileDBs = ['item_bases_weapon_kr', 'item_bases_kr', 'item_bases_armour_kr']
        itemDB = []
        for jDB in jsonFileDBs:
            path = os.path.dirname(os.path.realpath(__file__)) + '\\' + 'data' + '\\' + jDB + '.json'
            with codecs.open(path, 'r', 'utf-8-sig') as f:
                json_data = json.load(f)
                itemDB.append(json_data)
            f.close()
        #pprint.pprint(itemDB[0]['item_bases_weapon'], indent=4)


        it = InventoryTool(inventory_size, EXCEPT_CURRENCY)
        boxRegions = it.findImage(templateName, 0, confidence=templateConfidence)
        it.checkItemInInventoryWithInfo(boxRegions, itemDB)
        #pprint.pprint(it.itemInfoInInven, indent=4)
        it.itemConfirm()



        #it.findImage(templateName, show=1, confidence=templateConfidence)

 

네 코드는 이렇게 생겼습니다. 위 코드 이외에 인벤토리의 Resolution을 얻기 위해  POE 자동 물약 먹기 !! if 체력 반피시 … 에서 만들었던 cvFunc.py이 필요 합니다. inventoryFunc.py 와 동일한 폴더에 만들어 주시면 됩니다. 

우선 코드를 실행 시키기 이전에 DB… 라고 하긴 뭐하고 아래 json 파일이 필요 합니다. 해당 파일 링크는 요기서 다운로드 하신뒤 inventoryFunc.py 가 있는 폴더에서 data라는 폴더를 만들고 그 안에 해당 파일을 넣어 주세요 

  • item_bases_weapon_kr.json
  • item_bases_kr.json
  • item_bases_armour_kr.json

이 json 파일에는 https://poedb.tw/kr 에서 받아온 아이템 정보(한손 무기, 양손 무기, 보조 무기, 방어구, 장신구, 플라스크 만 )가 json 형태로 저장되어 있습니다. 그리고 아이템 사이즈 정보와 형식은 유명한 메크로죠 PoE-TradeMacro를 참조 했습니다. 

위 코드를 입력 후 실행 시키면(관리자 권한 잊지 않으셨죠 ?? ㅎㅎ) -Inven Organize Start 라는 문구와 함께 코드가 실행 됩니다. 그리고 F2, F3, F4 키를 누르면 아래 기능이 수행 됩니다. 

  • F2 – 인벤토리의 Currency를 Stash로 이동 (저번 시간에 한거죠 ? ㅎㅎ)
  • F3 – 인벤토리의 미확인 아이템을 모두 확인 
  • F4 – DB에서 검출된 모든 아이템을 판매 창에 올리기 (한손 무기, 양손 무기, 보조 무기, 방어구, 장신구, 플라스크 만 고유아이템은 제외)

F4에서 고유아이템을 제외 라고 했는데요 코드 상단에 보면 EXCEPT_SELLING 이라는 리스트 변수가 있습니다. 이 LIST에 데이터를 추가해 주면 다른 희귀도를 가진 아이템들도 판매 대상에서 제외 할 수 있습니다. 

코드에 대략적인 동작은 아래와 같습니다. 

  1. checkItemInInventoryWithInfo 저번 포스트에서 만들었던 checkItemInInvertory 에서 DB 를 조회하여 아이템 사이즈를 가져오는 루틴을 추가 했습니다. 마우스를 이동 시키면서 해당 마우스 위치의 아이템 정보를 가져오고 이 데이터로 json 파일을 조회하여 아이템 사이즈를 가져온뒤 아이템 영역에 해당하는 그리드를 건너 뛰는 형식입니다. 
  2. 1번 과정을 마치면 InventoryTool Class의  itemInfoInInven 값에 좌표별 아이템 정보가 입력되게 됩니다. 이 데이터를 가지고 Key 입력에 맞는 행위를 해줍니다. 
    1. F2 – moveCurrencyToStash()
    2. F3 – itemConfirm()
    3. F4 – itemSell()
  3. 실행이 완료되면 아래와 같은 결과가 뜰꺼에요 !!

3. config.cfg

[inventory]
confidence = 0.8
key_currency_to_stash = F2
key_item_confirm = F3
key_item_sell = F4
inven_region = (1308, 575, 596, 250)
inven_unit_empty_pic = invenUnitEmpty.png

 

기능별 입력할 키를 추가 했습니다. config.cfg 없이 코드를 실행시키면 인스트럭션이 나올 건데요 그 인스트럭션대로 쭉 따라해 주시면 config.cfg 파일과 그 내용을 만들게 됩니다. !

 

 

 

넵 오늘 포스팅은 여기까지 이구요 유배자의 길 말고 꽃길만 가시길 바랄게요 ㅎㅎ 모두 다음에 만나요 ㅎㅎㅎ 

 



블로그 구독하기 !!

You may also like...

14 Responses

  1. ㅇㅇ 댓글:

    지금까지 잘 따라왔는데 여기서 잘 안되네요 ㅠ 파일 실행 후 config.cfg 지운다음 인벤토리파이썬 파일 실행 후 이러한 에러가 뜨는데 config.cfg 를 넣으면 프로그램 실행은 되는데 동작은 안하구요… 이런 에러가 뜨는데 cv쪽 파일에 문제인거같기도 하구

    (venv) C:\Users\yg\PycharmProjects\PathOfExileP>python inventoryFunc.py
    “inven_region” Option Not Exist Take a Screenshot on Inventory
    Traceback (most recent call last):
    File “inventoryFunc.py”, line 324, in
    ip = cvf.ScreenShot()
    File “C:\Users\yg\PycharmProjects\PathOfExileP\cvFunc.py”, line 27, in __init__
    self.mouseCoord = pa.position()
    File “C:\Users\yg\venv\lib\site-packages\pyautogui\__init__.py”, line 200, in position
    posx, posy = platformModule._position()
    File “C:\Users\yg\venv\lib\site-packages\pyautogui\_pyautogui_win.py”, line 361, in _position
    ctypes.windll.user32.GetCursorPos(ctypes.byref(cursor))
    ctypes.ArgumentError: argument 1: : expected LP_POINT instance instead of pointer to POINT

  2. ㅇㅇ 댓글:

    이전 편까지 모든 매크로 잘 실행되었는데 이번 매크로는 해당 메세지가 뜨는데 무슨 문제일까요? 제가 영어가 언어라 혹시나해서 한글로 했는데도 같은 증상이네요

    C:\Users\yg\venv\Scripts\python.exe C:/Users/yg/PycharmProjects/PathOfExileP/inventoryFunc.py
    “inven_region” Option Not Exist Take a Screenshot on Inventory
    Traceback (most recent call last):
    File “C:/Users/yg/PycharmProjects/PathOfExileP/inventoryFunc.py”, line 324, in
    ip = cvf.ScreenShot()
    File “C:\Users\yg\PycharmProjects\PathOfExileP\cvFunc.py”, line 27, in __init__
    self.mouseCoord = pa.position()
    File “C:\Users\yg\venv\lib\site-packages\pyautogui\__init__.py”, line 200, in position
    posx, posy = platformModule._position()
    File “C:\Users\yg\venv\lib\site-packages\pyautogui\_pyautogui_win.py”, line 361, in _position
    ctypes.windll.user32.GetCursorPos(ctypes.byref(cursor))
    ctypes.ArgumentError: argument 1: : expected LP_POINT instance instead of pointer to POINT

    • 호그 댓글:

      죄송합니다. 이제 봤네요 ㅜㅜ 그럼 cvFunc.py 에서 self.mouseCoord = pa.position() 를 삭제하고 돌려보시겠어요 ??

  3. 호그 댓글:

    흠 그럼 cvFunc.py 에서 self.mouseCoord = pa.position() 를 삭제하고 돌려보시겠어요 ??

    • ㅇㅇ 댓글:

      답변갑사합니다! 이제 저 에러는 또 안나는데
      Traceback (most recent call last):
      File “C:/Users/yg/PycharmProjects/PathOfExileP/inventoryFunc.py”, line 398, in
      checkInventory(it)
      File “C:/Users/yg/PycharmProjects/PathOfExileP/inventoryFunc.py”, line 385, in checkInventory
      setActivePoe()
      File “C:/Users/yg/PycharmProjects/PathOfExileP/inventoryFunc.py”, line 32, in setActivePoe
      app.connect(title_re=’Path of Exile’)
      File “C:\Users\yg\venv\lib\site-packages\pywinauto\application.py”, line 978, in connect
      self.process = findwindows.find_element(**kwargs).process_id
      File “C:\Users\yg\venv\lib\site-packages\pywinauto\findwindows.py”, line 98, in find_element
      raise exception
      pywinauto.findwindows.ElementAmbiguousError: There are 2 elements that match the criteria {‘title_re’: ‘Path of Exile’, ‘backend’: ‘win32’, ‘visible_only’: False}

      사용하다가 프로그램 끄고 poe 다시키면 이에러가 반복적으로 뜨네요 이건 뭔 에러인가요?

      • ㅇㅇ 댓글:

        poe프로그램 충돌나는거 같은데 ㅠ

        • 호그 댓글:

          이게 setActivePoe 함수 때문인데요 ㅎㅎ 이 함수는 해당 키를 눌렀을때 PoE 게임을 액티브 윈도우로 만드는 역할을 합니다. ㅎㅎ 그런데 PoE를 껏다 키면 뭔가 윈도우를 못찾는 문제가 있는 모양이네요 ㅜㅜ 함수를 아래처럼 바꾸고 해보세요 ㅎㅎ

          def setActivePoe():
          try:
          app = pwa.application.Application()
          app.connect(title_re=’Path of Exile’)
          app_dialog = app.window()
          app_dialog.set_focus()
          except:
          pass

    • poe잼 댓글:

      안녕하세요 더이상 위의 에러는 뜨지 않는데 지금 드링크 매크로는 파이참에서 인벤정리 매크로는 가상환경 통해서 사용중이에요. 근데 처음에는 잘 되다가 시간 지나서 f2를 누르면 해당 오류가 자꾸 뜨는데 무슨 문제일까요? 구글링에 검색했는데 해결방법 같은데 잘 안찾아져서 여쭙습니다.
      Traceback (most recent call last):
      File “inventoryFunc_Eng.py”, line 398, in
      checkInventory(it)
      File “inventoryFunc_Eng.py”, line 385, in checkInventory
      setActivePoe()
      File “inventoryFunc_Eng.py”, line 32, in setActivePoe
      app.connect(title_re=’Path of Exile’)
      File “C:\Users\yg\venv\lib\site-packages\pywinauto\application.py”, line 978, in connect
      self.process = findwindows.find_element(**kwargs).process_id
      File “C:\Users\yg\venv\lib\site-packages\pywinauto\findwindows.py”, line 98, in find_element
      raise exception

      pywinauto.findwindows.ElementAmbiguousError: There are 2 elements that match the criteria {‘title_re’: ‘Path of Exile’, ‘backend’: ‘win32’, ‘visible_only’: False}

  4. ㅇㅇ 댓글:

    위에 에러는 더이상 뜨지 않는데 사용잘 하다가 해당 에러가 뜨는데요
    무슨 문제일까요? poe 프로그램을 appcontent 함수가 잘못 읽는건지…
    -Inven Organize Start
    press F2
    Traceback (most recent call last):
    File “inventoryFunc.py”, line 398, in
    checkInventory(it)
    File “inventoryFunc.py”, line 385, in checkInventory
    setActivePoe()
    File “inventoryFunc.py”, line 32, in setActivePoe
    app.connect(title_re=’Path of Exile’)
    File “C:\Users\yg\venv\lib\site-packages\pywinauto\application.py”, line 978, in connect
    self.process = findwindows.find_element(**kwargs).process_id
    File “C:\Users\yg\venv\lib\site-packages\pywinauto\findwindows.py”, line 98, in find_element
    raise exception
    pywinauto.findwindows.ElementAmbiguousError: There are 2 elements that match the criteria {‘title_re’: ‘Path of Exile’, ‘backend’: ‘win32’, ‘visible_only’: False}

  5. ㅇㅇ 댓글:

    죄송합니다 댓글이 안 쓰여진것처럼 보이다가 작성을 하면 자꾸 보이네요. 같은 댓글 반복 죄송해요~

    • 호그 댓글:

      이게 setActivePoe 함수 때문인데요 ㅎㅎ 이 함수는 해당 키를 눌렀을때 PoE 게임을 액티브 윈도우로 만드는 역할을 합니다. ㅎㅎ 그런데 PoE를 껏다 키면 뭔가 윈도우를 못찾는 문제가 있는 모양이네요 ㅜㅜ 함수를 아래처럼 바꾸고 해보세요 ㅎㅎ
      다만 아래처럼 변경하고 실행시 PoE 게임을 마우스로 눌러 Active 윈도우로 만들고 실행해야 합니다.

      def setActivePoe():
      try:
      app = pwa.application.Application()
      app.connect(title_re=’Path of Exile’)
      app_dialog = app.window()
      app_dialog.set_focus()
      except:
      pass

  6. ㅇㅇ 댓글:

    게임 좀더 쉽게 하려다가… 어느샌가 파이썬 공부하면서 책만 5권이나 샀네요 !
    Hello world!!
    이거 엄청 혁신적인 언이인대요 ?
    왜케 재밌지 ㅋㅋ

    • 호그 댓글:

      ㅋㅋㅋㅋㅋ 넵 쉽고 직관적이여서 기본만 알면 구글신을 통해 왠만한건 하실수 있으실 겁니다