From c94c2e2394779dcfe5868b7ea2e4b2be55e86ee2 Mon Sep 17 00:00:00 2001 From: rtw1x1 Date: Wed, 21 Jan 2026 21:48:18 +0000 Subject: [PATCH] QoL: Real Timer for items / affect Items must use REAL_TIME or REAL_TIME_FIRST_USE --- assets/root/game.py | 6 +- assets/root/localeinfo.py | 29 ++++++ assets/root/uiaffectshower.py | 30 +++---- assets/root/uitooltip.py | 160 ++++++++++++++++++++++++---------- 4 files changed, 159 insertions(+), 66 deletions(-) diff --git a/assets/root/game.py b/assets/root/game.py index f36b1bed..f3670379 100644 --- a/assets/root/game.py +++ b/assets/root/game.py @@ -762,18 +762,18 @@ class GameWindow(ui.ScriptWindow): # UNKNOWN_UPDATE def BINARY_NEW_AddAffect(self, type, pointIdx, value, duration): self.affectShower.BINARY_NEW_AddAffect(type, pointIdx, value, duration) + if chr.NEW_AFFECT_DRAGON_SOUL_DECK1 == type or chr.NEW_AFFECT_DRAGON_SOUL_DECK2 == type: self.interface.DragonSoulActivate(type - chr.NEW_AFFECT_DRAGON_SOUL_DECK1) + elif chr.NEW_AFFECT_DRAGON_SOUL_QUALIFIED == type: self.BINARY_DragonSoulGiveQuilification() def BINARY_NEW_RemoveAffect(self, type, pointIdx): self.affectShower.BINARY_NEW_RemoveAffect(type, pointIdx) + if chr.NEW_AFFECT_DRAGON_SOUL_DECK1 == type or chr.NEW_AFFECT_DRAGON_SOUL_DECK2 == type: self.interface.DragonSoulDeactivate() - - - # END_OF_UNKNOWN_UPDATE def ActivateSkillSlot(self, slotIndex): diff --git a/assets/root/localeinfo.py b/assets/root/localeinfo.py index 5ee906a7..cdef2eb2 100644 --- a/assets/root/localeinfo.py +++ b/assets/root/localeinfo.py @@ -381,3 +381,32 @@ def SecondToHM(time): if minute > 0: text += str(minute) + MINUTE return text + +# Convert seconds to Days-Hours-Minutes-Seconds in real time +def RTSecondToDHMS(time): + text = "" + + d = time // (24 * 3600) + time %= (24 * 3600) + h = time // 3600 + time %= 3600 + m = time // 60 + s = time % 60 + + if d or not text: + if d: + text += "%dd " % d + + if h or not text: + if h: + text += "%dh " % h + + if m or not text: + if m: + text += "%dm " % m + + if s or not text: + if s: + text += "%ds " % s + + return text.strip() diff --git a/assets/root/uiaffectshower.py b/assets/root/uiaffectshower.py index 598733a1..9db9d422 100644 --- a/assets/root/uiaffectshower.py +++ b/assets/root/uiaffectshower.py @@ -292,6 +292,9 @@ class AffectImage(ui.ExpandedImageBox): self.endTime = 0 if duration > 0: self.endTime = app.GetGlobalTimeStamp() + duration + leftTime = localeInfo.RTSecondToDHMS(self.endTime - app.GetGlobalTimeStamp()) + self.toolTip.AppendTextLine("(%s : %s)" % (localeInfo.LEFT_TIME, leftTime)) + self.toolTip.ResizeToolTip() def UpdateAutoPotionDescription(self): @@ -319,25 +322,14 @@ class AffectImage(ui.ExpandedImageBox): def UpdateDescription(self): if not self.isClocked: - self.__UpdateDescription2() return - - if not self.description: - return - - toolTip = self.description - if self.endTime > 0: - leftTime = localeInfo.SecondToDHM(self.endTime - app.GetGlobalTimeStamp()) - toolTip += " (%s : %s)" % (localeInfo.LEFT_TIME, leftTime) - self.SetToolTipText(toolTip, 0, 40) - - #µ¶ÀϹöÀü¿¡¼­ ½Ã°£À» Á¦°ÅÇϱâ À§Çؼ­ »ç¿ë - def __UpdateDescription2(self): + if not self.description: return - toolTip = self.description - self.SetToolTipText(toolTip, 0, 40) + if self.endTime > 0: + leftTime = localeInfo.RTSecondToDHMS(self.endTime - app.GetGlobalTimeStamp()) + self.toolTip.childrenList[-1].SetText("(%s : %s)" % (localeInfo.LEFT_TIME, leftTime)) def SetSkillAffectFlag(self, flag): self.isSkillAffect = flag @@ -404,7 +396,7 @@ class AffectShower(ui.Window): chr.NEW_AFFECT_SKILL_BOOK_BONUS : (localeInfo.TOOLTIP_APPLY_SKILL_BOOK_BONUS, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"), chr.NEW_AFFECT_SKILL_BOOK_NO_DELAY : (localeInfo.TOOLTIP_APPLY_SKILL_BOOK_NO_DELAY, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"), - # ÀÚµ¿¹°¾à hp, sp + # �ڵ����� hp, sp chr.NEW_AFFECT_AUTO_HP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/pattern/auto_hpgauge/05.dds"), chr.NEW_AFFECT_AUTO_SP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/pattern/auto_spgauge/05.dds"), #chr.NEW_AFFECT_AUTO_HP_RECOVERY : (localeInfo.TOOLTIP_AUTO_POTION_REST, "d:/ymir work/ui/skill/common/affect/gold_premium.sub"), @@ -424,7 +416,7 @@ class AffectShower(ui.Window): MALL_DESC_IDX_START+player.POINT_PC_BANG_DROP_BONUS: (localeInfo.TOOLTIP_MALL_ITEMBONUS_P_STATIC, "d:/ymir work/ui/skill/common/affect/Item_Bonus_p_on.sub",), } if app.ENABLE_DRAGON_SOUL_SYSTEM: - # ¿ëÈ¥¼® õ, Áö µ¦. + # ��ȥ�� õ, �� ��. AFFECT_DATA_DICT[chr.NEW_AFFECT_DRAGON_SOUL_DECK1] = (localeInfo.TOOLTIP_DRAGON_SOUL_DECK1, "d:/ymir work/ui/dragonsoul/buff_ds_sky1.tga") AFFECT_DATA_DICT[chr.NEW_AFFECT_DRAGON_SOUL_DECK2] = (localeInfo.TOOLTIP_DRAGON_SOUL_DECK2, "d:/ymir work/ui/dragonsoul/buff_ds_land1.tga") @@ -449,7 +441,7 @@ class AffectShower(ui.Window): self.affectImageDict={} self.__ArrangeImageList() - def ClearAffects(self): ## ½ºÅ³ ÀÌÆåÆ®¸¸ ¾ø¾Û´Ï´Ù. + def ClearAffects(self): ## ��ų ����Ʈ�� ���۴ϴ�. self.living_affectImageDict={} for key, image in self.affectImageDict.items(): if not image.IsSkillAffect(): @@ -475,7 +467,7 @@ class AffectShower(ui.Window): if not self.AFFECT_DATA_DICT.has_key(affect): return - ## ¿ë½ÅÀÇ °¡È£, ¼±ÀÎÀÇ ±³ÈÆÀº Duration À» 0 À¸·Î ¼³Á¤ÇÑ´Ù. + ## ����� ��ȣ, ������ ������ Duration �� 0 ���� �����Ѵ�. if affect == chr.NEW_AFFECT_NO_DEATH_PENALTY or\ affect == chr.NEW_AFFECT_SKILL_BOOK_BONUS or\ affect == chr.NEW_AFFECT_AUTO_SP_RECOVERY or\ diff --git a/assets/root/uitooltip.py b/assets/root/uitooltip.py index 00434c45..8709c46c 100644 --- a/assets/root/uitooltip.py +++ b/assets/root/uitooltip.py @@ -122,6 +122,8 @@ class ToolTip(ui.ThinBoard): self.xPos = -1 self.yPos = -1 + self.timeInfoList = [] + self.defFontName = localeInfo.UI_DEF_FONT self.ClearToolTip() @@ -131,6 +133,7 @@ class ToolTip(ui.ThinBoard): def ClearToolTip(self): self.toolTipHeight = 12 self.childrenList = [] + self.timeInfoList = [] def SetFollow(self, flag): self.followFlag = flag @@ -302,6 +305,12 @@ class ToolTip(ui.ThinBoard): if not self.followFlag: return + for timeText in self.timeInfoList: + if timeText["line"]: + leftSec = max(0, timeText["value"] - app.GetGlobalTimeStamp()) + if not self.isShopItem: + timeText["line"].SetText(localeInfo.LEFT_TIME + ": " + localeInfo.RTSecondToDHMS(leftSec)) + x = 0 y = 0 width = self.GetWidth() @@ -549,6 +558,13 @@ class ItemToolTip(ToolTip): return ToolTip.AppendTextLine(self, text, color, centerAlign) + def AppendTextLineTime(self, endTime, getLimit): + color = self.FONT_COLOR + if not self.CanEquip() and self.bCannotUseItemForceSetDisableColor: + color = self.DISABLE_COLOR + + return ToolTip.AppendTextLineTime(self, endTime, getLimit, color) + def ClearToolTip(self): self.isShopItem = False self.toolTipWidth = self.TOOL_TIP_WIDTH @@ -952,7 +968,21 @@ class ItemToolTip(ToolTip): #Planning for the ring socket system has not yet been decided #self.__AppendAccessoryMetinSlotInfo(metinSlot, 99001) - + + bHasRealtimeFlag = 0 + for i in xrange(item.LIMIT_MAX_NUM): + (limitType, limitValue) = item.GetLimit(i) + + if item.LIMIT_REAL_TIME == limitType: + bHasRealtimeFlag = 1 + + if 1 == bHasRealtimeFlag: + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) + + self.AppendSpace(5) ### Belt Item ### elif item.ITEM_TYPE_BELT == itemType: @@ -971,18 +1001,17 @@ class ItemToolTip(ToolTip): self.AppendWearableInformation() bHasRealtimeFlag = 0 - - # # Find out if there is limited time remaining for i in xrange(item.LIMIT_MAX_NUM): (limitType, limitValue) = item.GetLimit(i) if item.LIMIT_REAL_TIME == limitType: bHasRealtimeFlag = 1 - ## If exists, display related information. ex) Remaining time: 6 days 6 hours 58 minutes if 1 == bHasRealtimeFlag: - self.AppendMallItemLastTime(metinSlot[0]) - #dbg.TraceError("1) REAL_TIME flag On ") + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) ## Rod ## elif item.ITEM_TYPE_ROD == itemType: @@ -1056,20 +1085,25 @@ class ItemToolTip(ToolTip): elif item.ITEM_TYPE_UNIQUE == itemType: if 0 != metinSlot: bHasRealtimeFlag = 0 - for i in xrange(item.LIMIT_MAX_NUM): (limitType, limitValue) = item.GetLimit(i) if item.LIMIT_REAL_TIME == limitType: bHasRealtimeFlag = 1 - + if 1 == bHasRealtimeFlag: - self.AppendMallItemLastTime(metinSlot[0]) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) else: - time = metinSlot[player.METIN_SOCKET_MAX_NUM-1] + time = metinSlot[player.METIN_SOCKET_MAX_NUM - 1] if 1 == item.GetValue(2): ## Real-time use flag / given even if not equipped - self.AppendMallItemLastTime(time) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(time, item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(time, item.GetLimitValue(1)) else: self.AppendUniqueItemLastTime(time) @@ -1148,22 +1182,23 @@ class ItemToolTip(ToolTip): if item.LIMIT_REAL_TIME == limitType: bHasRealtimeFlag = 1 - ## If exists, display related information. ex) Remaining time: 6 days 6 hours 58 minutes if 1 == bHasRealtimeFlag: - self.AppendMallItemLastTime(metinSlot[0]) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) else: - # ... This... This time isn't checked on the server... - # I don't know why this exists, but let's just leave it... if 0 != metinSlot: - time = metinSlot[player.METIN_SOCKET_MAX_NUM-1] + time = metinSlot[player.METIN_SOCKET_MAX_NUM - 1] - ## Real-time usage Flag if 1 == item.GetValue(2): - self.AppendMallItemLastTime(time) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(time, item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(time, item.GetLimitValue(1)) elif item.USE_TIME_CHARGE_PER == itemSubType: bHasRealtimeFlag = 0 - for i in xrange(item.LIMIT_MAX_NUM): (limitType, limitValue) = item.GetLimit(i) @@ -1175,9 +1210,11 @@ class ItemToolTip(ToolTip): else: self.AppendTextLine(localeInfo.TOOLTIP_TIME_CHARGER_PER(item.GetValue(0))) - ## If available, display relevant information. ex) Time remaining: 6 days, 6 hours, 58 minutes if 1 == bHasRealtimeFlag: - self.AppendMallItemLastTime(metinSlot[0]) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) elif item.USE_TIME_CHARGE_FIX == itemSubType: bHasRealtimeFlag = 0 @@ -1186,21 +1223,32 @@ class ItemToolTip(ToolTip): if item.LIMIT_REAL_TIME == limitType: bHasRealtimeFlag = 1 + if metinSlot[2]: self.AppendTextLine(localeInfo.TOOLTIP_TIME_CHARGER_FIX(metinSlot[2])) else: self.AppendTextLine(localeInfo.TOOLTIP_TIME_CHARGER_FIX(item.GetValue(0))) - - ## If exists, display related information. ex) Remaining time: 6 days 6 hours 58 minutes + if 1 == bHasRealtimeFlag: - self.AppendMallItemLastTime(metinSlot[0]) + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) elif item.ITEM_TYPE_QUEST == itemType: + bHasRealtimeFlag = 0 for i in xrange(item.LIMIT_MAX_NUM): (limitType, limitValue) = item.GetLimit(i) if item.LIMIT_REAL_TIME == limitType: - self.AppendMallItemLastTime(metinSlot[0]) + bHasRealtimeFlag = 1 + + if 1 == bHasRealtimeFlag: + if item.LIMIT_REAL_TIME == item.GetLimitType(0) or item.LIMIT_REAL_TIME_START_FIRST_USE == item.GetLimitType(0): + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(0)) + else: + self.AppendMallItemLastTime(metinSlot[0], item.GetLimitValue(1)) + elif item.ITEM_TYPE_DS == itemType: self.AppendTextLine(self.__DragonSoulInfoString(itemVnum)) self.__AppendAttributeInformation(attrSlot) @@ -1209,17 +1257,13 @@ class ItemToolTip(ToolTip): for i in xrange(item.LIMIT_MAX_NUM): (limitType, limitValue) = item.GetLimit(i) - #dbg.TraceError("LimitType : %d, limitValue : %d" % (limitType, limitValue)) - + limitValue2 = item.GetLimitValue(i) + if item.LIMIT_REAL_TIME_START_FIRST_USE == limitType: - self.AppendRealTimeStartFirstUseLastTime(item, metinSlot, i) - #dbg.TraceError("2) REAL_TIME_START_FIRST_USE flag On ") - + self.AppendRealTimeStartFirstUseLastTime(item, metinSlot, i, limitValue2) + elif item.LIMIT_TIMER_BASED_ON_WEAR == limitType: self.AppendTimerBasedOnWearLastTime(metinSlot) - #dbg.TraceError("1) REAL_TIME flag On ") - - self.ShowToolTip() @@ -1782,7 +1826,7 @@ class ItemToolTip(ToolTip): self.toolTipHeight += 16 + 2 if 0 != leftTime: - timeText = (localeInfo.LEFT_TIME + " : " + localeInfo.SecondToDHM(leftTime)) + timeText = (localeInfo.LEFT_TIME + " : " + localeInfo.RTSecondToDHMS(leftTime)) timeTextLine = ui.TextLine() timeTextLine.SetParent(self) @@ -1808,24 +1852,49 @@ class ItemToolTip(ToolTip): self.AppendTextLine(localeInfo.TOOLTIP_FISH_LEN % (float(size) / 100.0), self.NORMAL_COLOR) def AppendUniqueItemLastTime(self, restMin): - restSecond = restMin*60 - self.AppendSpace(5) - self.AppendTextLine(localeInfo.LEFT_TIME + " : " + localeInfo.SecondToDHM(restSecond), self.NORMAL_COLOR) + if restMin > 0: + restSecond = restMin * 60 + self.AppendSpace(5) + self.AppendTextLine(localeInfo.LEFT_TIME + " : " + localeInfo.RTSecondToDHMS(restSecond), self.NORMAL_COLOR) - def AppendMallItemLastTime(self, endTime): + def AppendMallItemLastTime(self, endTime, getLimit): + if endTime > 0: + self.AppendSpace(5) + self.AppendTextLineTime(endTime, getLimit) + + def AppendTextLineTime(self, endTime, getLimit, color=FONT_COLOR): leftSec = max(0, endTime - app.GetGlobalTimeStamp()) - self.AppendSpace(5) - self.AppendTextLine(localeInfo.LEFT_TIME + " : " + localeInfo.SecondToDHM(leftSec), self.NORMAL_COLOR) - + + timeTextLine = ui.TextLine() + timeTextLine.SetParent(self) + timeTextLine.SetFontName(self.defFontName) + timeTextLine.SetPackedFontColor(color) + + if not self.isShopItem: + timeTextLine.SetText(localeInfo.LEFT_TIME + ": " + localeInfo.RTSecondToDHMS(leftSec)) + + timeTextLine.SetOutline() + timeTextLine.SetFeather(False) + timeTextLine.SetPosition(self.toolTipWidth / 2, self.toolTipHeight) + timeTextLine.SetHorizontalAlignCenter() + timeTextLine.Show() + + self.timeInfoList.append({"line": timeTextLine, "value": endTime, "limit": getLimit}) + + self.toolTipHeight += self.TEXT_LINE_HEIGHT + self.ResizeToolTip() + + return timeTextLine + def AppendTimerBasedOnWearLastTime(self, metinSlot): if 0 == metinSlot[0]: self.AppendSpace(5) self.AppendTextLine(localeInfo.CANNOT_USE, self.DISABLE_COLOR) else: endTime = app.GetGlobalTimeStamp() + metinSlot[0] - self.AppendMallItemLastTime(endTime) + self.AppendMallItemLastTime(endTime, getLimit) - def AppendRealTimeStartFirstUseLastTime(self, item, metinSlot, limitIndex): + def AppendRealTimeStartFirstUseLastTime(self, item, metinSlot, limitIndex, getLimit): useCount = metinSlot[1] endTime = metinSlot[0] @@ -1836,9 +1905,12 @@ class ItemToolTip(ToolTip): (limitType, limitValue) = item.GetLimit(limitIndex) endTime = limitValue + self.AppendUniqueItemLastTime(endTime / 60) + return + endTime += app.GetGlobalTimeStamp() - self.AppendMallItemLastTime(endTime) + self.AppendMallItemLastTime(endTime, getLimit) class HyperlinkItemToolTip(ItemToolTip): def __init__(self):