PoE(패스오브엑자일) 크래프팅을 도와주는 매크로 쉐이퍼와 엘더를 지원해 보자 !


안녕하세요 라이프온룸 입니드아 ㅋㅋ

오늘은 저번에 만들었던 PoE(패스오브엑자일) 크래프팅을 도와주는 매크로 에서 쉐이퍼, 엘더 아이템을 지원하도록 하게 해보겠습니다. 

저번 포스팅 대비 변경된 점은 다음과 같습니다. 

  1. config.cfg를 열지 않고 조건문을 입력할 수 있게 바꿨습니다. 
  2. prefix와 Suffix가 무조건 AND 관계 였는데 OR 관계가 될 수 있도록 변경했습니다. 
  3. 가능한 모드들을 GUI로 표현했습니다. 

이렇게 되는데요 자세한 사용법은 아래 영상을 참고해 주세요 ㅎㅎ (구독도 살짝 눌러주시면 배리 감사이구요 ㅎㅎ)

 

그리고 프로그램 링크는 아래 영상 설명란에 있습니다. 

 

0. 동작 화면 

  • F5를 눌렀을 경우 아래 처럼 해당 아이템에 가능한 Prefix/ Suffix 등이 출력 됩니다. 
  • F6을 눌렀을 경우 아래 처럼 해당 아이템에 가능한 Prefix/ Suffix 등이 자세히 출력 됩니다. 

F5 또는 F6을 누른 뒤 prefix, suffix 에 데이터를 넣고 OK를 누르면 저번에 봤던 화면이 나옵니다. 그러면 이 창을 아이템 위에 올리고 오브를 바르면 됩니다. 만약 잘못된 prefix와 suffix를 입력했을 경우 에러를 출력하게 됩니다. 

Suffix 에 | 민첩 #은 OR, & 민첩 # AND
입력한 조건식이 참인 경우.. 이제 오브를 발라보자 !
힘 #은 suffix인데 Prefix에 잘못 넣은 경우

1. config.cfg

는 변경사항이 없습니다. 다만 이제 쉐이퍼, 엘더 아이템에 대고 F5를 누를 경우 possible_item_explict 섹션에 쉐이퍼의 경우엔 sPrefix, sSuffix가, 엘더의 경우엔 ePrefix, eSuffix가 추가되었습니다. 

2. 코드 

–inventoryFunc.py–

기존 코드에서 아래 내용이 추가 되었습니다. 

K_RARENESS = '아이템 희귀도'

K_ITEMBASETYPE = 'itemBaseType' # 쉐이퍼 or 엘더

V_SHAPER = '쉐이퍼 아이템'
V_ELDER = '엘더 아이템'


def makeItemInfoOfClipboard(self, cText):
.....
        # -- ShaperElder 여부
        itemInfo[K_ITEMBASETYPE] = ''
        for idx, data in enumerate(tempList):
            if data.find(V_SHAPER) == 0 or data.find(V_ELDER) == 0:
                itemInfo[K_ITEMBASETYPE] = data
                specList.remove(data)

 

–gui.py–

import wx
import win32api
import win32con
import win32gui
import configparser
import os
import codecs
import threading
import time

colVal = (10, 10, 10)
stopColor = (247, 245, 231)
GUI_SECTION = 'gui'
GUI_OPT_FRM_SIZE = 'fram_size'

PNL_MODPRINT = 'mod/print'
PNL_MODPRINT_SHOW = 'mod/print/show/'
PNL_MODPRINT_EDIT = 'mod/print/edit/'
PNL_MODPRINT_RPNL = 'mod/print/reset_pnl/'
PNL_MODPRINT_INFO = 'mod/print/info/'

def readConfigFile(configFile, section, opt):

    config = configparser.ConfigParser(interpolation=None)
    config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))

    try:
        result = config[section][opt]
    except:
        result = None
    return result

def writeConfigFile(configFile, section, writeStr, opt = 'val'):

    config = configparser.ConfigParser(interpolation=None)
    config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))

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

    config[section][opt] = writeStr

    with open(configFile, 'w', encoding='UTF-8-sig') as config_file:
        config.write(config_file)


def setFrmPosition(win, initPos):
    win.SetPosition(initPos)

