diff --git a/assets/root/game.py b/assets/root/game.py index 8d4747fa..b81463c2 100644 --- a/assets/root/game.py +++ b/assets/root/game.py @@ -34,6 +34,7 @@ import uiPlayerGauge import uiCharacter import uiTarget import uiAutopickup +import uiStoneQueue # PRIVATE_SHOP_PRICE_LIST import uiPrivateShopBuilder @@ -2179,6 +2180,7 @@ class GameWindow(ui.ScriptWindow): "horse_state" : self.__Horse_UpdateState, "hide_horse_state" : self.__Horse_HideState, "AutoPickupState" : self.__AutoPickupState, + "StoneQueueState" : self.__StoneQueueState, "WarUC" : self.__GuildWar_UpdateMemberCount, "test_server" : self.__EnableTestServerFlag, "mall" : self.__InGameShop_Show, @@ -2229,6 +2231,9 @@ class GameWindow(ui.ScriptWindow): def __AutoPickupState(self, enabled, mode, mask, vip): uiAutopickup.SetAutoPickupState(int(enabled), int(mode), int(mask), int(vip)) + def __StoneQueueState(self, maxCount, active, current, success, fail): + uiStoneQueue.SetStoneQueueState(int(maxCount), int(active), int(current), int(success), int(fail)) + def AskSafeboxPassword(self): self.interface.AskSafeboxPassword() diff --git a/assets/root/uiStoneQueue.py b/assets/root/uiStoneQueue.py new file mode 100644 index 00000000..349782b8 --- /dev/null +++ b/assets/root/uiStoneQueue.py @@ -0,0 +1,233 @@ +import item +import net +import player +import ui + + +STATE_MAX = 3 +STATE_ACTIVE = 0 +STATE_CURRENT = 0 +STATE_SUCCESS = 0 +STATE_FAIL = 0 +OPEN_WINDOWS = [] + + +def SetStoneQueueState(maxCount, active, current, success, fail): + global STATE_MAX + global STATE_ACTIVE + global STATE_CURRENT + global STATE_SUCCESS + global STATE_FAIL + + STATE_MAX = max(1, int(maxCount)) + STATE_ACTIVE = 1 if int(active) else 0 + STATE_CURRENT = max(0, int(current)) + STATE_SUCCESS = max(0, int(success)) + STATE_FAIL = max(0, int(fail)) + + for window in OPEN_WINDOWS: + try: + window.Refresh() + except: + pass + + +class StoneQueueWindow(ui.BoardWithTitleBar): + PAGE_SIZE = 20 + + def __init__(self): + ui.BoardWithTitleBar.__init__(self) + + OPEN_WINDOWS.append(self) + + self.scrollSlotPos = -1 + self.selectedSlots = [] + self.eligibleSlots = [] + self.pageIndex = 0 + self.candidateButtons = [] + self.queueLines = [] + + self.AddFlag("float") + self.AddFlag("movable") + self.SetSize(340, 355) + self.SetTitleName("Stone Queue") + self.SetCloseEvent(self.Hide) + + self.__CreateChildren() + self.Hide() + + def __del__(self): + if self in OPEN_WINDOWS: + OPEN_WINDOWS.remove(self) + ui.BoardWithTitleBar.__del__(self) + + def Destroy(self): + if self in OPEN_WINDOWS: + OPEN_WINDOWS.remove(self) + self.ClearDictionary() + self.selectedSlots = [] + self.eligibleSlots = [] + self.candidateButtons = [] + self.queueLines = [] + + def __CreateChildren(self): + self.scrollLine = self.__CreateLine(15, 36) + self.statusLine = self.__CreateLine(15, 56) + self.progressLine = self.__CreateLine(15, 76) + self.resultLine = self.__CreateLine(15, 96) + + self.prevButton = self.__CreateButton(15, 118, 45, "Prev") + self.prevButton.SetEvent(self.__ChangePage, -1) + self.pageLine = self.__CreateLine(127, 122) + self.nextButton = self.__CreateButton(280, 118, 45, "Next") + self.nextButton.SetEvent(self.__ChangePage, 1) + + for row in range(5): + for column in range(4): + button = self.__CreateButton(15 + column * 78, 145 + row * 24, 72, "-") + self.candidateButtons.append(button) + + for index in range(8): + line = self.__CreateLine(15, 272 + index * 10) + self.queueLines.append(line) + + self.startButton = self.__CreateButton(185, 328, 65, "Start") + self.startButton.SetEvent(self.__StartQueue) + self.cancelButton = self.__CreateButton(260, 328, 65, "Cancel") + self.cancelButton.SetEvent(self.__CancelQueue) + + def __CreateLine(self, x, y): + textLine = ui.TextLine() + textLine.SetParent(self) + textLine.SetPosition(x, y) + textLine.SetOutline() + textLine.Show() + return textLine + + def __CreateButton(self, x, y, width, text): + button = ui.Button() + button.SetParent(self) + button.SetPosition(x, y) + button.SetUpVisual("d:/ymir work/ui/public/small_thin_button_01.sub") + button.SetOverVisual("d:/ymir work/ui/public/small_thin_button_02.sub") + button.SetDownVisual("d:/ymir work/ui/public/small_thin_button_03.sub") + button.SetDisableVisual("d:/ymir work/ui/public/small_thin_button_01.sub") + button.SetSize(width, 17) + button.SetText(text) + button.Show() + return button + + def __BuildEligibleSlots(self): + self.eligibleSlots = [] + if self.scrollSlotPos < 0: + return + + scrollIndex = player.GetItemIndex(self.scrollSlotPos) + for slot in range(player.INVENTORY_PAGE_SIZE * player.INVENTORY_PAGE_COUNT): + if player.REFINE_OK != player.CanRefine(scrollIndex, slot): + continue + + targetIndex = player.GetItemIndex(slot) + if targetIndex == 0: + continue + + item.SelectItem(targetIndex) + if item.GetItemType() != item.ITEM_TYPE_METIN: + continue + + self.eligibleSlots.append(slot) + + def __GetSlotLabel(self, slot): + itemVnum = player.GetItemIndex(slot) + if itemVnum == 0: + return "Slot %d" % slot + + item.SelectItem(itemVnum) + return "%d:+%d" % (slot, player.GetItemGrade(slot)) + + def __RefreshCandidates(self): + start = self.pageIndex * self.PAGE_SIZE + end = start + self.PAGE_SIZE + pageSlots = self.eligibleSlots[start:end] + + totalPages = max(1, (len(self.eligibleSlots) + self.PAGE_SIZE - 1) // self.PAGE_SIZE) + self.pageLine.SetText("Page %d / %d" % (self.pageIndex + 1, totalPages)) + + for index, button in enumerate(self.candidateButtons): + if index < len(pageSlots): + slot = pageSlots[index] + prefix = "[x]" if slot in self.selectedSlots else "[ ]" + button.SetText("%s %s" % (prefix, self.__GetSlotLabel(slot))) + button.Enable() + button.SetEvent(self.__ToggleSlot, slot) + else: + button.SetText("-") + button.Disable() + + self.prevButton.Enable() if self.pageIndex > 0 else self.prevButton.Disable() + self.nextButton.Enable() if end < len(self.eligibleSlots) else self.nextButton.Disable() + + def __RefreshQueueLines(self): + for index, line in enumerate(self.queueLines): + if index < len(self.selectedSlots): + line.SetText("Queue %d: %s" % (index + 1, self.__GetSlotLabel(self.selectedSlots[index]))) + else: + line.SetText("Queue %d: -" % (index + 1)) + + def __ToggleSlot(self, slot): + if STATE_ACTIVE: + return + + if slot in self.selectedSlots: + self.selectedSlots.remove(slot) + elif len(self.selectedSlots) < STATE_MAX: + self.selectedSlots.append(slot) + + self.Refresh() + + def __ChangePage(self, delta): + totalPages = max(1, (len(self.eligibleSlots) + self.PAGE_SIZE - 1) // self.PAGE_SIZE) + self.pageIndex = max(0, min(totalPages - 1, self.pageIndex + delta)) + self.__RefreshCandidates() + + def __StartQueue(self): + if STATE_ACTIVE or self.scrollSlotPos < 0 or not self.selectedSlots: + return + + command = "/stone_queue start %d %s" % ( + self.scrollSlotPos, + " ".join([str(slot) for slot in self.selectedSlots[:STATE_MAX]]), + ) + net.SendChatPacket(command, 0) + + def __CancelQueue(self): + net.SendChatPacket("/stone_queue cancel", 0) + + def Open(self, scrollSlotPos, targetSlotPos): + self.scrollSlotPos = scrollSlotPos + self.pageIndex = 0 + self.selectedSlots = [] + + self.__BuildEligibleSlots() + if targetSlotPos in self.eligibleSlots: + self.selectedSlots.append(targetSlotPos) + + net.SendChatPacket("/stone_queue sync", 0) + self.Refresh() + self.SetTop() + self.Show() + + def Refresh(self): + self.scrollLine.SetText("Scroll slot: %d" % self.scrollSlotPos) + self.statusLine.SetText("Status: %s" % ("Running" if STATE_ACTIVE else "Ready")) + self.progressLine.SetText("Progress: %d / %d" % (STATE_CURRENT, len(self.selectedSlots))) + self.resultLine.SetText("Results: %d success / %d fail / max %d" % (STATE_SUCCESS, STATE_FAIL, STATE_MAX)) + self.__RefreshCandidates() + self.__RefreshQueueLines() + + if STATE_ACTIVE: + self.startButton.Disable() + self.cancelButton.Enable() + else: + self.startButton.Enable() + self.cancelButton.Disable() diff --git a/assets/root/uiinventory.py b/assets/root/uiinventory.py index deb20a39..6686922d 100644 --- a/assets/root/uiinventory.py +++ b/assets/root/uiinventory.py @@ -11,6 +11,7 @@ import grp import uiScriptLocale import uiRefine import uiAttachMetin +import uiStoneQueue import uiPickMoney import uiCommon import uiPrivateShopBuilder # Prevent ItemMove while private shop is open @@ -357,6 +358,10 @@ class InventoryWindow(ui.ScriptWindow): self.attachMetinDialog = uiAttachMetin.AttachMetinDialog() self.attachMetinDialog.Hide() + ## StoneQueueDialog + self.stoneQueueDialog = uiStoneQueue.StoneQueueWindow() + self.stoneQueueDialog.Hide() + ## MoneySlot self.wndMoneySlot.SetEvent(ui.__mem_func__(self.OpenPickMoneyDialog)) @@ -407,6 +412,9 @@ class InventoryWindow(ui.ScriptWindow): self.attachMetinDialog.Destroy() self.attachMetinDialog = 0 + self.stoneQueueDialog.Destroy() + self.stoneQueueDialog = 0 + self.tooltipItem = None self.wndItem = 0 self.wndEquip = 0 @@ -841,20 +849,6 @@ class InventoryWindow(ui.ScriptWindow): scrollIndex = player.GetItemIndex(scrollSlotPos) targetIndex = player.GetItemIndex(targetSlotPos) - if player.REFINE_OK != player.CanRefine(scrollIndex, targetSlotPos): - return - - ########################################################### - self.__SendUseItemToItemPacket(scrollSlotPos, targetSlotPos) - #net.SendItemUseToItemPacket(scrollSlotPos, targetSlotPos) - return - ########################################################### - - ########################################################### - #net.SendRequestRefineInfoPacket(targetSlotPos) - #return - ########################################################### - result = player.CanRefine(scrollIndex, targetSlotPos) if player.REFINE_ALREADY_MAX_SOCKET_COUNT == result: @@ -879,7 +873,12 @@ class InventoryWindow(ui.ScriptWindow): if player.REFINE_OK != result: return - self.refineDialog.Open(scrollSlotPos, targetSlotPos) + item.SelectItem(targetIndex) + if item.GetItemType() == item.ITEM_TYPE_METIN: + self.stoneQueueDialog.Open(scrollSlotPos, targetSlotPos) + return + + self.__SendUseItemToItemPacket(scrollSlotPos, targetSlotPos) def DetachMetinFromItem(self, scrollSlotPos, targetSlotPos): scrollIndex = player.GetItemIndex(scrollSlotPos)