hxp
2023-12-22 92abd0a6d6d4cfa02850da755884cb6917652b96
10046 【后端】创建角色(修改支持角色、头像、外形)
9个文件已修改
285 ■■■■■ 已修改文件
PySysDB/PySysDBG.h 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py 29 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/CoreServerGroup/GameServer/Script/Player/CreateRole.py 129 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 73 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py 3 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBG.h
@@ -10,6 +10,17 @@
    char        Numerical5;    //数据5
};
//创角表
struct    tagCreateRole
{
    BYTE        _RoleType;        // 角色
    BYTE        Job;        // ְҵ
    DWORD        Face;        // 默认头像
    DWORD        ModelMark;    // 默认外形
    list        CreateRoleMap;    // 创角地图坐标信息 [dataMapID,posX,posY]
};
//创角限制服务器配置表 #tagCreateRoleLimitServer
struct    tagCreateRoleLimitServer
PySysDB/PySysDBPY.h
@@ -21,6 +21,16 @@
    list        StarAttrValue;    //累计总属性值
};
//创角表
struct    tagCreateRole
{
    BYTE        _RoleType;        // 角色
    list        BaseAttrIDList;    // 角色基础属性ID
    list        BaseAttrValueList;    // 角色基础属性值
    list        CreateRoleMap;    // 创角地图坐标信息 [dataMapID,posX,posY]
};
//灵根表 #tagRolePoint
struct    tagRolePoint
ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -29521,7 +29521,7 @@
class  tagRefreshType(Structure):
    _pack_ = 1
    _fields_ = [
                  ("RefreshType", c_ubyte),
                  ("RefreshType", c_ushort),
                  ("Value", c_int),    
                  ("ValueEx", c_int),    
                  ]