class InvenPanel(wx.Panel):

    stisfiedTxt = "조건 만족 !!"
    precond = ''
    sufcond = ''
    def __init__(self, parent):
        wx.Panel.__init__(self, parent, -1, style=wx.SIMPLE_BORDER)
        self.SetBackgroundColour(wx.Colour(colVal))
        self.mFrame = parent


        self.Bind(wx.EVT_LEFT_DCLICK, self.OnClick)

    #--------------------------------------------------------

    def OnClick(self, e):
        if e.LeftDClick():
            print('Click')

    def changeBackGround(self):
        self.SetBackgroundColour(stopColor)
        self.Refresh()
        print(self.GetSize())

        resultLabel = wx.StaticText(self, -1, self.stisfiedTxt, style=wx.ALIGN_CENTER)
        font = wx.Font(32, family=wx.DECORATIVE, style = wx.ITALIC, weight=wx.BOLD, underline=False)
        resultLabel.SetFont(font)
        resultLabel.SetForegroundColour(wx.Colour(255, 0, 0))

        resultLabel.Center()

    def makeAffixPrintContent(self, PrintStr):
        self.SetBackgroundColour(stopColor)
        self.Refresh()

        # sizer에 관하여 .. https://wxpython.org/Phoenix/docs/html/sizers_overview.html?highlight=boxsizer
        # proportion - sizer 에 들어가는 Compnent 들의 Sizer 크기 변화에 따라 커지게 할지 고정 할지를 정함
        # --- prefix 라벨과 textctl을 만들고 수평으로 배치
        preSizer = wx.BoxSizer(wx.HORIZONTAL)
        preSizer.AddSpacer(20)
        preSizer.Add(wx.StaticText(self, -1, 'Prefix', size= wx.Size(50, -1)), 1, 0, 0)
        self.preTxt = wx.TextCtrl(self, -1, 'Prefix', size= wx.Size(300, -1))
        preSizer.Add(self.preTxt, 10, 0, 0)
        preSizer.AddSpacer(20)

        # --- suffix 라벨과 textctl을 만들고 수평으로 배치
        sufSizer = wx.BoxSizer(wx.HORIZONTAL)
        sufSizer.AddSpacer(20)
        sufSizer.Add(wx.StaticText(self, -1, 'Suffix', size= wx.Size(50, -1)), 1, 0, 0)
        self.sufTxt = wx.TextCtrl(self, -1, 'Suffix', size= wx.Size(300, -1))
        sufSizer.Add(self.sufTxt, 10, 0, 0)
        sufSizer.AddSpacer(20)

        # --- 라벨과 mod가 출력될 textctl을 만들고 수직 으로 배치
        textSizer = wx.BoxSizer(wx.VERTICAL)
        textSizer.AddSpacer(20)
        textSizer.Add(wx.StaticText(self, -1, 'mods...'), 0, 0, 0)
        textSizer.AddSpacer(4)
        self.prtTxt = wx.TextCtrl(self, -1, PrintStr, style= wx.TE_MULTILINE | wx.TE_READONLY)
        textSizer.Add(self.prtTxt, 1, wx.EXPAND, 0)
        textSizer.AddSpacer(20)

        # --- 버튼을 만들고 수평으로 배치
        btnSizer = wx.BoxSizer(wx.HORIZONTAL)
        btnSizer.AddSpacer(20)
        self.btnConfirm = wx.Button(self, -1, 'OK', size= wx.Size(200, -1))
        self.btnCancel = wx.Button(self, -1, 'Cancel', size= wx.Size(200, -1))
        btnSizer.Add(self.btnConfirm, 0, wx.ALIGN_RIGHT, 0)
        btnSizer.AddSpacer(10)
        btnSizer.Add(self.btnCancel, 1, 0, 0)
        btnSizer.AddSpacer(20)

        self.logbox = wx.StaticText(self, -1, 'log', size= wx.Size(50, -1))

        # --- 만든 사이져들을 수직으로 배치
        preSufGrpSizer = wx.StaticBoxSizer(wx.VERTICAL, self, 'Condition')
        preSufGrpSizer.AddSpacer(20)
        preSufGrpSizer.Add(preSizer, 0, wx.EXPAND, 0)
        preSufGrpSizer.AddSpacer(4)
        preSufGrpSizer.Add(sufSizer, 0, wx.EXPAND, 0)
        preSufGrpSizer.AddSpacer(8)
        preSufGrpSizer.Add(self.logbox, 0, wx.EXPAND, 0)
        preSufGrpSizer.AddSpacer(8)
        preSufGrpSizer.Add(textSizer, 10, wx.EXPAND, 0)
        preSufGrpSizer.AddSpacer(4)
        preSufGrpSizer.Add(btnSizer, 0, wx.ALIGN_CENTER, 0)
        preSufGrpSizer.AddSpacer(20)

        self.preTxt.Bind(wx.EVT_TEXT, self.OnpreTxt)
        self.sufTxt.Bind(wx.EVT_TEXT, self.OnsufTxt)

        self.btnConfirm.Bind(wx.EVT_BUTTON, self.OnbtnConfirm)
        self.btnCancel.Bind(wx.EVT_BUTTON, self.OnbtnCancel)

        self.SetSizer(preSufGrpSizer)
        self.Layout()

    def OnpreTxt(self, event):
        self.precond = event.GetString()
        pass

    def OnsufTxt(self, event):
        self.sufcond = event.GetString()
        pass

    def OnbtnConfirm(self, event):
        msg = {
            'condData':{
                'prefix': self.precond,
                'suffix': self.sufcond,
            }
        }
        self.mFrame.orb_q.put_nowait(msg)
        # time.sleep(0.1)
        # self.mFrame.OnCloseWindow(None)
        pass

    def OnbtnCancel(self, event):
        self.mFrame.OnCloseWindow(None)
        pass

    def editTextCtrl(self, text):
        self.prtTxt.SetValue(text)

    def editLogBox(self, text):
        self.logbox.SetLabel(text)
        self.logbox.SetForegroundColour(wx.Colour(255, 0, 0))


    # def setInitBackgroundColor(self):
    #     self.SetBackgroundColour(wx.BLACK)

    def destroyPanel(self):
        self.Destroy()


