5 Commits

Author SHA1 Message Date
server
12df5a2bd6 issue-9: add sash inventory integration 2026-04-16 21:08:13 +02:00
server
09efcadbdd issue-8: add switchbot ui 2026-04-16 20:38:12 +02:00
server
ecc99a8683 issue-7: add stone queue ui 2026-04-16 20:02:14 +02:00
server
7871288b6d issue-6: add autopickup settings ui 2026-04-16 19:28:16 +02:00
server
4ef859e26f issue-5: add teleport hud 2026-04-16 18:33:07 +02:00
14 changed files with 1304 additions and 26 deletions

View File

@@ -33,6 +33,9 @@ import uiAffectShower
import uiPlayerGauge
import uiCharacter
import uiTarget
import uiAutopickup
import uiStoneQueue
import uiSwitchbot
# PRIVATE_SHOP_PRICE_LIST
import uiPrivateShopBuilder
@@ -2177,6 +2180,10 @@ class GameWindow(ui.ScriptWindow):
"PartyRequestDenied" : self.__PartyRequestDenied,
"horse_state" : self.__Horse_UpdateState,
"hide_horse_state" : self.__Horse_HideState,
"AutoPickupState" : self.__AutoPickupState,
"StoneQueueState" : self.__StoneQueueState,
"SwitchbotState" : self.__SwitchbotState,
"SwitchbotSlot" : self.__SwitchbotSlot,
"WarUC" : self.__GuildWar_UpdateMemberCount,
"test_server" : self.__EnableTestServerFlag,
"mall" : self.__InGameShop_Show,
@@ -2224,6 +2231,18 @@ class GameWindow(ui.ScriptWindow):
def PartyHealReady(self):
self.interface.PartyHealReady()
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 __SwitchbotState(self, speedIndex, activeCount, scrollCount, etaSeconds):
uiSwitchbot.SetSwitchbotState(int(speedIndex), int(activeCount), int(scrollCount), int(etaSeconds))
def __SwitchbotSlot(self, slotIndex, active, itemCell, attrType, minValue, attempts):
uiSwitchbot.SetSwitchbotSlotState(int(slotIndex), int(active), int(itemCell), int(attrType), int(minValue), int(attempts))
def AskSafeboxPassword(self):
self.interface.AskSafeboxPassword()

View File

@@ -26,6 +26,8 @@ import uiRestart
import uiToolTip
import uiMiniMap
import uiBiolog
import uiTeleport
import uiSwitchbot
import uiParty
import uiSafebox
import uiGuild
@@ -77,6 +79,8 @@ class Interface(object):
self.wndMessenger = None
self.wndMiniMap = None
self.wndBiolog = None
self.wndTeleport = None
self.wndSwitchbot = None
self.wndGuild = None
self.wndGuildBuilding = None
@@ -183,6 +187,8 @@ class Interface(object):
wndMiniMap = uiMiniMap.MiniMap()
wndBiolog = uiBiolog.BiologWindow()
wndTeleport = uiTeleport.TeleportWindow()
wndSwitchbot = uiSwitchbot.SwitchbotWindow()
wndSafebox = uiSafebox.SafeboxWindow()
# ITEM_MALL
@@ -199,9 +205,13 @@ class Interface(object):
self.wndDragonSoulRefine = wndDragonSoulRefine
self.wndMiniMap = wndMiniMap
self.wndBiolog = wndBiolog
self.wndTeleport = wndTeleport
self.wndSwitchbot = wndSwitchbot
self.wndSafebox = wndSafebox
self.wndChatLog = wndChatLog
self.wndMiniMap.SetBiologButtonEvent(ui.__mem_func__(self.ToggleBiologWindow))
self.wndMiniMap.SetTeleportButtonEvent(ui.__mem_func__(self.ToggleTeleportWindow))
self.wndMiniMap.SetSwitchbotButtonEvent(ui.__mem_func__(self.ToggleSwitchbotWindow))
if app.ENABLE_DRAGON_SOUL_SYSTEM:
self.wndDragonSoul.SetDragonSoulRefineWindow(self.wndDragonSoulRefine)
@@ -416,6 +426,8 @@ class Interface(object):
if self.wndBiolog:
self.wndBiolog.Hide()
if self.wndSwitchbot:
self.wndSwitchbot.Hide()
if self.wndSafebox:
self.wndSafebox.Destroy()
@@ -508,6 +520,7 @@ class Interface(object):
del self.tooltipSkill
del self.wndMiniMap
del self.wndBiolog
del self.wndSwitchbot
del self.wndSafebox
del self.wndMall
del self.wndParty
@@ -963,6 +976,24 @@ class Interface(object):
else:
self.wndBiolog.Hide()
def ToggleTeleportWindow(self):
if False == self.wndTeleport.IsShow():
(miniMapX, miniMapY) = self.wndMiniMap.GetGlobalPosition()
self.wndTeleport.SetPosition(max(10, miniMapX - self.wndTeleport.GetWidth() - 10), miniMapY + 24)
self.wndTeleport.Show()
self.wndTeleport.SetTop()
else:
self.wndTeleport.Hide()
def ToggleSwitchbotWindow(self):
if False == self.wndSwitchbot.IsShow():
(miniMapX, miniMapY) = self.wndMiniMap.GetGlobalPosition()
self.wndSwitchbot.SetPosition(max(10, miniMapX - self.wndSwitchbot.GetWidth() - 10), miniMapY + 40)
self.wndSwitchbot.Show()
self.wndSwitchbot.SetTop()
else:
self.wndSwitchbot.Hide()
def ToggleCharacterWindow(self, state):
if False == player.IsObserverMode():
if False == self.wndCharacter.IsShow():

View File