ServerPython/CoreServerGroup/GameServer/Script/IpyGameDataPY.py
@@ -41,6 +41,14 @@
                        ("char", "Numerical5", 0),
                        ),
                "CreateRole":(
                        ("BYTE", "RoleType", 1),
                        ("BYTE", "Job", 0),
                        ("DWORD", "Face", 0),
                        ("DWORD", "ModelMark", 0),
                        ("list", "CreateRoleMap", 0),
                        ),
                "CreateRoleLimitServer":(
                        ("list", "LimitServerGroupIDRangeList", 0),
                        ("list", "LimitServerGroupIDList", 0),
@@ -960,6 +968,23 @@
    def GetNumerical3(self): return self.Numerical3 # 数据3
    def GetNumerical4(self): return self.Numerical4 # 数据4
    def GetNumerical5(self): return self.Numerical5 # 数据5
# 创角表
class IPY_CreateRole():
    def __init__(self):
        self.RoleType = 0
        self.Job = 0
        self.Face = 0
        self.ModelMark = 0
        self.CreateRoleMap = []
        return
    def GetRoleType(self): return self.RoleType #  角色
    def GetJob(self): return self.Job #  ְҵ
    def GetFace(self): return self.Face #  默认头像
    def GetModelMark(self): return self.ModelMark #  默认外形
    def GetCreateRoleMap(self): return self.CreateRoleMap #  创角地图坐标信息 [dataMapID,posX,posY]
# 创角限制服务器配置表
class IPY_CreateRoleLimitServer():
@@ -2871,6 +2896,8 @@
        self.ipyConfigEx = {}
        self.ipyFuncConfigCache = self.__LoadFileData("FuncConfig", IPY_FuncConfig)
        self.ipyFuncConfigLen = len(self.ipyFuncConfigCache)
        self.ipyCreateRoleCache = self.__LoadFileData("CreateRole", IPY_CreateRole)
        self.ipyCreateRoleLen = len(self.ipyCreateRoleCache)
        self.ipyCreateRoleLimitServerCache = self.__LoadFileData("CreateRoleLimitServer", IPY_CreateRoleLimitServer)
        self.ipyCreateRoleLimitServerLen = len(self.ipyCreateRoleLimitServerCache)
        self.ipyWorldLVCache = self.__LoadFileData("WorldLV", IPY_WorldLV)
@@ -3211,6 +3238,8 @@
    
    def GetFuncConfigCount(self): return self.ipyFuncConfigLen
    def GetFuncConfigByIndex(self, index): return self.ipyFuncConfigCache[index]
    def GetCreateRoleCount(self): return self.ipyCreateRoleLen
    def GetCreateRoleByIndex(self, index): return self.ipyCreateRoleCache[index]
    def GetCreateRoleLimitServerCount(self): return self.ipyCreateRoleLimitServerLen
    def GetCreateRoleLimitServerByIndex(self, index): return self.ipyCreateRoleLimitServerCache[index]
    def GetWorldLVCount(self): return self.ipyWorldLVLen
ServerPython/CoreServerGroup/GameServer/Script/Player/CreateRole.py
@@ -27,7 +27,6 @@
import GameWorld
import random
import ChConfig
import ShareDefine
import PlayerControl
import PyGameData
#---------------------------------------------------------------------
@@ -116,18 +115,25 @@
    sendPack_Sex = 1 #sendPack.GetSex()
    sendPack_Hair = 10001 #sendPack.GetHair()
    sendPack_HairColor = 1 #sendPack.GetHairColor()
    sendPack_Face = 10005 #sendPack.GetFace()
    #sendPack_Face = 10005 #sendPack.GetFace()
    sendPack_FacePic = 0 # 固定为0,需与客户端配置一致
    serverID = 1 #sendPack.GetFacePic() # 脸谱作为serverID用
    sendPack_PlayerType = 1 #sendPack.GetPlayerType()
    sendPack_Job = sendPack.GetJob()
    roleType = sendPack.GetJob() # 创角使用job作为角色用
    ipyData = IpyGameDataPY.GetIpyGameData("CreateRole", roleType)
    if not ipyData:
        return
    job = ipyData.GetJob()
    face = ipyData.GetFace() # 头像
    modelMark = ipyData.GetModelMark() # 外形  和 时装有区别
    #-----------------------名字校验
    sendPack_Name = IpyGameDataPY.GetFuncCfg("CreateRole", 1) # 将命名格式直接传给db创角 gstCreatePlayer,因为这里的curPlayerID不是实际的curPlayerID
    if not sendPack_Name:
        return
    #C++过滤空格
    #sendPack_Name = GameWorld.GetGameWorld().GetCharTrim(sendPack_Name)
    
    GameWorld.Log("playerName = %s 创建角色,sendPack_Job=%s"%(sendPack_Name, sendPack_Job) , curPlayerID)
    GameWorld.Log("创建角色: accID=%s,roleType=%s,job=%s,face=%s,modelMark=%s, name=%s" % (accID, roleType, job, face, modelMark, sendPack_Name) , curPlayerID)
    
    #if not CheckPlayerName(curPlayer , sendPack_Name):
    #    #disRoleCreateError 人物创建的时候外观属性错误
@@ -150,7 +156,7 @@
    
    #---------------------职业检查
    openJob = IpyGameDataPY.GetFuncEvalCfg("OpenJob", 1)
    if sendPack_Job not in openJob:
    if job not in openJob:
        #curPlayer.Kick(IPY_GameServer.disCreateRoleJobError)
        PlayerControl.NotifyCode(curPlayer, "CreatUnusual")
        return
@@ -178,10 +184,10 @@
    #    return
    #===========================================================================
    
    createMapInfo = __GetCreateRoleMapInfo(sendPack_Job)
    createMapInfo = __GetCreateRoleMapInfo(ipyData.GetCreateRoleMap())
    if not createMapInfo:
        PlayerControl.NotifyCode(curPlayer, "CreatUnusual")
        GameWorld.ErrLog("没有职业对应创角地图信息:sendPack_Job=%s" % sendPack_Job, curPlayerID)
        GameWorld.ErrLog("没有职业对应创角地图信息:sendPack_Job=%s" % job, curPlayerID)
        return
    dataMapID, lineID, posX, posY = createMapInfo
    mapID, copyMapID = PyGameData.g_commMapLineInfo.get((dataMapID, lineID), (dataMapID, 0))
@@ -196,52 +202,54 @@
    baseSTR, basePNE, basePHY, baseCON = 0, 0, 0, 0
    
    curPlayer.SendToDBPlayerCreate(
                                    curPlayerID,                    #PlayerID,
                                    sendPack_Name,                  #PlayerName, //size = 14
                                    1,                              #inputAccState,        //0: 未创建, 1: 创建OK,正常登录 2:封号 3:已删除
                                    0,                              #inputGMLevel   //GM等级, 0:不是GM  >=1 : GM的等级
                                    sendPack_Sex,                   #Sex, //性别
                                    sendPack_Hair,                  #Hair, //发型, 1.标准型(男) 2.名仕型 3.浪子型 4.标准型(女) 5.马髻型 6.妩媚型
                                    sendPack_HairColor,             #HairColor, //头发颜色, 5种
                                    sendPack_Face,                  #Face, //基本脸型
                                    sendPack_FacePic,               #脸部图片
                                    sendPack_Job,                   #Job, //ְҵ
                                    1,                              #LV, //等级
                                    0,                              #TotalExp, //总经验
                                    0,                              #FamilyID, //家族
                                    1,                              #Country, //国家, 1.秦国(新手) 2.魏国 3.楚国   阵营
                                    0,                              #Mate,
                                    0,                              #Gold, //金子
                                    0,                              #Silver, //银子
                                    0,                              #金票
                                    0,                              #银票
                                    0,                              #FightPoint, //战斗值
                                    0,                              #HappyPoint, //娱乐值
                                    mapID,                          #MapID, //角色所在地图
                                    dataMapID,                      #DataMapID, //地图分线ID
                                    copyMapID,                      #CopyMapID, //副本地图ID
                                    posX,                           #PosX, //角色坐标
                                    posY,                           #PosY,
                                    0,                              #State, //角色状态   1.封存 2.死亡 3.正常  以后还有陆续添加
                                    100,                            #HP, //当前HP
                                    100,                            #MP, //当前MP
                                    0,                              #FreePoint, //未分配点数
                                    0,                              #FreeSkillPoint,//未分配技能点数
                                    baseSTR,                        #STR, //力量
                                    basePNE,                        #PNE, //智力
                                    basePHY,                        #PHY, //敏捷
                                    baseCON,                        #CON, //体力
                                    "",                             #Setting, //用户设定
                                    0,                              #PKValue, //PKֵ
                                    0,                              #ActiveValue, //击杀敌国阵营玩家和NPC的统计值
                                    sendPack_PlayerType,            #PlayerType, //角色的五行属性,组队用 1. 金 2. 木 3. 水 4. 土 5. 火
                                    "",                             #上次登录时间, 设置为空, 以便触发OnDay事件
                                    0,                              #是否使用仓库密码
                                    "111111",                       #仓库密码
                                    IPY_GameServer.TYPE_Price_Gold_Paper,   #默认使用金票     (金子/金票)
                                    curPlayerID, #PlayerID,
                                    sendPack_Name, #PlayerName, //size = 14
                                    1, #inputAccState,        //0: 未创建, 1: 创建OK,正常登录 2:封号 3:已删除
                                    0, #inputGMLevel   //GM等级, 0:不是GM  >=1 : GM的等级
                                    sendPack_Sex, #Sex, //性别
                                    sendPack_Hair, #Hair, //发型, 1.标准型(男) 2.名仕型 3.浪子型 4.标准型(女) 5.马髻型 6.妩媚型
                                    sendPack_HairColor, #HairColor, //头发颜色, 5种
                                    face, #Face, //基本脸型
                                    sendPack_FacePic, #脸部图片
                                    job, #Job, //ְҵ
                                    1, #LV, //等级
                                    0, #TotalExp, //总经验
                                    0, #FamilyID, //家族
                                    1, #Country, //国家, 1.秦国(新手) 2.魏国 3.楚国   阵营
                                    0, #Mate,
                                    0, #Gold, //金子
                                    0, #Silver, //银子
                                    0, #金票
                                    0, #银票
                                    0, #FightPoint, //战斗值
                                    0, #HappyPoint, //娱乐值
                                    mapID, #MapID, //角色所在地图
                                    dataMapID, #DataMapID, //地图分线ID
                                    copyMapID, #CopyMapID, //副本地图ID
                                    posX, #PosX, //角色坐标
                                    posY, #PosY,
                                    0, #State, //角色状态   1.封存 2.死亡 3.正常  以后还有陆续添加
                                    100, #HP, //当前HP
                                    100, #MP, //当前MP
                                    0, #FreePoint, //未分配点数
                                    0, #FreeSkillPoint,//未分配技能点数
                                    baseSTR, #STR, //力量
                                    basePNE, #PNE, //智力
                                    basePHY, #PHY, //敏捷
                                    baseCON, #CON, //体力
                                    "", #Setting, //用户设定
                                    0, #PKValue, //PKֵ
                                    0, #ActiveValue, //击杀敌国阵营玩家和NPC的统计值
                                    sendPack_PlayerType, #PlayerType, //角色的五行属性,组队用 1. 金 2. 木 3. 水 4. 土 5. 火
                                    "", #上次登录时间, 设置为空, 以便触发OnDay事件
                                    0, #是否使用仓库密码
                                    "111111", #仓库密码
                                    IPY_GameServer.TYPE_Price_Gold_Paper, #默认使用金票     (金子/金票)
                                    IPY_GameServer.TYPE_Price_Silver_Money, #默认使用银子     (银子/银票)
                                    80,                             #默认自动回血设定   inputHPRestoreSetting
                                    80                              #默认自动回魔设定   inputMPRestoreSetting
                                    80, #默认自动回血设定   inputHPRestoreSetting
                                    80, #默认自动回魔设定   inputMPRestoreSetting
                                    roleType,   #角色
                                    modelMark   #外观
                                    )
    
    # 创角流向
@@ -271,32 +279,27 @@
        return False
    
    if DirtyList.IsWordForbidden(playerName):
        GameWorld.Log('玩家创建角色失败, 名字不合法 = %s'%(playerName))
        GameWorld.Log('玩家创建角色失败, 名字不合法 = %s' % (playerName))
        return False
    
    playerNameLen = len(playerName)
    
    if playerNameLen < ChConfig.Def_CreatRole_MinStr:
        GameWorld.Log('玩家创建角色失败, 角色名字过短 = %s , %s < %s'%(playerName, playerNameLen, ChConfig.Def_CreatRole_MinStr))
        GameWorld.Log('玩家创建角色失败, 角色名字过短 = %s , %s < %s' % (playerName, playerNameLen, ChConfig.Def_CreatRole_MinStr))
        return False
    
    if playerNameLen > ChConfig.Def_CreatRole_MaxStr:
        GameWorld.Log('玩家创建角色失败, 角色名字过长 = %s , %s > %s'%(playerName, playerNameLen, ChConfig.Def_CreatRole_MaxStr))
        GameWorld.Log('玩家创建角色失败, 角色名字过长 = %s , %s > %s' % (playerName, playerNameLen, ChConfig.Def_CreatRole_MaxStr))
        return False
    
    return True
def __GetCreateRoleMapInfo(job):
def __GetCreateRoleMapInfo(createRoleMap):
    '''获取创角重生新手村地图
    @return: None
    @return: dataMapID, lineID, posX, posY
    '''
    createRoleMapDict = IpyGameDataPY.GetFuncEvalCfg("CreateRoleMap", 1) # {ְҵ:[dataMapID, posX,posY], ...}
    if job not in createRoleMapDict:
        return
    createRoleDataMapID, posX, posY = createRoleMapDict[job]
    createRoleDataMapID, posX, posY = createRoleMap
    mapShuntInfoDict = IpyGameDataPY.GetFuncEvalCfg("SetWorldPosShunt", 1) # 地图对应分流人数 {dataMapID:人数, ...}
    if createRoleDataMapID not in mapShuntInfoDict:
        return createRoleDataMapID, 0, posX, posY # 默认1线
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -29521,7 +29521,7 @@
class  tagRefreshType(Structure):
    _pack_ = 1
    _fields_ = [
                  ("RefreshType", c_ubyte),
                  ("RefreshType", c_ushort),
                  ("Value", c_int),    
                  ("ValueEx", c_int),    
                  ]
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -49,6 +49,13 @@
                        ("list", "StarAttrValue", 0),
                        ),
                "CreateRole":(
                        ("BYTE", "RoleType", 1),
                        ("list", "BaseAttrIDList", 0),
                        ("list", "BaseAttrValueList", 0),
                        ("list", "CreateRoleMap", 0),
                        ),
                "RolePoint":(
                        ("BYTE", "AttrID", 1),
                        ("dict", "AddAttrInfoPerPoint", 0),
@@ -2288,6 +2295,21 @@
    def GetStarUpNeedItemList(self): return self.StarUpNeedItemList # 升下一星所需道具 [[物品ID,个数], ...]
    def GetStarAttrType(self): return self.StarAttrType # 累计总属性类型
    def GetStarAttrValue(self): return self.StarAttrValue # 累计总属性值
# 创角表
class IPY_CreateRole():
    def __init__(self):
        self.RoleType = 0
        self.BaseAttrIDList = []
        self.BaseAttrValueList = []
        self.CreateRoleMap = []
        return
    def GetRoleType(self): return self.RoleType #  角色
    def GetBaseAttrIDList(self): return self.BaseAttrIDList #  角色基础属性ID
    def GetBaseAttrValueList(self): return self.BaseAttrValueList #  角色基础属性值
    def GetCreateRoleMap(self): return self.CreateRoleMap #  创角地图坐标信息 [dataMapID,posX,posY]
# 灵根表
class IPY_RolePoint():
@@ -6946,6 +6968,8 @@
        self.ipyDienstgradLen = len(self.ipyDienstgradCache)
        self.ipyTitleStarUpCache = self.__LoadFileData("TitleStarUp", IPY_TitleStarUp)
        self.ipyTitleStarUpLen = len(self.ipyTitleStarUpCache)
        self.ipyCreateRoleCache = self.__LoadFileData("CreateRole", IPY_CreateRole)
        self.ipyCreateRoleLen = len(self.ipyCreateRoleCache)
        self.ipyRolePointCache = self.__LoadFileData("RolePoint", IPY_RolePoint)
        self.ipyRolePointLen = len(self.ipyRolePointCache)
        self.ipyLingQiAttrCache = self.__LoadFileData("LingQiAttr", IPY_LingQiAttr)
@@ -7566,6 +7590,8 @@
    def GetDienstgradByIndex(self, index): return self.ipyDienstgradCache[index]
    def GetTitleStarUpCount(self): return self.ipyTitleStarUpLen
    def GetTitleStarUpByIndex(self, index): return self.ipyTitleStarUpCache[index]
    def GetCreateRoleCount(self): return self.ipyCreateRoleLen
    def GetCreateRoleByIndex(self, index): return self.ipyCreateRoleCache[index]
    def GetRolePointCount(self): return self.ipyRolePointLen
    def GetRolePointByIndex(self, index): return self.ipyRolePointCache[index]
    def GetLingQiAttrCount(self): return self.ipyLingQiAttrLen
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -129,7 +129,8 @@
def PlayerMoveCheckClientWorldTick(curPlayer, clientWorldTick, sendPack_PosX, sendPack_PosY):
    gameWorldTick = GameWorld.GetGameWorld().GetTick()
    Def_Max_Move_Tick = 5000
    if not curPlayer.GetSpeed():
        return False
    if abs(gameWorldTick - clientWorldTick) >= Def_Max_Move_Tick:
        curPlayer.Sync_ClientTick()
        #时间相差过大,可能因网络引起,拉回
@@ -1673,17 +1674,12 @@
        NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromMapID, 0)
        # 老号支持,本来就在中立地图的,返回新手村
        if not mapID:
            # {ְҵ:[dataMapID,posX,posY], ...}
            createRoleMapDict = IpyGameDataPY.GetFuncEvalCfg("CreateRoleMap", 1, {})
            if not createRoleMapDict:
            ipyData = IpyGameDataPY.GetIpyGameData("CreateRole", curPlayer.GetRoleType())
            if not ipyData:
                return
            job = curPlayer.GetJob()
            mapID, posX, posY = ipyData.GetCreateRoleMap()
            lineID = 0
            if job in createRoleMapDict:
                mapID, posX, posY = createRoleMapDict[job]
            else:
                mapInfoList = createRoleMapDict.values()
                mapID, posX, posY = mapInfoList[0]
    #离开副本
    else:
        fromFBMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FromFBMapID)