class AppFrame(wx.Frame):

    satisfied = False
    resized = False
    moving = False
    pressedKey = ''
    modStr = ''
    errStr = ''

    def __init__(self, gui_q, orbHelper_q, initSize, configFile):
        if initSize != None:
            s = wx.Size(initSize[0], initSize[1])
        else:
            s = wx.DefaultSize
        self.configFile = configFile
        wx.Frame.__init__(self, None, title="Inventory", size=s,
                          style=wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP )

        self.statusbar = self.CreateStatusBar(1)

        self.gui_q = gui_q
        self.orb_q = orbHelper_q
        self.makeTransparent()

        # self.pnl = InvenPanel(self)
        # hbox = wx.BoxSizer(wx.HORIZONTAL)
        #
        # hbox.Add(self.pnl, 1, wx.EXPAND | wx.ALL, 5)
        # self.SetSizer(hbox)
        # self.Centre()
        self.makePanel()

        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow)
        self.Bind(wx.EVT_MOVE, self.OnMove)
        self.Bind(wx.EVT_SIZE, self.OnSize)
        self.Bind(wx.EVT_IDLE, self.OnIdle)
        self.Bind(wx.EVT_KEY_DOWN, self.OnKeyDown)
        self.Bind(wx.EVT_KEY_UP, self.OnKeyUp)

        self.qThreadKill = False
        self.qThread = threading.Thread(target=self.qReceive, args=(self.gui_q, ))
        self.qThread.daemon = True
        self.qThread.start()

        #end AppFrame class
        # self.showAffixPrintMode()
        # self.refreshPanel()


    #--------------------------------------------------------
    def makePanel(self):
        self.pnl = InvenPanel(self)
        self.Refresh()

        hbox = wx.BoxSizer(wx.HORIZONTAL)

        hbox.Add(self.pnl, 1, wx.EXPAND | wx.ALL, 5)
        self.SetSizer(hbox)
        self.Centre()
        self.Layout()


    def refreshPanel(self):
        self.pnl.destroyPanel()
        self.makePanel()



    def makeTransparent(self):

        hwnd = self.GetHandle()
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE,
                           win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
        # colVal 에 해당하는 색을 가진 영역을 투명하게 변경 후 마우스 입력을 받도록 설정
        win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*colVal), 0, win32con.LWA_COLORKEY)

    def makeTransparentWhole(self):
        # 전체 프레임을 투명하게 함
        hwnd = self.GetHandle()
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE,
                           win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
        win32gui.SetLayeredWindowAttributes(hwnd, 0, 60, win32con.LWA_ALPHA)

    def changePnlColor(self):
        self.pnl.changeBackGround()

    def setStatusBarText(self, strs):
        self.statusbar.SetStatusText(strs)

    def showAffixPrintPnl(self):
        self.pnl.makeAffixPrintContent(self.modStr)

    def editAffixPrintTextCtrl(self):
        self.pnl.editTextCtrl(self.modStr)

    def editAffixPrintLogBox(self):
        self.pnl.editLogBox(self.errStr)


    # --------------------------------------------------------

    def qReceive(self, msgQ):
        while not self.qThreadKill:
            if not msgQ.empty():
                msg = msgQ.get()
                if msg == 'item/match':
                    print('gui item match ')
                    #self.makeTransparent()
                    wx.CallAfter(self.changePnlColor)
                elif msg == 'item/wait':
                    wx.CallAfter(self.setStatusBarText, 'Wait ....')

                elif msg == 'item/missmatch':
                    wx.CallAfter(self.setStatusBarText, 'Miss Match')

                elif msg.find('item/name') >= 0:
                    pickedItem = os.path.basename(msg)
                    stText = pickedItem + 'Picked'
                    wx.CallAfter(self.setStatusBarText, stText)

                elif msg.find(PNL_MODPRINT) >=0:
                    if msg.find(PNL_MODPRINT_SHOW) >= 0:
                        self.modStr = msg[len(PNL_MODPRINT_SHOW):]
                        wx.CallAfter(self.showAffixPrintPnl)
                    elif msg.find(PNL_MODPRINT_EDIT) >= 0:
                        self.modStr = msg[len(PNL_MODPRINT_EDIT):]
                        wx.CallAfter(self.editAffixPrintTextCtrl)
                    elif msg.find(PNL_MODPRINT_RPNL) >= 0:
                        # 투명창을 띄움
                        wx.CallAfter(self.refreshPanel)
                    elif msg.find(PNL_MODPRINT_INFO) >= 0:
                        self.errStr = msg[len(PNL_MODPRINT_INFO):]
                        wx.CallAfter(self.editAffixPrintLogBox)
                    else:
                        print('mod print mode error')

        print('gui thread end')

    #--------------------------------------------------------
    def OnMove(self, e):
        self.moving = True


    def OnSize(self, e):
        e.Skip()
        self.resized = True


    def OnIdle(self, e):
        if self.resized:
            frmSize = tuple(self.GetPosition()) + tuple(self.GetSize())
            writeConfigFile(self.configFile, GUI_SECTION, str(frmSize), GUI_OPT_FRM_SIZE)
            self.resized = False

        elif self.moving:
            frmSize = tuple(self.GetPosition()) + tuple(self.GetSize())
            writeConfigFile(self.configFile, GUI_SECTION, str(frmSize), GUI_OPT_FRM_SIZE)
            #print(self.pnl.GetSize())
            self.moving = False
    #--------------------------------------------------------
    # 테스트
    def OnKeyDown(self, e):
        self.pressedKey = e.GetKeyCode()
        print(self.pressedKey)


    def OnKeyUp(self, e):
        if self.pressedKey == e.GetKeyCode():
            if self.pressedKey == wx.WXK_F1:
                print('Pressed')
                self.makeTransparent()
                self.pnl.changeBackGround()
                #self.pnl.SetBackgroundColour(wx.BLUE)

            self.pressedKey = ''
    # --------------------------------------------------------

    def OnCloseWindow(self, evt) :
        #self.pnl.setInitBackgroundColor()
        self.qThreadKill = True
        self.Destroy()
    # --------------------------------------------------------
