Files
m2dev-client/assets/root/uicharacter.py
2026-02-13 01:44:21 +02:00

1344 lines
40 KiB
Python

import ui
import uiScriptLocale
import app
import net
import dbg
import snd
import player
import mouseModule
import wndMgr
import skill
import playerSettingModule
import quest
import localeInfo
import uiToolTip
import constInfo
import emotion
import chr
SHOW_ONLY_ACTIVE_SKILL = False
SHOW_LIMIT_SUPPORT_SKILL_LIST = []
HIDE_SUPPORT_SKILL_POINT = True
FACE_IMAGE_DICT = {
playerSettingModule.RACE_WARRIOR_M : "icon/face/warrior_m.tga",
playerSettingModule.RACE_WARRIOR_W : "icon/face/warrior_w.tga",
playerSettingModule.RACE_ASSASSIN_M : "icon/face/assassin_m.tga",
playerSettingModule.RACE_ASSASSIN_W : "icon/face/assassin_w.tga",
playerSettingModule.RACE_SURA_M : "icon/face/sura_m.tga",
playerSettingModule.RACE_SURA_W : "icon/face/sura_w.tga",
playerSettingModule.RACE_SHAMAN_M : "icon/face/shaman_m.tga",
playerSettingModule.RACE_SHAMAN_W : "icon/face/shaman_w.tga",
}
def unsigned32(n):
return n & 0xFFFFFFFF
class CharacterWindow(ui.ScriptWindow):
ACTIVE_PAGE_SLOT_COUNT = 8
SUPPORT_PAGE_SLOT_COUNT = 12
PAGE_SLOT_COUNT = 12
PAGE_HORSE = 3
SKILL_GROUP_NAME_DICT = {
playerSettingModule.JOB_WARRIOR : { 1 : localeInfo.SKILL_GROUP_WARRIOR_1, 2 : localeInfo.SKILL_GROUP_WARRIOR_2, },
playerSettingModule.JOB_ASSASSIN : { 1 : localeInfo.SKILL_GROUP_ASSASSIN_1, 2 : localeInfo.SKILL_GROUP_ASSASSIN_2, },
playerSettingModule.JOB_SURA : { 1 : localeInfo.SKILL_GROUP_SURA_1, 2 : localeInfo.SKILL_GROUP_SURA_2, },
playerSettingModule.JOB_SHAMAN : { 1 : localeInfo.SKILL_GROUP_SHAMAN_1, 2 : localeInfo.SKILL_GROUP_SHAMAN_2, },
}
STAT_DESCRIPTION = {
"HTH" : localeInfo.STAT_TOOLTIP_CON,
"INT" : localeInfo.STAT_TOOLTIP_INT,
"STR" : localeInfo.STAT_TOOLTIP_STR,
"DEX" : localeInfo.STAT_TOOLTIP_DEX,
}
STAT_MINUS_DESCRIPTION = localeInfo.STAT_MINUS_DESCRIPTION
def __init__(self):
ui.ScriptWindow.__init__(self)
self.state = "STATUS"
self.isLoaded = 0
self.toolTipSkill = 0
self.__Initialize()
self.__LoadWindow()
self.statusPlusCommandDict={
"HTH" : "/stat ht",
"INT" : "/stat iq",
"STR" : "/stat st",
"DEX" : "/stat dx",
}
self.statusMinusCommandDict={
"HTH-" : "/stat- ht",
"INT-" : "/stat- iq",
"STR-" : "/stat- st",
"DEX-" : "/stat- dx",
}
def __del__(self):
ui.ScriptWindow.__del__(self)
def __Initialize(self):
self.refreshToolTip = 0
self.curSelectedSkillGroup = 0
self.canUseHorseSkill = -1
self.toolTip = None
self.toolTipJob = None
self.toolTipAlignment = None
self.toolTipSkill = None
self.faceImage = None
self.statusPlusLabel = None
self.statusPlusValue = None
self.activeSlot = None
self.tabDict = None
self.tabButtonDict = None
self.pageDict = None
self.titleBarDict = None
self.statusPlusButtonDict = None
self.statusMinusButtonDict = None
self.skillPageDict = None
self.questShowingStartIndex = 0
self.questScrollBar = None
self.questSlot = None
self.questNameList = None
self.questLastTimeList = None
self.questLastCountList = None
self.skillGroupButton = ()
self.activeSlot = None
self.activeSkillPointValue = None
self.supportSkillPointValue = None
self.skillGroupButton1 = None
self.skillGroupButton2 = None
self.skillGroupButton3 = None
self.activeSkillGroupName = None
self.guildNameSlot = None
self.guildNameValue = None
self.characterNameSlot = None
self.characterNameValue = None
self.emotionToolTip = None
self.soloEmotionSlot = None
self.dualEmotionSlot = None
def Show(self):
self.__LoadWindow()
ui.ScriptWindow.Show(self)
def __LoadScript(self, fileName):
pyScrLoader = ui.PythonScriptLoader()
pyScrLoader.LoadScriptFile(self, fileName)
def __BindObject(self):
self.toolTip = uiToolTip.ToolTip()
self.toolTipJob = uiToolTip.ToolTip()
self.toolTipAlignment = uiToolTip.ToolTip(130)
self.faceImage = self.GetChild("Face_Image")
faceSlot=self.GetChild("Face_Slot")
self.statusPlusLabel = self.GetChild("Status_Plus_Label")
self.statusPlusValue = self.GetChild("Status_Plus_Value")
self.characterNameSlot = self.GetChild("Character_Name_Slot")
self.characterNameValue = self.GetChild("Character_Name")
self.guildNameSlot = self.GetChild("Guild_Name_Slot")
self.guildNameValue = self.GetChild("Guild_Name")
self.characterNameSlot.SAFE_SetStringEvent("MOUSE_OVER_IN", self.__ShowAlignmentToolTip)
self.characterNameSlot.SAFE_SetStringEvent("MOUSE_OVER_OUT", self.__HideAlignmentToolTip)
self.activeSlot = self.GetChild("Skill_Active_Slot")
self.activeSkillPointValue = self.GetChild("Active_Skill_Point_Value")
self.supportSkillPointValue = self.GetChild("Support_Skill_Point_Value")
self.skillGroupButton1 = self.GetChild("Skill_Group_Button_1")
self.skillGroupButton2 = self.GetChild("Skill_Group_Button_2")
self.skillGroupButton3 = self.GetChild("Skill_Group_Button_3")
self.activeSkillGroupName = self.GetChild("Active_Skill_Group_Name")
self.tabDict = {
"STATUS" : self.GetChild("Tab_01"),
"SKILL" : self.GetChild("Tab_02"),
"EMOTICON" : self.GetChild("Tab_03"),
"QUEST" : self.GetChild("Tab_04"),
}
self.tabButtonDict = {
"STATUS" : self.GetChild("Tab_Button_01"),
"SKILL" : self.GetChild("Tab_Button_02"),
"EMOTICON" : self.GetChild("Tab_Button_03"),
"QUEST" : self.GetChild("Tab_Button_04")
}
self.pageDict = {
"STATUS" : self.GetChild("Character_Page"),
"SKILL" : self.GetChild("Skill_Page"),
"EMOTICON" : self.GetChild("Emoticon_Page"),
"QUEST" : self.GetChild("Quest_Page")
}
self.titleBarDict = {
"STATUS" : self.GetChild("Character_TitleBar"),
"SKILL" : self.GetChild("Skill_TitleBar"),
"EMOTICON" : self.GetChild("Emoticon_TitleBar"),
"QUEST" : self.GetChild("Quest_TitleBar")
}
self.statusPlusButtonDict = {
"HTH" : self.GetChild("HTH_Plus"),
"INT" : self.GetChild("INT_Plus"),
"STR" : self.GetChild("STR_Plus"),
"DEX" : self.GetChild("DEX_Plus"),
}
self.statusMinusButtonDict = {
"HTH-" : self.GetChild("HTH_Minus"),
"INT-" : self.GetChild("INT_Minus"),
"STR-" : self.GetChild("STR_Minus"),
"DEX-" : self.GetChild("DEX_Minus"),
}
self.skillPageDict = {
"ACTIVE" : self.GetChild("Skill_Active_Slot"),
"SUPPORT" : self.GetChild("Skill_ETC_Slot"),
"HORSE" : self.GetChild("Skill_Active_Slot"),
}
self.skillPageStatDict = {
"SUPPORT" : player.SKILL_SUPPORT,
"ACTIVE" : player.SKILL_ACTIVE,
"HORSE" : player.SKILL_HORSE,
}
self.skillGroupButton = (
self.GetChild("Skill_Group_Button_1"),
self.GetChild("Skill_Group_Button_2"),
self.GetChild("Skill_Group_Button_3"),
)
global SHOW_ONLY_ACTIVE_SKILL
global HIDE_SUPPORT_SKILL_POINT
if SHOW_ONLY_ACTIVE_SKILL or HIDE_SUPPORT_SKILL_POINT:
self.GetChild("Support_Skill_Point_Label").Hide()
self.soloEmotionSlot = self.GetChild("SoloEmotionSlot")
self.dualEmotionSlot = self.GetChild("DualEmotionSlot")
self.__SetEmotionSlot()
self.questShowingStartIndex = 0
self.questScrollBar = self.GetChild("Quest_ScrollBar")
self.questScrollBar.SetScrollEvent(ui.__mem_func__(self.OnQuestScroll))
self.questSlot = self.GetChild("Quest_Slot")
for i in range(quest.QUEST_MAX_NUM):
self.questSlot.HideSlotBaseImage(i)
self.questSlot.SetCoverButton(i,\
"d:/ymir work/ui/game/quest/slot_button_01.sub",\
"d:/ymir work/ui/game/quest/slot_button_02.sub",\
"d:/ymir work/ui/game/quest/slot_button_03.sub",\
"d:/ymir work/ui/game/quest/slot_button_03.sub", True)
self.questNameList = []
self.questLastTimeList = []
self.questLastCountList = []
for i in range(quest.QUEST_MAX_NUM):
self.questNameList.append(self.GetChild("Quest_Name_0" + str(i)))
self.questLastTimeList.append(self.GetChild("Quest_LastTime_0" + str(i)))
self.questLastCountList.append(self.GetChild("Quest_LastCount_0" + str(i)))
def __SetSkillSlotEvent(self):
for skillPageValue in list(self.skillPageDict.values()):
skillPageValue.SetSlotStyle(wndMgr.SLOT_STYLE_NONE)
skillPageValue.SetSelectItemSlotEvent(ui.__mem_func__(self.SelectSkill))
skillPageValue.SetSelectEmptySlotEvent(ui.__mem_func__(self.SelectEmptySlot))
skillPageValue.SetUnselectItemSlotEvent(ui.__mem_func__(self.ClickSkillSlot))
skillPageValue.SetUseSlotEvent(ui.__mem_func__(self.ClickSkillSlot))
skillPageValue.SetOverInItemEvent(ui.__mem_func__(self.OverInItem))
skillPageValue.SetOverOutItemEvent(ui.__mem_func__(self.OverOutItem))
skillPageValue.SetPressedSlotButtonEvent(ui.__mem_func__(self.OnPressedSlotButton))
skillPageValue.AppendSlotButton("d:/ymir work/ui/game/windows/btn_plus_up.sub",\
"d:/ymir work/ui/game/windows/btn_plus_over.sub",\
"d:/ymir work/ui/game/windows/btn_plus_down.sub")
def __SetEmotionSlot(self):
self.emotionToolTip = uiToolTip.ToolTip()
for slot in (self.soloEmotionSlot, self.dualEmotionSlot):
slot.SetSlotStyle(wndMgr.SLOT_STYLE_NONE)
slot.SetSelectItemSlotEvent(ui.__mem_func__(self.__SelectEmotion))
slot.SetUnselectItemSlotEvent(ui.__mem_func__(self.__ClickEmotionSlot))
slot.SetUseSlotEvent(ui.__mem_func__(self.__ClickEmotionSlot))
slot.SetOverInItemEvent(ui.__mem_func__(self.__OverInEmotion))
slot.SetOverOutItemEvent(ui.__mem_func__(self.__OverOutEmotion))
slot.AppendSlotButton("d:/ymir work/ui/game/windows/btn_plus_up.sub",\
"d:/ymir work/ui/game/windows/btn_plus_over.sub",\
"d:/ymir work/ui/game/windows/btn_plus_down.sub")
for slotIdx, datadict in list(emotion.EMOTION_DICT.items()):
emotionIdx = slotIdx
slot = self.soloEmotionSlot
if slotIdx > 50:
slot = self.dualEmotionSlot
slot.SetEmotionSlot(slotIdx, emotionIdx)
slot.SetCoverButton(slotIdx)
def __SelectEmotion(self, slotIndex):
if not slotIndex in emotion.EMOTION_DICT:
return
if app.IsPressed(app.DIK_LCONTROL):
player.RequestAddToEmptyLocalQuickSlot(player.SLOT_TYPE_EMOTION, slotIndex)
return
mouseModule.mouseController.AttachObject(self, player.SLOT_TYPE_EMOTION, slotIndex, slotIndex)
def __ClickEmotionSlot(self, slotIndex):
print("click emotion")
if not slotIndex in emotion.EMOTION_DICT:
return
print("check acting")
if player.IsActingEmotion():
return
command = emotion.EMOTION_DICT[slotIndex]["command"]
print(("command", command))
if slotIndex > 50:
vid = player.GetTargetVID()
if 0 == vid or vid == player.GetMainCharacterIndex() or chr.IsNPC(vid) or chr.IsEnemy(vid):
import chat
chat.AppendChat(chat.CHAT_TYPE_INFO, localeInfo.EMOTION_CHOOSE_ONE)
return
command += " " + chr.GetNameByVID(vid)
print(("send_command", command))
net.SendChatPacket(command)
def ActEmotion(self, emotionIndex):
self.__ClickEmotionSlot(emotionIndex)
def __OverInEmotion(self, slotIndex):
if self.emotionToolTip:
if not slotIndex in emotion.EMOTION_DICT:
return
self.emotionToolTip.ClearToolTip()
self.emotionToolTip.SetTitle(emotion.EMOTION_DICT[slotIndex]["name"])
self.emotionToolTip.AlignHorizonalCenter()
self.emotionToolTip.ShowToolTip()
def __OverOutEmotion(self):
if self.emotionToolTip:
self.emotionToolTip.HideToolTip()
def __BindEvent(self):
for i in range(len(self.skillGroupButton)):
self.skillGroupButton[i].SetEvent(lambda arg=i: self.__SelectSkillGroup(arg))
self.RefreshQuest()
self.__HideJobToolTip()
for (tabKey, tabButton) in list(self.tabButtonDict.items()):
tabButton.SetEvent(ui.__mem_func__(self.__OnClickTabButton), tabKey)
for (statusPlusKey, statusPlusButton) in list(self.statusPlusButtonDict.items()):
statusPlusButton.SAFE_SetEvent(self.__OnClickStatusPlusButton, statusPlusKey)
statusPlusButton.ShowToolTip = lambda arg=statusPlusKey: self.__OverInStatButton(arg)
statusPlusButton.HideToolTip = lambda arg=statusPlusKey: self.__OverOutStatButton()
for (statusMinusKey, statusMinusButton) in list(self.statusMinusButtonDict.items()):
statusMinusButton.SAFE_SetEvent(self.__OnClickStatusMinusButton, statusMinusKey)
statusMinusButton.ShowToolTip = lambda arg=statusMinusKey: self.__OverInStatMinusButton(arg)
statusMinusButton.HideToolTip = lambda arg=statusMinusKey: self.__OverOutStatMinusButton()
for titleBarValue in list(self.titleBarDict.values()):
titleBarValue.SetCloseEvent(ui.__mem_func__(self.Hide))
self.questSlot.SetSelectItemSlotEvent(ui.__mem_func__(self.__SelectQuest))
def __LoadWindow(self):
if self.isLoaded == 1:
return
self.isLoaded = 1
try:
if app.IsRTL():
self.__LoadScript(uiScriptLocale.LOCALE_UISCRIPT_PATH + "CharacterWindow.py")
else:
self.__LoadScript("UIScript/CharacterWindow.py")
self.__BindObject()
self.__BindEvent()
except:
import exception
exception.Abort("CharacterWindow.__LoadWindow")
#self.tabButtonDict["EMOTICON"].Disable()
self.SetState("STATUS")
def Destroy(self):
self.ClearDictionary()
self.__Initialize()
def Close(self):
if 0 != self.toolTipSkill:
self.toolTipSkill.Hide()
self.Hide()
def SetSkillToolTip(self, toolTipSkill):
self.toolTipSkill = toolTipSkill
def __OnClickStatusPlusButton(self, statusKey):
try:
statusPlusCommand=self.statusPlusCommandDict[statusKey]
net.SendChatPacket(statusPlusCommand)
except KeyError as msg:
dbg.TraceError("CharacterWindow.__OnClickStatusPlusButton KeyError: %s", msg)
def __OnClickStatusMinusButton(self, statusKey):
try:
statusMinusCommand=self.statusMinusCommandDict[statusKey]
net.SendChatPacket(statusMinusCommand)
except KeyError as msg:
dbg.TraceError("CharacterWindow.__OnClickStatusMinusButton KeyError: %s", msg)
def __OnClickTabButton(self, stateKey):
self.SetState(stateKey)
def SetState(self, stateKey):
self.state = stateKey
for (tabKey, tabButton) in list(self.tabButtonDict.items()):
if stateKey!=tabKey:
tabButton.SetUp()
for tabValue in list(self.tabDict.values()):
tabValue.Hide()
for pageValue in list(self.pageDict.values()):
pageValue.Hide()
for titleBarValue in list(self.titleBarDict.values()):
titleBarValue.Hide()
self.titleBarDict[stateKey].Show()
self.tabDict[stateKey].Show()
self.pageDict[stateKey].Show()
def GetState(self):
return self.state
def __GetTotalAtkText(self):
minAtk=player.GetStatus(player.ATT_MIN)
maxAtk=player.GetStatus(player.ATT_MAX)
atkBonus=player.GetStatus(player.ATT_BONUS)
attackerBonus=player.GetStatus(player.ATTACKER_BONUS)
if minAtk==maxAtk:
return "%d" % (minAtk+atkBonus+attackerBonus)
else:
return "%d-%d" % (minAtk+atkBonus+attackerBonus, maxAtk+atkBonus+attackerBonus)
def __GetTotalMagAtkText(self):
minMagAtk=player.GetStatus(player.MAG_ATT)+player.GetStatus(player.MIN_MAGIC_WEP)
maxMagAtk=player.GetStatus(player.MAG_ATT)+player.GetStatus(player.MAX_MAGIC_WEP)
if minMagAtk==maxMagAtk:
return "%d" % (minMagAtk)
else:
return "%d-%d" % (minMagAtk, maxMagAtk)
def __GetTotalDefText(self):
defValue=player.GetStatus(player.DEF_GRADE)
if constInfo.ADD_DEF_BONUS_ENABLE:
defValue+=player.GetStatus(player.DEF_BONUS)
return "%d" % (defValue)
def RefreshStatus(self):
if self.isLoaded==0:
return
try:
self.GetChild("Level_Value").SetText(str(player.GetStatus(player.LEVEL)))
self.GetChild("Exp_Value").SetText(str(unsigned32(player.GetEXP())))
self.GetChild("RestExp_Value").SetText(str(unsigned32(player.GetStatus(player.NEXT_EXP)) - unsigned32(player.GetStatus(player.EXP))))
self.GetChild("HP_Value").SetText(str(player.GetStatus(player.HP)) + '/' + str(player.GetStatus(player.MAX_HP)))
self.GetChild("SP_Value").SetText(str(player.GetStatus(player.SP)) + '/' + str(player.GetStatus(player.MAX_SP)))
self.GetChild("STR_Value").SetText(str(player.GetStatus(player.ST)))
self.GetChild("DEX_Value").SetText(str(player.GetStatus(player.DX)))
self.GetChild("HTH_Value").SetText(str(player.GetStatus(player.HT)))
self.GetChild("INT_Value").SetText(str(player.GetStatus(player.IQ)))
self.GetChild("ATT_Value").SetText(self.__GetTotalAtkText())
self.GetChild("DEF_Value").SetText(self.__GetTotalDefText())
self.GetChild("MATT_Value").SetText(self.__GetTotalMagAtkText())
#self.GetChild("MATT_Value").SetText(str(player.GetStatus(player.MAG_ATT)))
self.GetChild("MDEF_Value").SetText(str(player.GetStatus(player.MAG_DEF)))
self.GetChild("ASPD_Value").SetText(str(player.GetStatus(player.ATT_SPEED)))
self.GetChild("MSPD_Value").SetText(str(player.GetStatus(player.MOVING_SPEED)))
self.GetChild("CSPD_Value").SetText(str(player.GetStatus(player.CASTING_SPEED)))
self.GetChild("ER_Value").SetText(str(player.GetStatus(player.EVADE_RATE)))
except:
#import exception
#exception.Abort("CharacterWindow.RefreshStatus.BindObject")
## Prevents game crash
pass
self.__RefreshStatusPlusButtonList()
self.__RefreshStatusMinusButtonList()
self.RefreshAlignment()
if self.refreshToolTip:
self.refreshToolTip()
def __RefreshStatusPlusButtonList(self):
if self.isLoaded==0:
return
statusPlusPoint=player.GetStatus(player.STAT)
if statusPlusPoint>0:
self.statusPlusValue.SetText(str(statusPlusPoint))
self.statusPlusLabel.Show()
self.ShowStatusPlusButtonList()
else:
self.statusPlusValue.SetText(str(0))
self.statusPlusLabel.Hide()
self.HideStatusPlusButtonList()
def __RefreshStatusMinusButtonList(self):
if self.isLoaded==0:
return
statusMinusPoint=self.__GetStatMinusPoint()
if statusMinusPoint>0:
self.__ShowStatusMinusButtonList()
else:
self.__HideStatusMinusButtonList()
def RefreshAlignment(self):
point, grade = player.GetAlignmentData()
import colorInfo
COLOR_DICT = { 0 : colorInfo.TITLE_RGB_GOOD_4,
1 : colorInfo.TITLE_RGB_GOOD_3,
2 : colorInfo.TITLE_RGB_GOOD_2,
3 : colorInfo.TITLE_RGB_GOOD_1,
4 : colorInfo.TITLE_RGB_NORMAL,
5 : colorInfo.TITLE_RGB_EVIL_1,
6 : colorInfo.TITLE_RGB_EVIL_2,
7 : colorInfo.TITLE_RGB_EVIL_3,
8 : colorInfo.TITLE_RGB_EVIL_4, }
colorList = COLOR_DICT.get(grade, colorInfo.TITLE_RGB_NORMAL)
gradeColor = ui.GenerateColor(colorList[0], colorList[1], colorList[2])
self.toolTipAlignment.ClearToolTip()
self.toolTipAlignment.AutoAppendTextLine(localeInfo.TITLE_NAME_LIST[grade], gradeColor)
self.toolTipAlignment.AutoAppendTextLine(localeInfo.ALIGNMENT_NAME + ": " + str(point))
self.toolTipAlignment.AlignHorizonalCenter()
def __ShowStatusMinusButtonList(self):
for (stateMinusKey, statusMinusButton) in list(self.statusMinusButtonDict.items()):
statusMinusButton.Show()
def __HideStatusMinusButtonList(self):
for (stateMinusKey, statusMinusButton) in list(self.statusMinusButtonDict.items()):
statusMinusButton.Hide()
def ShowStatusPlusButtonList(self):
for (statePlusKey, statusPlusButton) in list(self.statusPlusButtonDict.items()):
statusPlusButton.Show()
def HideStatusPlusButtonList(self):
for (statePlusKey, statusPlusButton) in list(self.statusPlusButtonDict.items()):
statusPlusButton.Hide()
def SelectSkill(self, skillSlotIndex):
mouseController = mouseModule.mouseController
if False == mouseController.isAttached():
srcSlotIndex = self.__RealSkillSlotToSourceSlot(skillSlotIndex)
selectedSkillIndex = player.GetSkillIndex(srcSlotIndex)
if skill.CanUseSkill(selectedSkillIndex):
if app.IsPressed(app.DIK_LCONTROL):
player.RequestAddToEmptyLocalQuickSlot(player.SLOT_TYPE_SKILL, srcSlotIndex)
return
mouseController.AttachObject(self, player.SLOT_TYPE_SKILL, srcSlotIndex, selectedSkillIndex)
else:
mouseController.DeattachObject()
def SelectEmptySlot(self, SlotIndex):
mouseModule.mouseController.DeattachObject()
## ToolTip
def OverInItem(self, slotNumber):
if mouseModule.mouseController.isAttached():
return
if 0 == self.toolTipSkill:
return
srcSlotIndex = self.__RealSkillSlotToSourceSlot(slotNumber)
skillIndex = player.GetSkillIndex(srcSlotIndex)
skillLevel = player.GetSkillLevel(srcSlotIndex)
skillGrade = player.GetSkillGrade(srcSlotIndex)
skillType = skill.GetSkillType(skillIndex)
## ACTIVE
if skill.SKILL_TYPE_ACTIVE == skillType:
overInSkillGrade = self.__GetSkillGradeFromSlot(slotNumber)
if overInSkillGrade == skill.SKILL_GRADE_COUNT-1 and skillGrade == skill.SKILL_GRADE_COUNT:
self.toolTipSkill.SetSkillNew(srcSlotIndex, skillIndex, skillGrade, skillLevel)
elif overInSkillGrade == skillGrade:
self.toolTipSkill.SetSkillNew(srcSlotIndex, skillIndex, overInSkillGrade, skillLevel)
else:
self.toolTipSkill.SetSkillOnlyName(srcSlotIndex, skillIndex, overInSkillGrade)
else:
self.toolTipSkill.SetSkillNew(srcSlotIndex, skillIndex, skillGrade, skillLevel)
def OverOutItem(self):
if 0 != self.toolTipSkill:
self.toolTipSkill.HideToolTip()
## Quest
def __SelectQuest(self, slotIndex):
questIndex = quest.GetQuestIndex(self.questShowingStartIndex+slotIndex)
import event
event.QuestButtonClick(-2147483648 + questIndex)
def RefreshQuest(self):
if self.isLoaded==0:
return
questCount = quest.GetQuestCount()
questRange = list(range(quest.QUEST_MAX_NUM))
if questCount > quest.QUEST_MAX_NUM:
self.questScrollBar.Show()
else:
self.questScrollBar.Hide()
for i in questRange[:questCount]:
(questName, questIcon, questCounterName, questCounterValue) = quest.GetQuestData(self.questShowingStartIndex+i)
self.questNameList[i].SetText(questName)
self.questNameList[i].Show()
self.questLastCountList[i].Show()
self.questLastTimeList[i].Show()
if len(questCounterName) > 0:
self.questLastCountList[i].SetText("%s : %d" % (questCounterName, questCounterValue))
else:
self.questLastCountList[i].SetText("")
## Icon
self.questSlot.SetSlot(i, i, 1, 1, questIcon)
for i in questRange[questCount:]:
self.questNameList[i].Hide()
self.questLastTimeList[i].Hide()
self.questLastCountList[i].Hide()
self.questSlot.ClearSlot(i)
self.questSlot.HideSlotBaseImage(i)
self.__UpdateQuestClock()
def __UpdateQuestClock(self):
if "QUEST" == self.state:
# QUEST_LIMIT_COUNT_BUG_FIX
for i in range(min(quest.GetQuestCount(), quest.QUEST_MAX_NUM)):
# END_OF_QUEST_LIMIT_COUNT_BUG_FIX
(lastName, lastTime) = quest.GetQuestLastTime(i)
clockText = localeInfo.QUEST_UNLIMITED_TIME
if len(lastName) > 0:
if lastTime <= 0:
clockText = localeInfo.QUEST_TIMEOVER
else:
questLastMinute = lastTime // 60
questLastSecond = lastTime % 60
clockText = lastName + " : "
if questLastMinute > 0:
clockText += str(questLastMinute) + localeInfo.QUEST_MIN
if questLastSecond > 0:
clockText += " "
if questLastSecond > 0:
clockText += str(questLastSecond) + localeInfo.QUEST_SEC
self.questLastTimeList[i].SetText(clockText)
def __GetStatMinusPoint(self):
POINT_STAT_RESET_COUNT = 112
return player.GetStatus(POINT_STAT_RESET_COUNT)
def __OverInStatMinusButton(self, stat):
try:
self.__ShowStatToolTip(self.STAT_MINUS_DESCRIPTION[stat] % self.__GetStatMinusPoint())
except KeyError:
pass
self.refreshToolTip = lambda arg=stat: self.__OverInStatMinusButton(arg)
def __OverOutStatMinusButton(self):
self.__HideStatToolTip()
self.refreshToolTip = 0
def __OverInStatButton(self, stat):
try:
self.__ShowStatToolTip(self.STAT_DESCRIPTION[stat])
except KeyError:
pass
def __OverOutStatButton(self):
self.__HideStatToolTip()
def __ShowStatToolTip(self, statDesc):
self.toolTip.ClearToolTip()
self.toolTip.AppendTextLine(statDesc)
self.toolTip.Show()
def __HideStatToolTip(self):
self.toolTip.Hide()
def OnPressEscapeKey(self):
self.Close()
return True
def OnUpdate(self):
self.__UpdateQuestClock()
## Skill Process
def __RefreshSkillPage(self, name, slotCount):
global SHOW_LIMIT_SUPPORT_SKILL_LIST
skillPage = self.skillPageDict[name]
startSlotIndex = skillPage.GetStartIndex()
if "ACTIVE" == name:
if self.PAGE_HORSE == self.curSelectedSkillGroup:
startSlotIndex += slotCount
getSkillType = skill.GetSkillType
getSkillIndex = player.GetSkillIndex
getSkillGrade = player.GetSkillGrade
getSkillLevel = player.GetSkillLevel
getSkillLevelUpPoint = skill.GetSkillLevelUpPoint
getSkillMaxLevel = skill.GetSkillMaxLevel
for i in range(slotCount + 1):
slotIndex = i + startSlotIndex
skillIndex = getSkillIndex(slotIndex)
for j in range(skill.SKILL_GRADE_COUNT):
skillPage.ClearSlot(self.__GetRealSkillSlot(j, i))
if 0 == skillIndex:
continue
skillGrade = getSkillGrade(slotIndex)
skillLevel = getSkillLevel(slotIndex)
skillType = getSkillType(skillIndex)
## Horse riding skill exception handling
if player.SKILL_INDEX_RIDING == skillIndex:
if 1 == skillGrade:
skillLevel += 19
elif 2 == skillGrade:
skillLevel += 29
elif 3 == skillGrade:
skillLevel = 40
skillPage.SetSkillSlotNew(slotIndex, skillIndex, max(skillLevel - 1, 0), skillLevel)
skillPage.SetSlotCount(slotIndex, skillLevel)
## ACTIVE
elif skill.SKILL_TYPE_ACTIVE == skillType:
for j in range(skill.SKILL_GRADE_COUNT):
realSlotIndex = self.__GetRealSkillSlot(j, slotIndex)
skillPage.SetSkillSlotNew(realSlotIndex, skillIndex, j, skillLevel)
skillPage.SetCoverButton(realSlotIndex)
if (skillGrade == skill.SKILL_GRADE_COUNT) and j == (skill.SKILL_GRADE_COUNT - 1):
skillPage.SetSlotCountNew(realSlotIndex, skillGrade, skillLevel)
elif (not self.__CanUseSkillNow()) or (skillGrade != j):
skillPage.SetSlotCount(realSlotIndex, 0)
skillPage.DisableCoverButton(realSlotIndex)
if not player.IsSkillActive(slotIndex):
skillPage.DeactivateSlot(realSlotIndex)
if player.IsSkillCoolTime(slotIndex) and skillGrade != j:
skillPage.TransferSlotCoolTime(realSlotIndex, self.__GetRealSkillSlot(skillGrade, i))
else:
self.SkillClearCoolTime(realSlotIndex)
else:
skillPage.SetSlotCountNew(realSlotIndex, skillGrade, skillLevel)
# Check if this is the active slot
# Grade 3 appears in slot 2, so check both conditions
isActiveSlot = (skillGrade == j) or ((skillGrade == skill.SKILL_GRADE_COUNT) and j == (skill.SKILL_GRADE_COUNT - 1))
if player.IsSkillActive(slotIndex) and isActiveSlot:
skillPage.ActivateSlot(realSlotIndex)
else:
skillPage.DeactivateSlot(realSlotIndex)
else:
if not SHOW_LIMIT_SUPPORT_SKILL_LIST or skillIndex in SHOW_LIMIT_SUPPORT_SKILL_LIST:
realSlotIndex = self.__GetETCSkillRealSlotIndex(slotIndex)
skillPage.SetSkillSlot(realSlotIndex, skillIndex, skillLevel)
skillPage.SetSlotCountNew(realSlotIndex, skillGrade, skillLevel)
if skill.CanUseSkill(skillIndex):
skillPage.SetCoverButton(realSlotIndex)
# Clear storage for horse skills at level 0 BEFORE restore runs
if skillType == skill.SKILL_TYPE_HORSE and skillLevel == 0:
player.ResetHorseSkillCoolTime(skillIndex, realSlotIndex)
skillPage.SetSlotCoolTime(realSlotIndex, 0)
if player.IsSkillActive(slotIndex):
skillPage.ActivateSlot(realSlotIndex)
else:
skillPage.DeactivateSlot(realSlotIndex)
skillPage.RefreshSlot()
self.__RestoreSlotCoolTime(skillPage)
def __RestoreSlotCoolTime(self, skillPage):
restoreType = skill.SKILL_TYPE_NONE
if self.PAGE_HORSE == self.curSelectedSkillGroup:
restoreType = skill.SKILL_TYPE_HORSE
else:
restoreType = skill.SKILL_TYPE_ACTIVE
skillPage.RestoreSlotCoolTime(restoreType)
def __ClearHorseSkillQuickSlots(self):
HORSE_SKILL_SET = (137, 138, 139, 140)
quick_slot_per_page = 8 # two quick_slot windows * 4 slots
quick_page_count = 4 # matches QUICKPAGE_NUMBER_FILENAME
current_page = player.GetQuickPage()
for page in range(quick_page_count):
player.SetQuickPage(page)
for local_slot in range(quick_slot_per_page):
slotType, position = player.GetLocalQuickSlot(local_slot)
if slotType != player.SLOT_TYPE_SKILL:
continue
skillIndex = player.GetSkillIndex(position)
if skillIndex in HORSE_SKILL_SET:
player.RequestDeleteGlobalQuickSlot(page * quick_slot_per_page + local_slot)
player.SetQuickPage(current_page)
def RefreshSkill(self):
if self.isLoaded == 0:
return
if self.__IsChangedHorseRidingSkillLevel():
if not self.__CanUseHorseSkill():
if self.curSelectedSkillGroup == self.PAGE_HORSE:
self.__SelectSkillGroup(0) # fall back to first active tab
self.__ClearHorseSkillQuickSlots() # remove horse skills from taskbar
self.RefreshCharacter()
return
global SHOW_ONLY_ACTIVE_SKILL
if SHOW_ONLY_ACTIVE_SKILL:
self.__RefreshSkillPage("ACTIVE", self.ACTIVE_PAGE_SLOT_COUNT)
else:
self.__RefreshSkillPage("ACTIVE", self.ACTIVE_PAGE_SLOT_COUNT)
self.__RefreshSkillPage("SUPPORT", self.SUPPORT_PAGE_SLOT_COUNT)
self.RefreshSkillPlusButtonList()
def CanShowPlusButton(self, skillIndex, skillLevel, curStatPoint):
## Check if skill exists
if 0 == skillIndex:
return False
## Check if skill can be leveled up
if not skill.CanLevelUpSkill(skillIndex, skillLevel):
return False
return True
def __RefreshSkillPlusButton(self, name):
global HIDE_SUPPORT_SKILL_POINT
if HIDE_SUPPORT_SKILL_POINT and "SUPPORT" == name:
return
slotWindow = self.skillPageDict[name]
slotWindow.HideAllSlotButton()
slotStatType = self.skillPageStatDict[name]
if 0 == slotStatType:
return
statPoint = player.GetStatus(slotStatType)
startSlotIndex = slotWindow.GetStartIndex()
if "HORSE" == name:
startSlotIndex += self.ACTIVE_PAGE_SLOT_COUNT
if statPoint > 0:
for i in range(self.PAGE_SLOT_COUNT):
slotIndex = i + startSlotIndex
skillIndex = player.GetSkillIndex(slotIndex)
skillGrade = player.GetSkillGrade(slotIndex)
skillLevel = player.GetSkillLevel(slotIndex)
if skillIndex == 0:
continue
if skillGrade != 0:
continue
if name == "HORSE":
if player.GetStatus(player.LEVEL) >= skill.GetSkillLevelLimit(skillIndex):
if skillLevel < 20:
slotWindow.ShowSlotButton(self.__GetETCSkillRealSlotIndex(slotIndex))
else:
if "SUPPORT" == name:
if not SHOW_LIMIT_SUPPORT_SKILL_LIST or skillIndex in SHOW_LIMIT_SUPPORT_SKILL_LIST:
if self.CanShowPlusButton(skillIndex, skillLevel, statPoint):
slotWindow.ShowSlotButton(slotIndex)
else:
if self.CanShowPlusButton(skillIndex, skillLevel, statPoint):
slotWindow.ShowSlotButton(slotIndex)
def RefreshSkillPlusButtonList(self):
if self.isLoaded==0:
return
self.RefreshSkillPlusPointLabel()
if not self.__CanUseSkillNow():
return
try:
if self.PAGE_HORSE == self.curSelectedSkillGroup:
self.__RefreshSkillPlusButton("HORSE")
else:
self.__RefreshSkillPlusButton("ACTIVE")
self.__RefreshSkillPlusButton("SUPPORT")
except:
import exception
exception.Abort("CharacterWindow.RefreshSkillPlusButtonList.BindObject")
def RefreshSkillPlusPointLabel(self):
if self.isLoaded==0:
return
if self.PAGE_HORSE == self.curSelectedSkillGroup:
activeStatPoint = player.GetStatus(player.SKILL_HORSE)
self.activeSkillPointValue.SetText(str(activeStatPoint))
else:
activeStatPoint = player.GetStatus(player.SKILL_ACTIVE)
self.activeSkillPointValue.SetText(str(activeStatPoint))
supportStatPoint = max(0, player.GetStatus(player.SKILL_SUPPORT))
self.supportSkillPointValue.SetText(str(supportStatPoint))
## Skill Level Up Button
def OnPressedSlotButton(self, slotNumber):
srcSlotIndex = self.__RealSkillSlotToSourceSlot(slotNumber)
skillIndex = player.GetSkillIndex(srcSlotIndex)
curLevel = player.GetSkillLevel(srcSlotIndex)
maxLevel = skill.GetSkillMaxLevel(skillIndex)
net.SendChatPacket("/skillup " + str(skillIndex))
## Use Skill
def ClickSkillSlot(self, slotIndex):
srcSlotIndex = self.__RealSkillSlotToSourceSlot(slotIndex)
skillIndex = player.GetSkillIndex(srcSlotIndex)
skillType = skill.GetSkillType(skillIndex)
if not self.__CanUseSkillNow():
if skill.SKILL_TYPE_ACTIVE == skillType:
return
for slotWindow in list(self.skillPageDict.values()):
if slotWindow.HasSlot(slotIndex):
if skill.CanUseSkill(skillIndex):
player.ClickSkillSlot(srcSlotIndex)
return
mouseModule.mouseController.DeattachObject()
## FIXME: When using a skill, find and update the slot by slot number.
## Very inefficient. The structure itself needs improvement.
def OnUseSkill(self, slotIndex, coolTime):
skillIndex = player.GetSkillIndex(slotIndex)
skillType = skill.GetSkillType(skillIndex)
## ACTIVE
if skill.SKILL_TYPE_ACTIVE == skillType:
skillGrade = player.GetSkillGrade(slotIndex)
slotIndex = self.__GetRealSkillSlot(skillGrade, slotIndex)
## ETC
else:
slotIndex = self.__GetETCSkillRealSlotIndex(slotIndex)
for slotWindow in list(self.skillPageDict.values()):
if slotWindow.HasSlot(slotIndex):
slotWindow.StoreSlotCoolTime(skillType, slotIndex, coolTime)
self.__RestoreSlotCoolTime(slotWindow)
return
def OnActivateSkill(self, slotIndex):
skillIndex = player.GetSkillIndex(slotIndex)
skillType = skill.GetSkillType(skillIndex)
## ACTIVE
if skill.SKILL_TYPE_ACTIVE == skillType:
skillGrade = player.GetSkillGrade(slotIndex)
slotIndex = self.__GetRealSkillSlot(skillGrade, slotIndex)
## ETC
else:
slotIndex = self.__GetETCSkillRealSlotIndex(slotIndex)
for slotWindow in list(self.skillPageDict.values()):
if slotWindow.HasSlot(slotIndex):
slotWindow.ActivateSlot(slotIndex)
return
def OnDeactivateSkill(self, slotIndex):
skillIndex = player.GetSkillIndex(slotIndex)
skillType = skill.GetSkillType(skillIndex)
## ACTIVE
if skill.SKILL_TYPE_ACTIVE == skillType:
skillGrade = player.GetSkillGrade(slotIndex)
slotIndex = self.__GetRealSkillSlot(skillGrade, slotIndex)
## ETC
else:
slotIndex = self.__GetETCSkillRealSlotIndex(slotIndex)
for slotWindow in list(self.skillPageDict.values()):
if slotWindow.HasSlot(slotIndex):
slotWindow.DeactivateSlot(slotIndex)
return
def __ShowJobToolTip(self):
self.toolTipJob.ShowToolTip()
def SkillClearCoolTime(self, slotIndex):
skillIndex = player.GetSkillIndex(slotIndex)
if skillIndex < 1:
return
skillType = skill.GetSkillType(skillIndex)
## ACTIVE
# Map to the correct visual slot based on skill type
if skill.SKILL_TYPE_ACTIVE == skillType:
slotIndex = self.__GetRealSkillSlot(player.GetSkillGrade(slotIndex), slotIndex)
else:
slotIndex = self.__GetETCSkillRealSlotIndex(slotIndex)
for slotWindow in list(self.skillPageDict.values()):
if slotWindow.HasSlot(slotIndex):
slotWindow.SetSlotCoolTime(slotIndex, 0)
def __HideJobToolTip(self):
self.toolTipJob.HideToolTip()
def __SetJobText(self, mainJob, subJob):
if player.GetStatus(player.LEVEL)<5:
subJob=0
def __ShowAlignmentToolTip(self):
self.toolTipAlignment.ShowToolTip()
def __HideAlignmentToolTip(self):
self.toolTipAlignment.HideToolTip()
def RefreshCharacter(self):
if self.isLoaded==0:
return
## Name
try:
characterName = player.GetName()
guildName = player.GetGuildName()
self.characterNameValue.SetText(characterName)
self.guildNameValue.SetText(guildName)
if not guildName:
if app.IsRTL():
self.characterNameSlot.SetPosition(190, 34)
else:
self.characterNameSlot.SetPosition(109, 34)
self.guildNameSlot.Hide()
else:
self.characterNameSlot.SetPosition(153, 34)
self.guildNameSlot.Show()
except:
import exception
exception.Abort("CharacterWindow.RefreshCharacter.BindObject")
race = net.GetMainActorRace()
group = net.GetMainActorSkillGroup()
empire = net.GetMainActorEmpire()
## Job Text
job = chr.RaceToJob(race)
self.__SetJobText(job, group)
## FaceImage
try:
faceImageName = FACE_IMAGE_DICT[race]
try:
self.faceImage.LoadImage(faceImageName)
except:
print(("CharacterWindow.RefreshCharacter(race=%d, faceImageName=%s)" % (race, faceImageName)))
self.faceImage.Hide()
except KeyError:
self.faceImage.Hide()
## GroupName
self.__SetSkillGroupName(race, group)
self.__SetSkillSlotData(race, group, empire)
## Skill
if 0 == group:
self.__SelectSkillGroup(0)
else:
if self.__CanUseHorseSkill():
self.__SelectSkillGroup(0)
def __SetSkillGroupName(self, race, group):
job = chr.RaceToJob(race)
if job not in self.SKILL_GROUP_NAME_DICT:
return
nameList = self.SKILL_GROUP_NAME_DICT[job]
if 0 == group:
self.skillGroupButton1.SetText(nameList[1])
self.skillGroupButton2.SetText(nameList[2])
if self.__CanUseHorseSkill():
self.skillGroupButton3.SetText(localeInfo.SKILL_GROUP_HORSE)
self.skillGroupButton3.Show()
self.skillGroupButton3.SetPosition(95, 2)
else:
self.skillGroupButton3.Hide()
self.skillGroupButton1.Show()
self.skillGroupButton2.Show()
self.activeSkillGroupName.Hide()
else:
if self.__CanUseHorseSkill():
self.activeSkillGroupName.Hide()
self.skillGroupButton1.SetText(nameList.get(group, "Noname"))
self.skillGroupButton3.SetText(localeInfo.SKILL_GROUP_HORSE)
self.skillGroupButton1.Show()
self.skillGroupButton2.Hide()
self.skillGroupButton3.Show()
self.skillGroupButton3.SetPosition(50, 2)
else:
self.activeSkillGroupName.SetText(nameList.get(group, "Noname"))
self.activeSkillGroupName.Show()
self.skillGroupButton1.Hide()
self.skillGroupButton2.Hide()
self.skillGroupButton3.Hide()
def __SetSkillSlotData(self, race, group, empire=0):
## SkillIndex
playerSettingModule.RegisterSkill(race, group, empire)
## Event
self.__SetSkillSlotEvent()
## Refresh
self.RefreshSkill()
def __SelectSkillGroup(self, pageIndex, xxx_todo_changeme = list(range(3))):
(PAGE_SKILL_1, PAGE_SKILL_2, PAGE_SKILL_HORSE) = xxx_todo_changeme
for pageButton in self.skillGroupButton:
pageButton.SetUp()
self.skillGroupButton[pageIndex].Down()
if pageIndex in (PAGE_SKILL_1, PAGE_SKILL_2):
skillGroupIndex = net.GetMainActorSkillGroup()
if bool(skillGroupIndex):
(tmpCurSkillGroup, tmpSkillGroup) = (skillGroupIndex - 1, skillGroupIndex)
else:
(tmpCurSkillGroup, tmpSkillGroup) = (pageIndex, pageIndex + 1)
self.curSelectedSkillGroup = tmpCurSkillGroup
self.__SetSkillSlotData(net.GetMainActorRace(), tmpSkillGroup, net.GetMainActorEmpire())
elif pageIndex == PAGE_SKILL_HORSE and self.__CanUseHorseSkill():
self.curSelectedSkillGroup = self.PAGE_HORSE
self.RefreshSkill()
def __CanUseSkillNow(self):
if 0 == net.GetMainActorSkillGroup():
return False
return True
def __CanUseHorseSkill(self):
slotIndex = player.GetSkillSlotIndex(player.SKILL_INDEX_RIDING)
if not slotIndex:
return False
grade = player.GetSkillGrade(slotIndex)
level = player.GetSkillLevel(slotIndex)
if level < 0:
level *= -1
# Map to UI-displayed riding level (matches __RefreshSkillPage logic)
# grade 1: base 1..20 shown as 20..39 (offset +19)
# grade 2: base 1..10 shown as 30..39 (offset +29)
# grade 3: shown as 40
effective = 0
if grade >= 3:
effective = 40
elif grade == 2:
effective = level + 29
elif grade == 1:
effective = level + 19
else:
effective = level
# Require displayed riding level >= 21 to enable the horse page
return effective >= 21
def __IsChangedHorseRidingSkillLevel(self):
ret = False
if -1 == self.canUseHorseSkill:
self.canUseHorseSkill = self.__CanUseHorseSkill()
if self.canUseHorseSkill != self.__CanUseHorseSkill():
ret = True
self.canUseHorseSkill = self.__CanUseHorseSkill()
return ret
def __GetRealSkillSlot(self, skillGrade, skillSlot):
return skillSlot + min(skill.SKILL_GRADE_COUNT-1, skillGrade)*skill.SKILL_GRADE_STEP_COUNT
def __GetETCSkillRealSlotIndex(self, skillSlot):
if skillSlot > 100:
return skillSlot
return skillSlot % self.ACTIVE_PAGE_SLOT_COUNT
def __RealSkillSlotToSourceSlot(self, realSkillSlot):
if realSkillSlot > 100:
return realSkillSlot
if self.PAGE_HORSE == self.curSelectedSkillGroup:
return realSkillSlot + self.ACTIVE_PAGE_SLOT_COUNT
return realSkillSlot % skill.SKILL_GRADE_STEP_COUNT
def __GetSkillGradeFromSlot(self, skillSlot):
return int(skillSlot // skill.SKILL_GRADE_STEP_COUNT)
def SelectSkillGroup(self, index):
self.__SelectSkillGroup(index)
def OnQuestScroll(self):
questCount = quest.GetQuestCount()
scrollLineCount = max(0, questCount - quest.QUEST_MAX_NUM)
startIndex = int(scrollLineCount * self.questScrollBar.GetPos())
if startIndex != self.questShowingStartIndex:
self.questShowingStartIndex = startIndex
self.RefreshQuest()