diff --git a/assets/root/playersettingmodule.py b/assets/root/playersettingmodule.py index d01c4da5..75e00183 100644 --- a/assets/root/playersettingmodule.py +++ b/assets/root/playersettingmodule.py @@ -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") \ No newline at end of file + #chrmgr.RegisterMotionData(chr.MOTION_MODE_GENERAL, chr.MOTION_DEAD, name + "_destruction.msa") diff --git a/assets/root/uiinventory.py b/assets/root/uiinventory.py index 6686922d..0c673aa9 100644 --- a/assets/root/uiinventory.py +++ b/assets/root/uiinventory.py @@ -24,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 @@ -88,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() @@ -252,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() @@ -439,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 @@ -463,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() @@ -709,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() @@ -1205,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) diff --git a/assets/root/uitooltip.py b/assets/root/uitooltip.py index 3ff2dc74..7cce17ce 100644 --- a/assets/root/uitooltip.py +++ b/assets/root/uitooltip.py @@ -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): diff --git a/assets/uiscript/uiscript/costumewindow.py b/assets/uiscript/uiscript/costumewindow.py index 5ff7ce0b..71a27652 100644 --- a/assets/uiscript/uiscript/costumewindow.py +++ b/assets/uiscript/uiscript/costumewindow.py @@ -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}, ), }, ), diff --git a/assets/uiscript/uiscript/equipmentdialog.py b/assets/uiscript/uiscript/equipmentdialog.py index 8089642f..f09c1c4b 100644 --- a/assets/uiscript/uiscript/equipmentdialog.py +++ b/assets/uiscript/uiscript/equipmentdialog.py @@ -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}, ), },