#-----------------------------------------------------
#
# class invenProcessor(wx.App):
#     def OnInit(self):
#         frame = AppFrame(None)
#         frame.Show(True)
#         return True


#end AppFrame class

#=======================================================

class TextFrame(wx.Frame):
    def __init__(self, texts):

        wx.Frame.__init__( self, None, title=" ",
                           style= wx.STAY_ON_TOP | wx.NO_BORDER)
                           #style= wx.DEFAULT_FRAME_STYLE | wx.STAY_ON_TOP )
        self.SetClientSize((200, 200))
        self.texts = texts

        self.SetBackgroundColour(wx.BLACK)
        self.makeTransparent()
        #
        pnl = wx.Panel(self, size=(200, 200))
        resultLabel = wx.StaticText(pnl, -1, self.texts, style=wx.ALIGN_CENTER)
        font = wx.Font(24, family=wx.DECORATIVE, style = wx.ITALIC, weight=wx.BOLD, underline=False)
        resultLabel.SetFont(font)
        resultLabel.SetForegroundColour(wx.Colour(255, 0, 0))

        resultLabel.Center()

        resultLabel.Bind(wx.EVT_ENTER_WINDOW, self.OnCloseWindow)
        self.Bind(wx.EVT_CLOSE, self.OnCloseWindow )


    #end AppFrame class

    #--------------------------------------------------------

    def OnCloseWindow(self, evt ) :
        self.Destroy()

    #-----------------------------------------------------

    def makeTransparent(self):

        hwnd = self.GetHandle()
        win32gui.SetWindowLong(hwnd, win32con.GWL_EXSTYLE,
                           win32gui.GetWindowLong(hwnd, win32con.GWL_EXSTYLE) | win32con.WS_EX_LAYERED)
        # colVal 에 해당하는 색을 가진 영역을 투명하게 변경 후 마우스 입력을 받도록 설정
        win32gui.SetLayeredWindowAttributes(hwnd, win32api.RGB(*colVal), 0, win32con.LWA_COLORKEY)


if __name__ == '__main__' :



    # test
    from ast import literal_eval
    import wx.lib.inspection
    import queue

    testQ = queue.Queue()

    configFile = os.path.dirname(os.path.realpath(__file__)) + '\\' + 'config.cfg'
    config = configparser.ConfigParser(interpolation=None)
    config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))


    try:
        initPosSize = literal_eval(config[GUI_SECTION][GUI_OPT_FRM_SIZE])
        initPos = initPosSize[:2]
        initSize = initPosSize[2:]
    except:
        initSize = None
        initPos = None


    app = wx.App(False)
    frm = AppFrame(testQ, testQ, initSize, configFile)
    if initPos != None:
        setFrmPosition(frm, initPos)
    frm.Show()
    #wx.lib.inspection.InspectionTool().Show()
    app.MainLoop()


 

–orbHelper.py–

#-*- coding:utf-8 -*-
import inventoryFunc as invenF
import gui as gui
import mouse as mo
import keyboard as keys
import pprint
import time
import os
import codecs
import json
import re