@@ -3911,10 +3907,7 @@
        LuckyHitRateTotal = curPlayer.GetLuckyHitRate()
        
        job = curPlayer.GetJob()
        diffAttrDict = self.__GetAttrFightPowerParamDiff(job)
        for paramName, diffValue in diffAttrDict.items():
            exec("%s = max(0, %s - %s)" % (paramName, paramName, diffValue))
        #获取策划配置的表格
        FightpowerFormula = IpyGameDataPY.GetFuncCfg("FightpowerFormula")
        totalFightPower = eval(FormulaControl.GetCompileFormula("FightpowerFormula", FightpowerFormula))
@@ -3924,26 +3917,6 @@
            GameWorld.ErrLog("模块战力超过数值上限, MfpType=%s,fightPower=%s, %s" % (self.mfpType, totalFightPower, self.GetMFPAttrStr()))
            totalFightPower = ShareDefine.Def_UpperLimit_DWord
        return totalFightPower
    def __GetAttrFightPowerParamDiff(self, job):
        ## 战力计算属性参数与实际属性差值
        #角色基础模块某些属性不计算战力
        if self.mfpType != ShareDefine.Def_MFPType_Role:
            return {}
        roleBaseAttrDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 1)
        notFightPowerEffIDNameDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 2)
        if job not in roleBaseAttrDict:
            return {}
        diffAttrDict = {}
        jobBaseAttrDict = roleBaseAttrDict[job]
        for attrID, paramName in notFightPowerEffIDNameDict.items():
            if attrID not in jobBaseAttrDict:
                continue
            diffAttrDict[paramName] = jobBaseAttrDict[attrID]
        return diffAttrDict
    
    def GetMFPAttrStr(self):
        attrStr = ""