@@ -659,6 +659,7 @@ def __LoadGameWarriorEx(race, path):
## Bone
chrmgr.RegisterAttachingBoneName(chr.PART_WEAPON, "equip_right_hand")
chrmgr.RegisterAttachingBoneName(chr.PART_ACCE, "Bip01 Spine2")
def __LoadGameAssassinEx(race, path):
## Assassin
@@ -872,6 +873,7 @@ def __LoadGameAssassinEx(race, path):
chrmgr.RegisterAttachingBoneName(chr.PART_WEAPON, "equip_right")
chrmgr.RegisterAttachingBoneName(chr.PART_WEAPON_LEFT, "equip_left")
chrmgr.RegisterAttachingBoneName(chr.PART_ACCE, "Bip01 Spine2")
def __LoadGameSuraEx(race, path):
## Sura
@@ -1189,6 +1191,7 @@ def __LoadGameShamanEx(race, path):
chrmgr.RegisterAttachingBoneName(chr.PART_WEAPON, "equip_right")
chrmgr.RegisterAttachingBoneName(chr.PART_WEAPON_LEFT, "equip_left")
chrmgr.RegisterAttachingBoneName(chr.PART_ACCE, "Bip01 Spine2")
def __LoadGameSkill():
@@ -1456,4 +1459,4 @@ def SetGuildBuilding(race, name, grade):
chrmgr.SetPathName("d:/ymir work/guild/building/%s/" % name)
chrmgr.LoadRaceData("%s%02d.msm" % (name, grade))
chrmgr.RegisterMotionMode(chr.MOTION_MODE_GENERAL)
#chrmgr.RegisterMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_DEAD, name + "_destruction.msa")
#chrmgr.RegisterMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_DEAD, name + "_destruction.msa")

145
assets/root/uiAutopickup.py Normal file
View File

@@ -0,0 +1,145 @@
import net
import ui
STATE_ENABLED = 0
STATE_MODE = 0
STATE_MASK = 31
STATE_VIP = 0
OPEN_WINDOWS = []
FILTERS = (
(1, "Weapons"),
(2, "Armor"),
(4, "Yang"),
(8, "Stones"),
(16, "Materials"),
)
def SetAutoPickupState(enabled, mode, mask, vip):
global STATE_ENABLED
global STATE_MODE
global STATE_MASK
global STATE_VIP
STATE_ENABLED = 1 if int(enabled) else 0
STATE_MODE = 1 if int(mode) else 0
STATE_MASK = int(mask) & 31
STATE_VIP = 1 if int(vip) else 0
for window in OPEN_WINDOWS:
try:
window.ApplyState()
except:
pass
class AutoPickupWindow(ui.BoardWithTitleBar):
def __init__(self):
ui.BoardWithTitleBar.__init__(self)
OPEN_WINDOWS.append(self)
self.filterButtons = {}
self.AddFlag("float")
self.AddFlag("movable")
self.SetSize(280, 248)
self.SetTitleName("Auto Pickup")
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.filterButtons = {}
def __CreateChildren(self):
self.statusLine = self.__CreateLine(15, 36)
self.rangeLine = self.__CreateLine(15, 56)
self.modeLine = self.__CreateLine(15, 76)
self.noteLine = self.__CreateLine(15, 96)
self.enableButton = self.__CreateButton(170, 34, 90, "Enable")
self.enableButton.SetEvent(self.__ToggleEnabled)
self.whitelistButton = self.__CreateButton(15, 118, 118, "Whitelist")
self.whitelistButton.SetEvent(self.__SetMode, 0)
self.blacklistButton = self.__CreateButton(142, 118, 118, "Blacklist")
self.blacklistButton.SetEvent(self.__SetMode, 1)
for index, filterData in enumerate(FILTERS):
(bit, label) = filterData
button = self.__CreateButton(15, 150 + index * 18, 245, label)
button.SetEvent(self.__ToggleFilter, bit)
self.filterButtons[bit] = button
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 __Send(self, command):
net.SendChatPacket(command, 0)
def __ToggleEnabled(self):
SetAutoPickupState(0 if STATE_ENABLED else 1, STATE_MODE, STATE_MASK, STATE_VIP)
self.__Send("/autopickup enable %d" % STATE_ENABLED)
def __SetMode(self, mode):
SetAutoPickupState(STATE_ENABLED, mode, STATE_MASK, STATE_VIP)
self.__Send("/autopickup mode %s" % ("blacklist" if mode else "whitelist"))
def __ToggleFilter(self, bit):
mask = STATE_MASK ^ bit
SetAutoPickupState(STATE_ENABLED, STATE_MODE, mask, STATE_VIP)
self.__Send("/autopickup mask %d" % STATE_MASK)
def ApplyState(self):
self.statusLine.SetText("Status: %s" % ("Enabled" if STATE_ENABLED else "Disabled"))
self.rangeLine.SetText("Range: %s" % ("VIP 300 / Free 220" if STATE_VIP else "Free 220"))
self.modeLine.SetText("Mode: %s" % ("Blacklist" if STATE_MODE else "Whitelist"))
self.noteLine.SetText("Only nearby owned drops are valid")
self.enableButton.SetText("Disable" if STATE_ENABLED else "Enable")
if STATE_MODE == 0:
self.whitelistButton.Down()
self.blacklistButton.SetUp()
else:
self.whitelistButton.SetUp()
self.blacklistButton.Down()
for (bit, label) in FILTERS:
prefix = "[x]" if (STATE_MASK & bit) else "[ ]"
self.filterButtons[bit].SetText("%s %s" % (prefix, label))
def Show(self):
self.__Send("/autopickup sync")
self.ApplyState()
ui.BoardWithTitleBar.Show(self)

233
assets/root/uiStoneQueue.py Normal file
View File

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

455
assets/root/uiSwitchbot.py Normal file
View File