import multiprocessing as mp
import configparser
from ast import literal_eval

SECTION_ORB = 'orb_helper'
SECTION_POS = 'possible_item_explict'
SECTION_CUR = 'current_item_explict'
SECTION_COND = 'tobe_item_explict'
jsonFileDBs = ['mods']
modsDB = {}

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)
        modsDB = json_data
    f.close()

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()


GUITHREAD = None
GUIQ = mp.Queue()
ORBHELPERQ = mp.Queue()

def deleteSpace(strOrList):
    returnList = []
    if type(strOrList) == list:
        for mod in strOrList:
            returnList.append(mod.replace(' ', ''))
    elif type(strOrList) == str:
        returnList = strOrList.replace(' ', '')
    return returnList

# mod.json의 Prefix Suffix 항목들을 Lv 별로 재정리
def sortAndFilt(modList, itemLevel):

    itemLevel = int(itemLevel)
    # valList = []
    # for tmpDict in modList:
    #     valList.append(tmpDict)

    newlist = sorted(modList, key=lambda k: int([*k.values()][0]['lv']))
    filtList = list(filter(lambda k: int([*k.values()][0]['lv']) <= itemLevel, newlist))

    #print(filtList)
    if filtList == []:
        return None, None, None


    minVal = [*filtList[0].values()][0]['val']
    maxVal = [*filtList[-1].values()][0]['val']

    detailStr = ''
    for data in filtList:
        for k, v in data.items():
            #detailStr += '-- affix: %-8s lv: %-3s stat: %s \n' % (k, v['lv'], v['val'])
            valueStr = v['val'].replace('\n', ' / ' )
            detailStr += '    -- affix: ' + k.ljust(8) + 'lv: ' + v['lv'].ljust(4) + 'stat: ' + valueStr + '\n'

    return minVal, maxVal, detailStr

def makeItemModStr(modStr, strToAdd):
    if modStr.find('\n') >= 0:
        tmpStr = modStr.split('\n')
        strToAdd += '/'.join(tmpStr) + '\n'
    else:
        strToAdd += modStr + '\n'

    return strToAdd

def writeConfigFile(configFile, section, writeStr, opt = 'val'):
    config = configparser.ConfigParser(interpolation=None)
    config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))

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

    config[section][opt] = writeStr

    with open(configFile, 'w', encoding='UTF-8-sig') as config_file:
        config.write(config_file)

def getCurrentItemExplict(modValReg, invenItem):

    comExpStringList = []

    if invenF.K_EXPLICT in invenItem:
        for expString in invenItem[invenF.K_EXPLICT]:
            comExpString = expString

            while True:

                ms = modValReg.search(comExpString)
                if ms == None:
                    break

                start, end = ms.span()
                comExpString = comExpString[:start] + '#' + comExpString[end:]
            comExpString = deleteSpace(comExpString)
            comExpStringList.append(comExpString)

    return comExpStringList

def getAffixList(itemBaseType):
    returnList = []
    if itemBaseType == invenF.V_SHAPER:
        returnList = ['prefix', 'suffix', 'sPrefix', 'sSuffix']
    elif itemBaseType == invenF.V_ELDER:
        returnList = ['prefix', 'suffix', 'ePrefix', 'eSuffix']
    else:
        returnList = ['prefix', 'suffix']
    return returnList

# affix dictonary 를 prefix, suffix로 단순화 시킴
def makeAffixDictToSimple(affixDict):

    returnDict = {
        'prefix': [],
        'suffix': []
    }

    for affix, val in affixDict.items():
        if affix.lower().find('prefix') >= 0:
            returnDict['prefix'] += val
        elif affix.lower().find('suffix') >= 0:
            returnDict['suffix'] += val

    return returnDict