@@ -4387,31 +4360,21 @@
    def CalcRoleBaseAttr(self, curPlayer):
        # 计算玩家角色基础属性值
        
        curPlayerID = curPlayer.GetID()
        #curPlayerID = curPlayer.GetID()
        job = curPlayer.GetJob()
        lvAttrDict = IpyGameDataPY.GetFuncEvalCfg("LVUPAttr%s" % job, 1)
        if not lvAttrDict:
            GameWorld.ErrLog('无此职业等级刷属性配置!job=%s' % (job), curPlayerID)
        roleType = curPlayer.GetRoleType()
        ipyData = IpyGameDataPY.GetIpyGameData("CreateRole", roleType)
        if not ipyData:
            return
        baseAttrIDList = ipyData.GetBaseAttrIDList()
        baseAttrValueList = ipyData.GetBaseAttrValueList()
        allAttrList = [{} for _ in range(4)]
        
        # 职业初始属性
        roleBaseAttrDict = IpyGameDataPY.GetFuncEvalCfg("CreatRoleBaseAttr", 1)
        if job in roleBaseAttrDict:
            for roleBaseAttrID, value in roleBaseAttrDict[job].items():
                CalcAttrDict_Type(roleBaseAttrID, value, allAttrList)
        #GameWorld.DebugLog("初始加属性: %s" % allAttrList)
        # 等级成长属性
        LV = curPlayer.GetLV()
        for lvAttrID, formula in lvAttrDict.items():
            calcValue = eval(FormulaControl.GetCompileFormula("LVUPAttr%s_%s" % (job, lvAttrID), formula))
            CalcAttrDict_Type(lvAttrID, calcValue, allAttrList)
            #GameWorld.DebugLog("    lvAttrID=%s,calcValue=%s" % (lvAttrID, calcValue))
        #GameWorld.DebugLog("等级加属性: %s" % allAttrList)
        # 初始属性
        if baseAttrIDList and baseAttrValueList and len(baseAttrIDList) == len(baseAttrValueList):
            for i, attrID in enumerate(baseAttrIDList):
                CalcAttrDict_Type(attrID, baseAttrValueList[i], allAttrList)
        GameWorld.DebugLog("初始加属性: %s" % allAttrList)
        
        # 属性点属性
        hadRefreshAttr = curPlayer.GetDictByKey(ChConfig.Def_Player_HadRefreshAttr) # 本地图是否刷新过属性
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerViewCacheTube.py
@@ -166,6 +166,9 @@
    curPlayerPropDict["LV"] = curPlayer.GetLV()
    curPlayerPropDict["RealmLV"] = curPlayer.GetOfficialRank()
    curPlayerPropDict["Job"] = curPlayer.GetJob()
    curPlayerPropDict["RoleType"] = curPlayer.GetRoleType()
    curPlayerPropDict["Face"] = curPlayer.GetFace()
    curPlayerPropDict["ModelMark"] = curPlayer.GetModelMark()
    curPlayerPropDict["VIPLV"] = curPlayer.GetVIPLv()
    curPlayerPropDict["Name"] = curPlayer.GetPlayerName()
    curPlayerPropDict["FamilyID"] = curPlayer.GetFamilyID()