@@ -0,0 +1,455 @@
import item
import net
import player
import ui
import uitooltip
STATE_SPEED = 1
STATE_ACTIVE_COUNT = 0
STATE_SCROLL_COUNT = 0
STATE_ETA_SECONDS = 0
STATE_SLOTS = []
OPEN_WINDOWS = []
_AFFECT_HELPER = None
for _slotIndex in range(5):
STATE_SLOTS.append({
"active": 0,
"itemCell": 0,
"attrType": 0,
"minValue": 0,
"attempts": 0,
})
def _GetAffectHelper():
global _AFFECT_HELPER
if _AFFECT_HELPER is None:
_AFFECT_HELPER = uitooltip.ItemToolTip()
return _AFFECT_HELPER
def _GetAffectLabel(attrType):
if attrType <= 0:
return "-"
try:
label = _GetAffectHelper()._ItemToolTip__GetAffectString(attrType, 1)
except:
label = None
if not label:
return "Attr %d" % attrType
return label
ATTR_OPTIONS = (
(item.APPLY_MAX_HP, _GetAffectLabel(item.APPLY_MAX_HP)),
(item.APPLY_MAX_SP, _GetAffectLabel(item.APPLY_MAX_SP)),
(item.APPLY_STR, _GetAffectLabel(item.APPLY_STR)),
(item.APPLY_DEX, _GetAffectLabel(item.APPLY_DEX)),
(item.APPLY_CON, _GetAffectLabel(item.APPLY_CON)),
(item.APPLY_INT, _GetAffectLabel(item.APPLY_INT)),
(item.APPLY_ATT_SPEED, _GetAffectLabel(item.APPLY_ATT_SPEED)),
(item.APPLY_MOV_SPEED, _GetAffectLabel(item.APPLY_MOV_SPEED)),
(item.APPLY_CAST_SPEED, _GetAffectLabel(item.APPLY_CAST_SPEED)),
(item.APPLY_CRITICAL_PCT, _GetAffectLabel(item.APPLY_CRITICAL_PCT)),
(item.APPLY_PENETRATE_PCT, _GetAffectLabel(item.APPLY_PENETRATE_PCT)),
(item.APPLY_ATTBONUS_MONSTER, _GetAffectLabel(item.APPLY_ATTBONUS_MONSTER)),
(item.APPLY_ATTBONUS_DEVIL, _GetAffectLabel(item.APPLY_ATTBONUS_DEVIL)),
(item.APPLY_ATTBONUS_HUMAN, _GetAffectLabel(item.APPLY_ATTBONUS_HUMAN)),
(item.APPLY_STEAL_HP, _GetAffectLabel(item.APPLY_STEAL_HP)),
(item.APPLY_STEAL_SP, _GetAffectLabel(item.APPLY_STEAL_SP)),
(item.APPLY_BLOCK, _GetAffectLabel(item.APPLY_BLOCK)),
(item.APPLY_DODGE, _GetAffectLabel(item.APPLY_DODGE)),
(item.APPLY_ATT_GRADE_BONUS, _GetAffectLabel(item.APPLY_ATT_GRADE_BONUS)),
(item.APPLY_DEF_GRADE_BONUS, _GetAffectLabel(item.APPLY_DEF_GRADE_BONUS)),
(item.APPLY_RESIST_SWORD, _GetAffectLabel(item.APPLY_RESIST_SWORD)),
(item.APPLY_RESIST_TWOHAND, _GetAffectLabel(item.APPLY_RESIST_TWOHAND)),
(item.APPLY_RESIST_DAGGER, _GetAffectLabel(item.APPLY_RESIST_DAGGER)),
(item.APPLY_RESIST_BOW, _GetAffectLabel(item.APPLY_RESIST_BOW)),
(item.APPLY_RESIST_FIRE, _GetAffectLabel(item.APPLY_RESIST_FIRE)),
(item.APPLY_RESIST_ELEC, _GetAffectLabel(item.APPLY_RESIST_ELEC)),
(item.APPLY_RESIST_MAGIC, _GetAffectLabel(item.APPLY_RESIST_MAGIC)),
(item.APPLY_RESIST_WIND, _GetAffectLabel(item.APPLY_RESIST_WIND)),
(item.APPLY_RESIST_ICE, _GetAffectLabel(item.APPLY_RESIST_ICE)),
(item.APPLY_RESIST_EARTH, _GetAffectLabel(item.APPLY_RESIST_EARTH)),
(item.APPLY_RESIST_DARK, _GetAffectLabel(item.APPLY_RESIST_DARK)),
)
SPEED_OPTIONS = (
(0, "Slow / 3s"),
(1, "Normal / 2s"),
(2, "Fast / 1s"),
)
def SetSwitchbotState(speedIndex, activeCount, scrollCount, etaSeconds):
global STATE_SPEED
global STATE_ACTIVE_COUNT
global STATE_SCROLL_COUNT
global STATE_ETA_SECONDS
STATE_SPEED = int(speedIndex)
STATE_ACTIVE_COUNT = max(0, int(activeCount))
STATE_SCROLL_COUNT = max(0, int(scrollCount))
STATE_ETA_SECONDS = max(0, int(etaSeconds))
for window in OPEN_WINDOWS:
try:
window.Refresh()
except:
pass
def SetSwitchbotSlotState(slotIndex, active, itemCell, attrType, minValue, attempts):
slotIndex = int(slotIndex)
if slotIndex < 0 or slotIndex >= len(STATE_SLOTS):
return
STATE_SLOTS[slotIndex]["active"] = 1 if int(active) else 0
STATE_SLOTS[slotIndex]["itemCell"] = int(itemCell)
STATE_SLOTS[slotIndex]["attrType"] = int(attrType)
STATE_SLOTS[slotIndex]["minValue"] = int(minValue)
STATE_SLOTS[slotIndex]["attempts"] = int(attempts)
for window in OPEN_WINDOWS:
try:
window.Refresh()
except:
pass
class SwitchbotWindow(ui.BoardWithTitleBar):
CANDIDATE_PAGE_SIZE = 12
def __init__(self):
ui.BoardWithTitleBar.__init__(self)
OPEN_WINDOWS.append(self)
self.selectedSlotIndex = 0
self.pageIndex = 0
self.candidateSlots = []
self.slotWidgets = []
self.candidateButtons = []
self.speedLabels = {}
self.attrLabels = {}
self.AddFlag("float")
self.AddFlag("movable")
self.SetSize(535, 406)
self.SetTitleName("Switchbot")
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.slotWidgets = []
self.candidateButtons = []
self.candidateSlots = []
self.speedLabels = {}
self.attrLabels = {}
def __CreateChildren(self):
self.statusLine = self.__CreateLine(15, 36)
self.scrollLine = self.__CreateLine(15, 56)
self.etaLine = self.__CreateLine(15, 76)
self.helpLine = self.__CreateLine(15, 96)
self.speedCombo = ui.ComboBox()
self.speedCombo.SetParent(self)
self.speedCombo.SetPosition(398, 34)
self.speedCombo.SetSize(120, 18)
self.speedCombo.SetEvent(self.__OnChangeSpeed)
self.speedCombo.Show()
for (speedIndex, label) in SPEED_OPTIONS:
self.speedCombo.InsertItem(speedIndex, label)
self.speedLabels[speedIndex] = label
for slotIndex in range(5):
baseY = 126 + slotIndex * 38
row = {}
row["selectButton"] = self.__CreateButton(15, baseY, 48, "Slot %d" % (slotIndex + 1))
row["selectButton"].SetEvent(self.__SelectSlot, slotIndex)
row["itemLine"] = self.__CreateLine(72, baseY + 2)
row["statusLine"] = self.__CreateLine(72, baseY + 18)
row["attrCombo"] = ui.ComboBox()
row["attrCombo"].SetParent(self)
row["attrCombo"].SetPosition(220, baseY)
row["attrCombo"].SetSize(165, 18)
row["attrCombo"].SetEvent(lambda attrType, line=slotIndex: self.__SetAttrType(line, attrType))
row["attrCombo"].Show()
for (attrType, label) in ATTR_OPTIONS:
row["attrCombo"].InsertItem(attrType, label)
attrBar = ui.SlotBar()
attrBar.SetParent(self)
attrBar.SetPosition(392, baseY)
attrBar.SetSize(48, 18)
attrBar.Show()
row["valueBar"] = attrBar
row["valueEdit"] = ui.EditLine()
row["valueEdit"].SetParent(attrBar)
row["valueEdit"].SetPosition(3, 3)
row["valueEdit"].SetSize(42, 12)
row["valueEdit"].SetMax(5)
row["valueEdit"].SetNumberMode()
row["valueEdit"].Show()
row["startButton"] = self.__CreateButton(447, baseY, 40, "Start")
row["startButton"].SetEvent(self.__ToggleSlot, slotIndex)
row["clearButton"] = self.__CreateButton(492, baseY, 28, "X")
row["clearButton"].SetEvent(self.__ClearSlot, slotIndex)
self.slotWidgets.append(row)
self.prevButton = self.__CreateButton(15, 330, 44, "Prev")
self.prevButton.SetEvent(self.__ChangePage, -1)
self.pageLine = self.__CreateLine(80, 334)
self.nextButton = self.__CreateButton(170, 330, 44, "Next")
self.nextButton.SetEvent(self.__ChangePage, 1)
for index in range(self.CANDIDATE_PAGE_SIZE):
column = index % 2
row = index // 2
button = self.__CreateButton(15 + column * 155, 356 + row * 18, 148, "-")
button.SetEvent(self.__AssignCandidate, index)
self.candidateButtons.append(button)
self.syncButton = self.__CreateButton(305, 330, 54, "Sync")
self.syncButton.SetEvent(self.__Sync)
self.startAllButton = self.__CreateButton(366, 330, 74, "Start All")
self.startAllButton.SetEvent(self.__StartAll)
self.stopAllButton = self.__CreateButton(446, 330, 74, "Stop All")
self.stopAllButton.SetEvent(self.__StopAll)
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 __Send(self, command):
net.SendChatPacket(command, 0)
def __IsEligibleItem(self, slotPos):
itemVnum = player.GetItemIndex(slotPos)
if itemVnum == 0:
return False
item.SelectItem(itemVnum)
if item.GetItemType() == item.ITEM_TYPE_COSTUME:
return False
if item.GetItemType() not in (item.ITEM_TYPE_WEAPON, item.ITEM_TYPE_ARMOR):
return False
for attrIndex in range(player.ATTRIBUTE_SLOT_MAX_NUM):
if player.GetItemAttribute(slotPos, attrIndex)[0] != 0:
return True
return False
def __GetItemLabel(self, slotPos):
itemVnum = player.GetItemIndex(slotPos)
if itemVnum == 0:
return "Slot %d" % slotPos
item.SelectItem(itemVnum)
return "%d: %s" % (slotPos, item.GetItemName())
def __BuildCandidateSlots(self):
self.candidateSlots = []
for slotPos in range(player.INVENTORY_PAGE_SIZE * player.INVENTORY_PAGE_COUNT):
if self.__IsEligibleItem(slotPos):
self.candidateSlots.append(slotPos)
def __FormatEta(self):
if STATE_ETA_SECONDS <= 0:
return "ETA: -"
minutes = STATE_ETA_SECONDS // 60
seconds = STATE_ETA_SECONDS % 60
return "ETA: %02d:%02d" % (minutes, seconds)
def __GetAttrType(self, slotIndex):
return STATE_SLOTS[slotIndex]["attrType"]
def __GetMinValue(self, slotIndex):
text = self.slotWidgets[slotIndex]["valueEdit"].GetText()
if not text:
return STATE_SLOTS[slotIndex]["minValue"]
return int(text)
def __SelectSlot(self, slotIndex):
self.selectedSlotIndex = slotIndex
self.Refresh()
def __SetAttrType(self, slotIndex, attrType):
SetSwitchbotSlotState(
slotIndex,
STATE_SLOTS[slotIndex]["active"],
STATE_SLOTS[slotIndex]["itemCell"],
attrType,
STATE_SLOTS[slotIndex]["minValue"],
STATE_SLOTS[slotIndex]["attempts"],
)
def __AssignCandidate(self, localIndex):
candidateIndex = self.pageIndex * self.CANDIDATE_PAGE_SIZE + localIndex
if candidateIndex < 0 or candidateIndex >= len(self.candidateSlots):
return
slotIndex = self.selectedSlotIndex
SetSwitchbotSlotState(
slotIndex,
0,
self.candidateSlots[candidateIndex],
STATE_SLOTS[slotIndex]["attrType"],
STATE_SLOTS[slotIndex]["minValue"],
0,
)
def __ToggleSlot(self, slotIndex):
slotState = STATE_SLOTS[slotIndex]
if slotState["active"]:
self.__Send("/switchbot stop %d" % slotIndex)
return
itemCell = slotState["itemCell"]
attrType = self.__GetAttrType(slotIndex)
minValue = self.__GetMinValue(slotIndex)
if not self.__IsEligibleItem(itemCell) or attrType <= 0 or minValue <= 0:
return
SetSwitchbotSlotState(slotIndex, 0, itemCell, attrType, minValue, slotState["attempts"])
self.__Send("/switchbot start %d %d %d %d" % (slotIndex, itemCell, attrType, minValue))
def __ClearSlot(self, slotIndex):
self.__Send("/switchbot clear %d" % slotIndex)
def __ChangePage(self, delta):
totalPages = max(1, (len(self.candidateSlots) + self.CANDIDATE_PAGE_SIZE - 1) // self.CANDIDATE_PAGE_SIZE)
self.pageIndex = max(0, min(totalPages - 1, self.pageIndex + delta))
self.Refresh()
def __OnChangeSpeed(self, speedIndex):
self.__Send("/switchbot speed %d" % int(speedIndex))
def __Sync(self):
self.__Send("/switchbot sync")
def __StartAll(self):
for slotIndex in range(len(STATE_SLOTS)):
slotState = STATE_SLOTS[slotIndex]
if slotState["active"]:
continue
itemCell = slotState["itemCell"]
attrType = self.__GetAttrType(slotIndex)
minValue = self.__GetMinValue(slotIndex)
if not self.__IsEligibleItem(itemCell) or attrType <= 0 or minValue <= 0:
continue
self.__Send("/switchbot start %d %d %d %d" % (slotIndex, itemCell, attrType, minValue))
def __StopAll(self):
self.__Send("/switchbot stop_all")
def Refresh(self):
self.__BuildCandidateSlots()
self.statusLine.SetText("Status: %d active slot(s)" % STATE_ACTIVE_COUNT)
self.scrollLine.SetText("Switch items: %d" % STATE_SCROLL_COUNT)
self.etaLine.SetText(self.__FormatEta())
self.helpLine.SetText("Select a row, assign an item, pick a target bonus and min value")
self.speedCombo.SetCurrentItem(self.speedLabels.get(STATE_SPEED, SPEED_OPTIONS[1][1]))
for slotIndex in range(len(self.slotWidgets)):
slotState = STATE_SLOTS[slotIndex]
row = self.slotWidgets[slotIndex]
row["selectButton"].SetText(("> " if self.selectedSlotIndex == slotIndex else "") + "S%d" % (slotIndex + 1))
row["itemLine"].SetText("Item: %s" % ("-" if not self.__IsEligibleItem(slotState["itemCell"]) else self.__GetItemLabel(slotState["itemCell"])))
row["statusLine"].SetText("Target: %s / tries %d / %s" % (
_GetAffectLabel(slotState["attrType"]),
slotState["attempts"],
"Running" if slotState["active"] else "Ready",
))
if slotState["attrType"] > 0:
row["attrCombo"].SetCurrentItem(_GetAffectLabel(slotState["attrType"]))
else:
row["attrCombo"].SetCurrentItem("-")
if slotState["minValue"] > 0 and row["valueEdit"].GetText() != str(slotState["minValue"]):
row["valueEdit"].SetText(str(slotState["minValue"]))
elif slotState["minValue"] <= 0 and row["valueEdit"].GetText():
row["valueEdit"].SetText("")
row["startButton"].SetText("Stop" if slotState["active"] else "Start")
start = self.pageIndex * self.CANDIDATE_PAGE_SIZE
end = start + self.CANDIDATE_PAGE_SIZE
pageSlots = self.candidateSlots[start:end]
totalPages = max(1, (len(self.candidateSlots) + self.CANDIDATE_PAGE_SIZE - 1) // self.CANDIDATE_PAGE_SIZE)
self.pageLine.SetText("Candidates %d / %d" % (self.pageIndex + 1, totalPages))
for localIndex in range(len(self.candidateButtons)):
button = self.candidateButtons[localIndex]
if localIndex < len(pageSlots):
button.SetText(self.__GetItemLabel(pageSlots[localIndex]))
button.Enable()
else:
button.SetText("-")
button.Disable()
if self.pageIndex > 0:
self.prevButton.Enable()
else:
self.prevButton.Disable()
if end < len(self.candidateSlots):
self.nextButton.Enable()
else:
self.nextButton.Disable()
def Show(self):
self.__Sync()
self.Refresh()
ui.BoardWithTitleBar.Show(self)

173
assets/root/uiTeleport.py Normal file
View File

@@ -0,0 +1,173 @@
import time
import background
import net
import player
import quest
import ui
class TeleportWindow(ui.BoardWithTitleBar):
TITLE = "Teleport System"
PRESET_BUTTONS = (
(1, "Village 1"),
(2, "Village 2"),
(3, "Valley"),
(4, "Desert"),
(5, "Sohan"),
(6, "Fireland"),
(7, "Devil"),
(8, "Cave"),
)
def __init__(self):
ui.BoardWithTitleBar.__init__(self)
self.lastRefreshTime = 0.0
self.slotRows = []
self.AddFlag("float")
self.AddFlag("movable")
self.SetSize(310, 255)
self.SetTitleName("Teleport")
self.SetCloseEvent(self.Hide)
self.__CreateChildren()
self.Hide()
def __del__(self):
ui.BoardWithTitleBar.__del__(self)
def __CreateChildren(self):
self.statusLine = self.__CreateValueLine(15, 36)
self.mapLine = self.__CreateValueLine(15, 56)
self.coordLine = self.__CreateValueLine(15, 76)
self.slotSummaryLine = self.__CreateValueLine(15, 96)
self.cooldownLine = self.__CreateValueLine(15, 116)
for index, presetData in enumerate(self.PRESET_BUTTONS):
(presetId, label) = presetData
row = index // 4
column = index % 4
button = self.__CreateButton(15 + column * 71, 142 + row * 24, 64, label)
button.SetEvent(self.__SendPresetWarp, presetId)
for slot in range(1, 6):
label = self.__CreateValueLine(15, 196 + (slot - 1) * 11)
saveButton = self.__CreateButton(100, 192 + (slot - 1) * 11, 42, "Save")
saveButton.SetEvent(self.__SendSaveSlot, slot)
useButton = self.__CreateButton(148, 192 + (slot - 1) * 11, 42, "Use")
useButton.SetEvent(self.__SendUseSlot, slot)
self.slotRows.append((label, saveButton, useButton))
def __CreateValueLine(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 __GetTeleportQuestData(self):
questCount = min(quest.GetQuestCount(), quest.QUEST_MAX_NUM)
for questIndex in range(questCount):
(questName, questIcon, questCounterName, questCounterValue) = quest.GetQuestData(questIndex)
if questName != self.TITLE:
continue
maxSlots = 3
if "/" in questCounterName:
parts = questCounterName.split("/")
try:
maxSlots = int(parts[-1].strip())
except:
maxSlots = 3
(clockName, clockValue) = quest.GetQuestLastTime(questIndex)
return {
"savedCount" : max(questCounterValue, 0),
"maxSlots" : max(maxSlots, 3),
"clockName" : clockName,
"clockValue" : max(clockValue, 0),
}
return None
def __FormatCooldown(self, seconds):
return "%02d:%02d" % (seconds // 60, seconds % 60)
def __RefreshSlotRows(self, maxSlots):
for slot, row in enumerate(self.slotRows, 1):
(label, saveButton, useButton) = row
if slot <= maxSlots:
label.SetText("Slot %d" % slot)
saveButton.Enable()
useButton.Enable()
else:
label.SetText("Slot %d (VIP)" % slot)
saveButton.Disable()
useButton.Disable()
def Refresh(self):
teleportData = self.__GetTeleportQuestData()
(x, y, z) = player.GetMainCharacterPosition()
currentMap = background.GetCurrentMapName()
self.mapLine.SetText("Map: %s" % currentMap)
self.coordLine.SetText("Coords: %d, %d" % (x // 100, y // 100))
if not teleportData:
self.statusLine.SetText("Status: Waiting for teleport quest")
self.slotSummaryLine.SetText("Saved: -")
self.cooldownLine.SetText("Cooldown: -")
self.__RefreshSlotRows(3)
return
self.statusLine.SetText("Status: %s" % ("Cooldown" if teleportData["clockValue"] > 0 else "Ready"))
self.slotSummaryLine.SetText("Saved: %d / %d" % (teleportData["savedCount"], teleportData["maxSlots"]))
if teleportData["clockValue"] > 0 and len(teleportData["clockName"]) > 0:
self.cooldownLine.SetText("Cooldown: %s" % self.__FormatCooldown(teleportData["clockValue"]))
else:
self.cooldownLine.SetText("Cooldown: Ready")
self.__RefreshSlotRows(teleportData["maxSlots"])
def Show(self):
self.Refresh()
ui.BoardWithTitleBar.Show(self)
def OnUpdate(self):
currentTime = time.time()
if currentTime - self.lastRefreshTime < 0.2:
return
self.lastRefreshTime = currentTime
self.Refresh()
def __SendTeleportCommand(self, action, arg):
net.SendChatPacket("/teleport_system %s %d" % (action, arg), 0)
self.lastRefreshTime = 0.0
self.Refresh()
def __SendSaveSlot(self, slot):
self.__SendTeleportCommand("save", slot)
def __SendUseSlot(self, slot):
self.__SendTeleportCommand("saved", slot)
def __SendPresetWarp(self, presetId):
self.__SendTeleportCommand("preset", presetId)

View File

@@ -8,6 +8,7 @@ import localeInfo
import constInfo
import chrmgr
import player
import uiAutopickup
import uiPrivateShopBuilder # 占쏙옙占쏙옙호
import interfaceModule # 占쏙옙占쏙옙호
@@ -39,8 +40,14 @@ class OptionDialog(ui.ScriptWindow):
self.alwaysShowNameButtonList = []
self.showDamageButtonList = []
self.showsalesTextButtonList = []
self.autoPickupButton = None
self.autoPickupDialog = None
def Destroy(self):
if self.autoPickupDialog:
self.autoPickupDialog.Destroy()
self.autoPickupDialog = None
self.ClearDictionary()
self.__Initialize()
@@ -80,6 +87,7 @@ class OptionDialog(ui.ScriptWindow):
self.showDamageButtonList.append(GetObject("show_damage_off_button"))
self.showsalesTextButtonList.append(GetObject("salestext_on_button"))
self.showsalesTextButtonList.append(GetObject("salestext_off_button"))
self.autoPickupButton = GetObject("autopickup_button")
except:
import exception
@@ -130,6 +138,7 @@ class OptionDialog(ui.ScriptWindow):
self.showsalesTextButtonList[0].SAFE_SetEvent(self.__OnClickSalesTextOnButton)
self.showsalesTextButtonList[1].SAFE_SetEvent(self.__OnClickSalesTextOffButton)
self.autoPickupButton.SAFE_SetEvent(self.__OnClickAutoPickupButton)
self.__ClickRadioButton(self.nameColorModeButtonList, constInfo.GET_CHRNAME_COLOR_INDEX())
self.__ClickRadioButton(self.viewTargetBoardButtonList, constInfo.GET_VIEW_OTHER_EMPIRE_PLAYER_TARGET_BOARD())
@@ -241,6 +250,15 @@ class OptionDialog(ui.ScriptWindow):
def __OnClickSalesTextOffButton(self):
systemSetting.SetShowSalesTextFlag(False)
self.RefreshShowSalesText()
def __OnClickAutoPickupButton(self):
if not self.autoPickupDialog:
self.autoPickupDialog = uiAutopickup.AutoPickupWindow()
if self.autoPickupDialog.IsShow():
self.autoPickupDialog.Hide()
else:
self.autoPickupDialog.Show()
def __CheckPvPProtectedLevelPlayer(self):
if player.GetStatus(player.LEVEL)<constInfo.PVPMODE_PROTECTED_LEVEL:

View File

@@ -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
@@ -23,6 +24,12 @@ ITEM_FLAG_APPLICABLE = 1 << 14
class CostumeWindow(ui.ScriptWindow):
SLOT_ORDER = (
item.COSTUME_SLOT_BODY,
item.COSTUME_SLOT_HAIR,
item.COSTUME_SLOT_SASH,
)
def __init__(self, wndInventory):
import exception
@@ -87,8 +94,7 @@ class CostumeWindow(ui.ScriptWindow):
def RefreshCostumeSlot(self):
getItemVNum=player.GetItemIndex
for i in range(item.COSTUME_SLOT_COUNT):
slotNumber = item.COSTUME_SLOT_START + i
for slotNumber in self.SLOT_ORDER:
self.wndEquip.SetItemSlot(slotNumber, getItemVNum(slotNumber), 0)
self.wndEquip.RefreshSlot()
@@ -251,11 +257,13 @@ class InventoryWindow(ui.ScriptWindow):
isLoaded = 0
isOpenedCostumeWindowWhenClosingInventory = 0 # Whether costume window was open when closing inventory
isOpenedBeltWindowWhenClosingInventory = 0 # Whether belt inventory was open when closing inventory
sashAbsorbSlot = -1
def __init__(self):
ui.ScriptWindow.__init__(self)
self.isOpenedBeltWindowWhenClosingInventory = 0 # Whether belt inventory was open when closing inventory
self.sashAbsorbSlot = -1
self.__LoadWindow()
@@ -357,6 +365,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 +419,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
@@ -431,6 +446,7 @@ class InventoryWindow(ui.ScriptWindow):
self.equipmentTab = []
def Hide(self):
self.__AbortSashAbsorb(False)
if constInfo.GET_ITEM_QUESTION_DIALOG_STATUS():
self.OnCloseQuestionDialog()
return
@@ -455,6 +471,91 @@ class InventoryWindow(ui.ScriptWindow):
def Close(self):
self.Hide()
def __AbortSashAbsorb(self, showMessage=True):
if self.sashAbsorbSlot == -1:
return
self.sashAbsorbSlot = -1
if showMessage:
chat.AppendChat(chat.CHAT_TYPE_INFO, "Sash absorb canceled.")
def __IsSashItem(self, slotIndex):
itemVnum = player.GetItemIndex(slotIndex)
if not itemVnum:
return False
item.SelectItem(itemVnum)
return item.GetItemType() == item.ITEM_TYPE_COSTUME and item.GetItemSubType() == item.COSTUME_TYPE_SASH
def __CanAbsorbIntoSash(self, sashSlot, targetSlot):
if sashSlot == targetSlot:
return False
if player.IsEquipmentSlot(sashSlot) or player.IsEquipmentSlot(targetSlot):
return False
if player.GetItemMetinSocket(sashSlot, 0):
return False
targetVnum = player.GetItemIndex(targetSlot)
if not targetVnum:
return False
item.SelectItem(targetVnum)
itemType = item.GetItemType()
itemSubType = item.GetItemSubType()
if itemType == item.ITEM_TYPE_WEAPON:
return itemSubType != item.WEAPON_ARROW
if itemType != item.ITEM_TYPE_ARMOR:
return False
return itemSubType in (
item.ARMOR_BODY,
item.ARMOR_HEAD,
item.ARMOR_SHIELD,
item.ARMOR_WRIST,
item.ARMOR_FOOTS,
item.ARMOR_NECK,
item.ARMOR_EAR,
)
def __BeginSashAbsorb(self, sashSlot):
if player.IsEquipmentSlot(sashSlot):
chat.AppendChat(chat.CHAT_TYPE_INFO, "Unequip the sash before absorbing bonuses.")
return
if player.GetItemMetinSocket(sashSlot, 0):
chat.AppendChat(chat.CHAT_TYPE_INFO, "This sash already contains absorbed bonuses.")
return
if self.sashAbsorbSlot == sashSlot:
self.__AbortSashAbsorb()
return
self.sashAbsorbSlot = sashSlot
chat.AppendChat(chat.CHAT_TYPE_INFO, "Select a weapon or armor piece to absorb into the sash.")
def __OpenSashAbsorbQuestion(self, sashSlot, targetSlot):
targetVnum = player.GetItemIndex(targetSlot)
item.SelectItem(targetVnum)
targetName = item.GetItemName()
self.questionDialog = uiCommon.QuestionDialog()
self.questionDialog.SetText("Absorb bonuses from %s? The source item will be destroyed." % targetName)
self.questionDialog.SetAcceptEvent(ui.__mem_func__(self.__AcceptSashAbsorb))
self.questionDialog.SetCancelEvent(ui.__mem_func__(self.OnCloseQuestionDialog))
self.questionDialog.sashSlot = sashSlot
self.questionDialog.targetSlot = targetSlot
self.questionDialog.Open()
constInfo.SET_ITEM_QUESTION_DIALOG_STATUS(1)
def __AcceptSashAbsorb(self):
net.SendChatPacket("/sash absorb %d %d" % (self.questionDialog.sashSlot, self.questionDialog.targetSlot), 0)
self.__AbortSashAbsorb(False)
self.OnCloseQuestionDialog()
def SetInventoryPage(self, page):
self.inventoryPageIndex = page
self.inventoryTab[1-page].SetUp()
@@ -701,6 +802,18 @@ class InventoryWindow(ui.ScriptWindow):
itemSlotIndex = self.__InventoryLocalSlotPosToGlobalSlotPos(itemSlotIndex)
if self.sashAbsorbSlot != -1 and not mouseModule.mouseController.isAttached():
if itemSlotIndex == self.sashAbsorbSlot:
self.__AbortSashAbsorb()
return
if self.__CanAbsorbIntoSash(self.sashAbsorbSlot, itemSlotIndex):
self.__OpenSashAbsorbQuestion(self.sashAbsorbSlot, itemSlotIndex)
else:
chat.AppendChat(chat.CHAT_TYPE_INFO, "Only unequipped weapon or armor items can be absorbed.")
self.__AbortSashAbsorb(False)
return
if mouseModule.mouseController.isAttached():
attachedSlotType = mouseModule.mouseController.GetAttachedType()
attachedSlotPos = mouseModule.mouseController.GetAttachedSlotNumber()
@@ -841,20 +954,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 +978,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)
@@ -1206,6 +1310,11 @@ class InventoryWindow(ui.ScriptWindow):
def __UseItem(self, slotIndex):
ItemVNum = player.GetItemIndex(slotIndex)
item.SelectItem(ItemVNum)
if self.__IsSashItem(slotIndex):
self.__BeginSashAbsorb(slotIndex)
return
if item.IsFlag(item.ITEM_FLAG_CONFIRM_WHEN_USE):
self.questionDialog = uiCommon.QuestionDialog()
self.questionDialog.SetText(localeInfo.INVENTORY_REALLY_USE_ITEM)

View File

@@ -225,6 +225,12 @@ class MiniMap(ui.ScriptWindow):
self.tooltipBiolog = MapTextToolTip()
self.tooltipBiolog.SetText("Biolog")
self.tooltipBiolog.Show()
self.tooltipTeleport = MapTextToolTip()
self.tooltipTeleport.SetText("Teleport")
self.tooltipTeleport.Show()
self.tooltipSwitchbot = MapTextToolTip()
self.tooltipSwitchbot.SetText("Switchbot")
self.tooltipSwitchbot.Show()
self.tooltipInfo = MapTextToolTip()
self.tooltipInfo.Show()
@@ -263,7 +269,11 @@ class MiniMap(ui.ScriptWindow):
self.MiniMapShowButton = 0
self.AtlasShowButton = 0
self.BiologButton = 0
self.TeleportButton = 0
self.SwitchbotButton = 0
self.biologButtonEvent = None
self.teleportButtonEvent = None
self.switchbotButtonEvent = None
self.tooltipMiniMapOpen = 0
self.tooltipMiniMapClose = 0
@@ -271,6 +281,8 @@ class MiniMap(ui.ScriptWindow):
self.tooltipScaleDown = 0
self.tooltipAtlasOpen = 0
self.tooltipBiolog = 0
self.tooltipTeleport = 0
self.tooltipSwitchbot = 0
self.tooltipInfo = None
self.serverInfo = None
@@ -363,6 +375,28 @@ class MiniMap(ui.ScriptWindow):
self.BiologButton.SetEvent(self.biologButtonEvent)
self.BiologButton.Show()
self.TeleportButton = ui.Button()
self.TeleportButton.SetParent(self.OpenWindow)
self.TeleportButton.SetPosition(9, 132)
self.TeleportButton.SetUpVisual("d:/ymir work/ui/public/small_thin_button_01.sub")
self.TeleportButton.SetOverVisual("d:/ymir work/ui/public/small_thin_button_02.sub")
self.TeleportButton.SetDownVisual("d:/ymir work/ui/public/small_thin_button_03.sub")
self.TeleportButton.SetText("TP")
if self.teleportButtonEvent:
self.TeleportButton.SetEvent(self.teleportButtonEvent)
self.TeleportButton.Show()
self.SwitchbotButton = ui.Button()
self.SwitchbotButton.SetParent(self.OpenWindow)
self.SwitchbotButton.SetPosition(9, 153)
self.SwitchbotButton.SetUpVisual("d:/ymir work/ui/public/small_thin_button_01.sub")
self.SwitchbotButton.SetOverVisual("d:/ymir work/ui/public/small_thin_button_02.sub")
self.SwitchbotButton.SetDownVisual("d:/ymir work/ui/public/small_thin_button_03.sub")
self.SwitchbotButton.SetText("Sw")
if self.switchbotButtonEvent:
self.SwitchbotButton.SetEvent(self.switchbotButtonEvent)
self.SwitchbotButton.Show()
(ButtonPosX, ButtonPosY) = self.MiniMapShowButton.GetGlobalPosition()
self.tooltipMiniMapOpen.SetTooltipPosition(ButtonPosX, ButtonPosY)
@@ -381,6 +415,12 @@ class MiniMap(ui.ScriptWindow):
(ButtonPosX, ButtonPosY) = self.BiologButton.GetGlobalPosition()
self.tooltipBiolog.SetTooltipPosition(ButtonPosX, ButtonPosY)
(ButtonPosX, ButtonPosY) = self.TeleportButton.GetGlobalPosition()
self.tooltipTeleport.SetTooltipPosition(ButtonPosX, ButtonPosY)
(ButtonPosX, ButtonPosY) = self.SwitchbotButton.GetGlobalPosition()
self.tooltipSwitchbot.SetTooltipPosition(ButtonPosX, ButtonPosY)
self.ShowMiniMap()
def Destroy(self):
@@ -466,6 +506,16 @@ class MiniMap(ui.ScriptWindow):
else:
self.tooltipBiolog.Hide()
if True == self.TeleportButton.IsIn():
self.tooltipTeleport.Show()
else:
self.tooltipTeleport.Hide()
if True == self.SwitchbotButton.IsIn():
self.tooltipSwitchbot.Show()
else:
self.tooltipSwitchbot.Hide()
def OnRender(self):
(x, y) = self.GetGlobalPosition()
fx = float(x)
@@ -515,3 +565,13 @@ class MiniMap(ui.ScriptWindow):
self.biologButtonEvent = event
if self.BiologButton:
self.BiologButton.SetEvent(event)
def SetTeleportButtonEvent(self, event):
self.teleportButtonEvent = event
if self.TeleportButton:
self.TeleportButton.SetEvent(event)
def SetSwitchbotButtonEvent(self, event):
self.switchbotButtonEvent = event
if self.SwitchbotButton:
self.SwitchbotButton.SetEvent(event)

View File

@@ -1021,12 +1021,14 @@ class ItemToolTip(ToolTip):
isCostumeItem = 0
isCostumeHair = 0
isCostumeBody = 0
isCostumeSash = 0
if app.ENABLE_COSTUME_SYSTEM:
if item.ITEM_TYPE_COSTUME == itemType:
isCostumeItem = 1
isCostumeHair = item.COSTUME_TYPE_HAIR == itemSubType
isCostumeBody = item.COSTUME_TYPE_BODY == itemSubType
isCostumeSash = item.COSTUME_TYPE_SASH == itemSubType
#dbg.TraceError("IS_COSTUME_ITEM! body(%d) hair(%d)" % (isCostumeBody, isCostumeHair))
@@ -1124,6 +1126,15 @@ class ItemToolTip(ToolTip):
self.__AppendAttributeInformation(attrSlot)
self.AppendWearableInformation()
if isCostumeSash:
self.AppendSpace(5)
absorbPct = metinSlot[1] if metinSlot and metinSlot[1] else item.GetValue(0)
self.AppendTextLine("Absorb rate: %d%%" % absorbPct, self.NORMAL_COLOR)
if metinSlot and metinSlot[0]:
self.AppendTextLine("Absorbed item vnum: %d" % metinSlot[0], self.NORMAL_COLOR)
else:
self.AppendTextLine("Right-click the sash, then select an item to absorb.", self.CONDITION_COLOR)
bHasRealtimeFlag = 0
for i in range(item.LIMIT_MAX_NUM):

View File

@@ -1,8 +1,6 @@
import uiScriptLocale
import item
COSTUME_START_INDEX = item.COSTUME_SLOT_START
window = {
"name" : "CostumeWindow",
@@ -71,9 +69,9 @@ window = {
"height" : 145,
"slot" : (
{"index":COSTUME_START_INDEX+0, "x":61, "y":45, "width":32, "height":64},
{"index":COSTUME_START_INDEX+1, "x":61, "y": 8, "width":32, "height":32},
{"index":COSTUME_START_INDEX+2, "x":5, "y":145, "width":32, "height":32},
{"index":item.COSTUME_SLOT_BODY, "x":61, "y":45, "width":32, "height":64},
{"index":item.COSTUME_SLOT_HAIR, "x":61, "y": 8, "width":32, "height":32},
{"index":item.COSTUME_SLOT_SASH, "x":5, "y":145, "width":32, "height":32},
),
},
),

View File

@@ -69,6 +69,7 @@ window = {
##{"index":22, "x":75, "y":106, "width":32, "height":32},
## 새 벨트
{"index":23, "x":39, "y":106, "width":32, "height":32},
{"index":24, "x":2, "y":106, "width":32, "height":32},
),
},

View File

@@ -20,7 +20,7 @@ window = {
"y" : 0,
"width" : 300,
"height" : 25*11+8,
"height" : 25*12+8,
"children" :
(
@@ -32,7 +32,7 @@ window = {
"y" : 0,
"width" : 300,
"height" : 25*11+8,
"height" : 25*12+8,
"children" :
(
@@ -433,7 +433,29 @@ window = {
"default_image" : ROOT_PATH + "middle_button_01.sub",
"over_image" : ROOT_PATH + "middle_button_02.sub",
"down_image" : ROOT_PATH + "middle_button_03.sub",
},
},
{
"name" : "autopickup_label",
"type" : "text",
"x" : LINE_LABEL_X,
"y" : 265+2,
"text" : "Auto Pickup",
},
{
"name" : "autopickup_button",
"type" : "button",
"x" : LINE_DATA_X,
"y" : 265,
"text" : "Configure",
"default_image" : ROOT_PATH + "middle_button_01.sub",
"over_image" : ROOT_PATH + "middle_button_02.sub",
"down_image" : ROOT_PATH + "middle_button_03.sub",
},
),
},
),