# 특정 아이템의 레벨별 모드 정보를 불러옴
def getPossibleMod(modValReg, invenItem, configFile, detail=False):

    if invenItem == None:
        return None, None
    # pprint.pprint(result)
    print('-----------')

    affixDict = {}

    try:
        itemLv = int(invenItem[invenF.KG_ITEMLV])
    except:
        print('No ITEM LEVEL')


    itemClass = invenItem[invenF.K_ITEMCLASS]
    comExpStringList = []
    configModStr = ''
    if invenF.K_EXPLICT in invenItem:
        for expString in invenItem[invenF.K_EXPLICT]:
            comExpString = expString
            configModStr += expString + '\n'
            while True:
                ms = modValReg.search(comExpString)
                if ms == None:
                    break

                start, end = ms.span()
                comExpString = comExpString[:start] + '#' + comExpString[end:]
            comExpStringList.append(comExpString)
        configModStr = '\n' + configModStr
        writeConfigFile(configFile, SECTION_CUR, configModStr)

    affixList = getAffixList(invenItem[invenF.K_ITEMBASETYPE])

    print('Curren Item Explict:' + configModStr)
    print('----------------------------------------')
    configModStr = ''
    for mainClass, itemData in modsDB.items():
        if itemClass in itemData:
            configModStr += '++++++++++++++++++++++++++++++++++++++++' + '\n'
            configModStr += '++ Possible Mod on ' + itemClass + ' Item Level : ' + str(itemLv) + '\n'
            configModStr += '++++++++++++++++++++++++++++++++++++++++' + '\n'
            for affix in affixList:

                configModStr += '+ ' + affix + '\n'
                configModStr += '++++++++++++++++++++++++++++++++++++++++' + '\n'
                affixDict[affix] = []

                for invenItemMod, modVal in itemData[itemClass][affix].items():
                    modMin, modMax, modStr = sortAndFilt(modVal['modval'], itemLv)
                    if modMin != None:
                        affixDict[affix].append(invenItemMod)
                        configModStr = makeItemModStr(invenItemMod, configModStr)
                        if detail == True:
                            configModStr += modStr
                configModStr += '++++++++++++++++++++++++++++++++++++++++' + '\n'

            print(configModStr)
            # minMax = sortAndFilt(modVal['modval'], itemLv)
            # print('\t minmax: ', minMax)
            configModStr = '\n' + configModStr
            writeConfigFile(configFile, SECTION_POS, configModStr)

            break

            # for invenItemMod in comExpStringList:
            #     if invenItemMod in [*itemData[itemClass]['prefix']]:
            #         print(invenItemMod, 'is', ' prefix')
            #     elif invenItemMod in [*itemData[itemClass]['suffix']]:
            #         print(invenItemMod, 'is', ' suffix')


    affixDict = makeAffixDictToSimple(affixDict)

    return affixDict, configModStr

# 입력한 조건식이 유효한지 판단
def checkConditionValidation(conditionList, rarity, possibleMods):

    affixCntDict = {}
    returnModList = []
    for affix, condition in conditionList.items():
        affixCntDict[affix] = 0
        andModList = condition.split('&')
        andModList = [i.strip() for i in andModList]
        if (andModList[0] == '' or andModList[0] == '|') and len(andModList) == 1:
            continue

        if andModList[0].find('|') == 0:
            newMode = returnModList.pop(-1) + andModList.pop(0)
            returnModList += [newMode]
            returnModList += andModList

        elif andModList[0] == '':
            andModList.pop(0)
            returnModList += andModList

        else:
            returnModList += andModList

    # 정규표현식
    # modStrRegEx = re.compile('([^|&]+)')
    # operatorRegEx = re.compile('([|&]+)')
    #
    # modList = modStrRegEx.findall(condition)
    # modList = [i.strip() for i in modList]
    #
    # opList = operatorRegEx.findall(condition)
    # opList = [i.strip() for i in opList]

        print('----------------------------------------')
        print(affix, ' Condition Mode List:', returnModList)


        checkValidCondition = 0

        for orExpresion in andModList:
            condMods = orExpresion.split('|')
            condMods = [i.strip() for i in condMods]
            for condMod in condMods:
                for modDB in possibleMods[affix]:
                    if modDB.find(condMod) >= 0:
                        print(affix, ' cond: ', condMod, affix, ' db : ', modDB)
                        checkValidCondition = 1
                        break
                if checkValidCondition == 0:
                    print('no condition found on DB')
                    return False
                checkValidCondition = 0
            affixCntDict[affix] += 1

        print(affix + 'CNT : ' +  str(affixCntDict[affix]))
    print('----------------------------------------')

    totalCnt = 0
    for affix, cnt in affixCntDict.items():
        totalCnt += cnt
        if rarity == invenF.V_MAGIC:
            if cnt > 1:
                return False
        elif rarity == invenF.V_RARE:
            if cnt > 3:
                return False

    if totalCnt == 0:
        return False

    print(returnModList)
    returnModList = deleteSpace(returnModList)
    return returnModList


# 입력한 조건식과 실제 아이템의 Explict List 가 부합하는지 확인
def compareConditionExpress(explictList, andModList):

    condition = 0
    condList = []

    for orExpresion in andModList:
        condMods = orExpresion.split('|')
        condMods = [i.strip() for i in condMods]
        for condMod in condMods:
            for itemMod in explictList:
                if itemMod.find(condMod) >= 0:
                    condition = True
        condList.append(condition)
        condition = False

    if False in condList:
        return False
    return True

    pass

# Gui 프로세스
def guiProcess(gui_q, orbHelper_q, guiInitPosSize, configFile):
    if guiInitPosSize != None:
        initPos = guiInitPosSize[:2]
        initSize = guiInitPosSize[2:]
    else:
        initSize = None
        initPos = None
    app = gui.wx.App(False)
    frm = gui.AppFrame(gui_q, orbHelper_q, initSize, configFile)
    if initPos != None:
        gui.setFrmPosition(frm, initPos)
    frm.Show()
    app.MainLoop()
    msg = {'end': ''}
    orbHelper_q.put_nowait(msg)

