PoE(패스오브엑자일) 크래프팅을 도와주는 매크로 쉐이퍼와 엘더를 지원해 보자 !
안녕하세요 라이프온룸 입니드아 ㅋㅋ
오늘은 저번에 만들었던 PoE(패스오브엑자일) 크래프팅을 도와주는 매크로 에서 쉐이퍼, 엘더 아이템을 지원하도록 하게 해보겠습니다.
저번 포스팅 대비 변경된 점은 다음과 같습니다.
- config.cfg를 열지 않고 조건문을 입력할 수 있게 바꿨습니다.
- prefix와 Suffix가 무조건 AND 관계 였는데 OR 관계가 될 수 있도록 변경했습니다.
- 가능한 모드들을 GUI로 표현했습니다.
이렇게 되는데요 자세한 사용법은 아래 영상을 참고해 주세요 ㅎㅎ (구독도 살짝 눌러주시면 배리 감사이구요 ㅎㅎ)
그리고 프로그램 링크는 아래 영상 설명란에 있습니다.
0. 동작 화면
- F5를 눌렀을 경우 아래 처럼 해당 아이템에 가능한 Prefix/ Suffix 등이 출력 됩니다.
- F6을 눌렀을 경우 아래 처럼 해당 아이템에 가능한 Prefix/ Suffix 등이 자세히 출력 됩니다.
F5 또는 F6을 누른 뒤 prefix, suffix 에 데이터를 넣고 OK를 누르면 저번에 봤던 화면이 나옵니다. 그러면 이 창을 아이템 위에 올리고 오브를 바르면 됩니다. 만약 잘못된 prefix와 suffix를 입력했을 경우 에러를 출력하게 됩니다.
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)
블로그 구독하기 !!
유용한 자료 감사합니다.
우선 감사하단 인사드립니다 ^^
작동중에
비카오스 피해의 #%를 추가 카오스 피해로 획득
이옵션이 이름이 바껴서 작동이안되는데 수정법 있나여?
카오스가 아닌 피해의 #%를 추가 카오스 피해로 획득
이렇게 바꼈습니다
data -> mods.json 파일에서 해당 내용 검색후 변경 하시면 됩니다. !! ㅎㅎ
혹시 프리픽스나 서픽스에 두가지 옵션을 넣을순없나요 둘중 하나만 만족하면 동작할수 있게
유튜브에서 답변 드렸습니다.
안녕하세요. 종종 둘러보게 됩니다.
이 글에서 제가 이해한, 각각 프리픽스와 서픽스의 세부 등급은 조정하지 못한다는게 맞나요?
링크 어딨나요?ㅜㅠ
안녕하세요 질문좀 드립니…
3.9에서 새롭게 등록된 정복자 베이스통해서 하려고 했는데
data폴더안의 내용물을 수정해보려고 해도… 까막눈이 하는 배껴쓰기로는 효과가 없더라구요…
mods << 이거 수정하면 가능한게 맞나요..??
설명좀 부탁드립니다..
poedb.tw에서 접두 접미에 대해 크롤링 하셧던 건지 질문 드립니다. 막상 body 쪽을 까보니 어떻게 해야 이쁠지 감이 안오네요.