def runGui(configFile):
    global GUITHREAD
    global GUIQ
    global ORBHELPERQ

    guiInitPosSize = gui.readConfigFile(configFile, gui.GUI_SECTION, gui.GUI_OPT_FRM_SIZE)
    if guiInitPosSize != None:
        guiInitPosSize = literal_eval(guiInitPosSize)

    if GUITHREAD == None:
        GUITHREAD = mp.Process(target=guiProcess, args=(GUIQ, ORBHELPERQ, guiInitPosSize, configFile))
        GUITHREAD.start()
        #GUITHREAD.join()
        return True
    else:
        print('gui Alive')
        return False

def runGuiForPrint(configFile, modStr):


    if runGui(configFile):
        msg = gui.PNL_MODPRINT_SHOW + modStr
    else:
        msg = gui.PNL_MODPRINT_EDIT + modStr
    GUIQ.put_nowait(msg)


def mainOrbHelper(keyboardKey, configFile):
    global GUITHREAD
    it = invenF.InventoryTool((2599, 1152, 1213, 513), [])
    modValReg = re.compile('([+.0-9]+)')

    moLState = 0
    moRState = 0
    listKeyState = [0] * len(keyboardKey)

    orbPicked = 0
    blockMouseOn = 0

    conditionList = False
    modDict = {}
    invItem = 0

    while True:
        time.sleep(0.001)
        valLeft = mo.is_pressed('left')
        valRight = mo.is_pressed('right')
        try:
            dataFromGui = ORBHELPERQ.get_nowait()
            if 'end' in dataFromGui.keys():
                GUITHREAD = None
                blockMouseOn = False
                conditionList = False
                orbPicked = 0
            elif 'condData' in dataFromGui.keys():
                prefixStr = dataFromGui['condData']['prefix']
                writeConfigFile(configFile, SECTION_COND, prefixStr, 'prefix')
                suffixStr = dataFromGui['condData']['suffix']
                writeConfigFile(configFile, SECTION_COND, suffixStr, 'suffix')

                config = configparser.ConfigParser(interpolation=None)
                config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))
                condDict = {
                    'prefix': config[SECTION_COND]['prefix'],
                    'suffix': config[SECTION_COND]['suffix']
                }

                conditionList = checkConditionValidation(condDict, invItem[invenF.K_RARENESS], modDict)

                if conditionList != False:
                    print('Condition you put: ', conditionList, 'is Valid')
                    itemExplictList = getCurrentItemExplict(modValReg, invItem)
                    print('item Explict : ', itemExplictList)
                    if itemExplictList != []:
                        blockMouseOn = True
                        # 패널 최기화 시키고 투명으로 다시 만든 후 해야함

                        GUIQ.put_nowait(gui.PNL_MODPRINT_RPNL)

                        condMatch = compareConditionExpress(itemExplictList, conditionList)
                        print('Condition Match : ', condMatch)
                        if condMatch:
                            GUIQ.put_nowait('item/match')
                    else:
                        # GUI q 로 전송
                        #print('this item have no explict')
                        msg = gui.PNL_MODPRINT_INFO + 'this item have no explict'
                        GUIQ.put_nowait(msg)

                else:
                    # GUI q 로 전송
                    # print('Condition Expresion Error')
                    msg = gui.PNL_MODPRINT_INFO + 'Condition Expresion Error'
                    GUIQ.put_nowait(msg)



        except:
            dataFromGui = None
            pass

        if blockMouseOn == True:
            # -- left mouse
            if valLeft != moLState and valLeft == True and orbPicked == 1:
                GUIQ.put_nowait('item/wait')
                time.sleep(0.3)

                #GUIQ.put_nowait('item/match')

                result = it.getItemInfoForMods((0, 0), itemDB)
                if result != None:
                    itemExplictList = getCurrentItemExplict(modValReg, result)
                    print('item Explict : ', itemExplictList)
                    if itemExplictList != []:
                        matching = compareConditionExpress(itemExplictList, conditionList)
                        if matching == True:
                            print('Condition Matched')
                            blockMouseOn = False
                            conditionList = False
                            orbPicked = 0
                            GUIQ.put_nowait('item/match')
                        else:
                            print('Condition Not Matched')
                            GUIQ.put_nowait('item/missmatch')
                    else:
                        print('no item explict')


                moLState = valLeft
            elif valLeft != moLState and valLeft == False:
                value = keys.is_pressed('shift')
                if value == False:
                    orbPicked = 0
                moLState = valLeft

            # -- right mouse
            if valRight != moRState and valRight == True:
                moRState = valRight
                pass

            elif valRight != moRState and valRight == False:

                result = it.getItemInfoFromClipboard((0, 0))
                try:
                    if result[invenF.K_ITEMBASENAME].find('오브') >= 0:
                        msg = 'item/name/' + result[invenF.K_ITEMBASENAME]
                        GUIQ.put_nowait(msg)
                        orbPicked = 1
                except:
                    pass
                moRState = valRight

        # -- keys
        for idx, pressedKey in enumerate(keyboardKey):
            value = keys.is_pressed(pressedKey)
            if value == True:
                # F5
                if idx == 0 and listKeyState[idx] != value:
                    invenF.setActivePoe()
                    invItem = it.getItemInfoForMods((0, 0), itemDB)
                    modDict, modStr = getPossibleMod(modValReg, invItem, configFile)

                    listKeyState[idx] = value
                    if modStr != None:
                        runGuiForPrint(configFile, modStr)
                # F6
                elif idx == 1 and listKeyState[idx] != value:
                    invenF.setActivePoe()
                    invItem = it.getItemInfoForMods((0, 0), itemDB)
                    modDict, modStr = getPossibleMod(modValReg, invItem, configFile, detail=True)

                    listKeyState[idx] = value
                    if modStr != None:
                        runGuiForPrint(configFile, modStr)
                # F7
                elif idx == 2 and listKeyState[idx] != value:
                    invenF.setActivePoe()
                    listKeyState[idx] = value
                    # -- Condition Check 후 현제 아이템 상태가 조건을 만족하는지 확인
                    print('Mouse Blocker Start')
                    if blockMouseOn == False:

                        config = configparser.ConfigParser(interpolation=None)
                        config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))
                        condDict ={
                            'prefix' : config[SECTION_COND]['prefix'],
                            'suffix' : config[SECTION_COND]['suffix']
                        }

                        result = it.getItemInfoForMods((0, 0), itemDB)
                        if result != None:
                            modDict, _ = getPossibleMod(modValReg, result, configFile)
                            conditionList = checkConditionValidation(condDict, result[invenF.K_RARENESS], modDict)

                            if conditionList != False:
                                print('Condition you put: ', conditionList, 'is Valid')
                                itemExplictList = getCurrentItemExplict(modValReg, result)
                                print('item Explict : ', itemExplictList)
                                if itemExplictList != []:
                                    if runGui(configFile) == True:
                                        condMatch = compareConditionExpress(itemExplictList, conditionList)
                                        print('Condition Match : ', condMatch)
                                        if condMatch:
                                            GUIQ.put_nowait('item/match')
                                else:
                                    print('this item have no explict')
                                    break
                            else:
                                print('Condition Expresion Error')
                                break
                        else:
                            break

                        blockMouseOn = True
                    # else:
                    #     conditionList = False
                    #     blockMouseOn = False

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

if __name__=="__main__":
    # multiprocessing code 를 excutable로 만들경우 아래 코드가 필요
    mp.freeze_support()



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

    config = configparser.ConfigParser(interpolation=None)
    config.read_file(codecs.open(configFile, 'r', 'UTF-8-sig'))

    getPosModKey = config[SECTION_ORB]['key_possible_mod']
    getPosModKeyDetail = config[SECTION_ORB]['key_possible_mod_detail']
    blockMouse = config[SECTION_ORB]['key_orb_mouse_block']



    print('orb helper started !')
    mainOrbHelper([getPosModKey, getPosModKeyDetail, blockMouse], configFile)



 



블로그 구독하기 !!

You may also like...

9 Responses

  1. 당신의 팬 댓글:

    유용한 자료 감사합니다.

  2. lks 댓글:

    우선 감사하단 인사드립니다 ^^
    작동중에
    비카오스 피해의 #%를 추가 카오스 피해로 획득
    이옵션이 이름이 바껴서 작동이안되는데 수정법 있나여?
    카오스가 아닌 피해의 #%를 추가 카오스 피해로 획득
    이렇게 바꼈습니다

    • 호그 댓글:

      data -> mods.json 파일에서 해당 내용 검색후 변경 하시면 됩니다. !! ㅎㅎ

  3. ㅇㅇ 댓글:

    혹시 프리픽스나 서픽스에 두가지 옵션을 넣을순없나요 둘중 하나만 만족하면 동작할수 있게

  4. JH 댓글:

    안녕하세요. 종종 둘러보게 됩니다.
    이 글에서 제가 이해한, 각각 프리픽스와 서픽스의 세부 등급은 조정하지 못한다는게 맞나요?

  5. 링크가 어딨을까요 댓글:

    링크 어딨나요?ㅜㅠ

  6. 지나가는행인 댓글:

    안녕하세요 질문좀 드립니…
    3.9에서 새롭게 등록된 정복자 베이스통해서 하려고 했는데
    data폴더안의 내용물을 수정해보려고 해도… 까막눈이 하는 배껴쓰기로는 효과가 없더라구요…
    mods << 이거 수정하면 가능한게 맞나요..??
    설명좀 부탁드립니다..

  7. 행인 댓글:

    poedb.tw에서 접두 접미에 대해 크롤링 하셧던 건지 질문 드립니다. 막상 body 쪽을 까보니 어떻게 해야 이쁠지 감이 안오네요.