hxp
2025-10-20 d2350a9a6ec29bdd9fc2cb63cdc9e27b57bc9574
232 【付费内容】历练秘笈-服务端
9个文件已修改
2个文件已添加
361 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py 5 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py 64 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py 37 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 31 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py 138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
PySysDB/PySysDBPY.h
@@ -3088,7 +3088,7 @@
//祝福树
struct tagTreeLV
struct TreeLV
{
    BYTE        _TreeLV;    //仙树等级
    DWORD        LVUPNeedMoney;    //升到下一级所需货币数
@@ -3098,6 +3098,18 @@
    list        EquipColorRateList2;    //boss产出装备品质概率列表,[0品质万分率, 1品质万分率, ...]
};
//历练秘笈
struct LLMJ
{
    BYTE        _MJLV;    //秘笈等级
    DWORD        CostWarhammer;    //消耗战锤
    BYTE        ExpAddPer;    //经验加成比例,百分比
    DWORD        ExpExUpper;    //经验加成每日上限
    BYTE        DecomposeAddPer;    //分解加成比例,百分比
    DWORD        DecomposeExUpper;    //结晶加成每日上限
};
//淘金营地表
struct GoldRushCamp
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3909,6 +3909,11 @@
Def_PDict_TreeFreeTimeCnt = "TreeFreeTimeCnt" # 今日已领取免费减时次数,过天重置
Def_PDict_TreeFreeTimeLast = "TreeFreeTimeLast" # 今日上次领取免费减时时间戳,过天重置
#历练秘笈
Def_PDict_LLMJLVInfo = "LLMJLVInfo" # 秘笈等级,消耗战锤*100 + 秘笈等级
Def_PDict_LLMJExp = "LLMJExp" # 秘笈今日已额外获得经验
Def_PDict_LLMJDecompose = "LLMJDecompose" # 秘笈今日已额外获得分解货币
#任务,每个任务组有且仅有一个进行中的任务
Def_PDict_TaskIDLast = "TaskIDLast_%s" # 上一次完成的任务ID,参数(任务组)
Def_PDict_TaskID = "TaskID_%s" # 当前进行中的任务ID,参数(任务组)
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -35422,6 +35422,70 @@
#------------------------------------------------------
# B1 28 历练秘笈信息 #tagSCLLMJInfo
class  tagSCLLMJInfo(Structure):
    _pack_ = 1
    _fields_ = [
                  ("Cmd", c_ubyte),
                  ("SubCmd", c_ubyte),
                  ("MJLV", c_ubyte),    # 秘笈等级,激活后从1开始
                  ("Zhanchui", c_int),    # 秘笈累计消耗战锤
                  ("ExpEx", c_int),    # 秘笈今日已额外获得经验
                  ("DecomposeEx", c_int),    # 秘笈今日已额外获得分解货币
                  ]
    def __init__(self):
        self.Clear()
        self.Cmd = 0xB1
        self.SubCmd = 0x28
        return
    def ReadData(self, stringData, _pos=0, _len=0):
        self.Clear()
        memmove(addressof(self), stringData[_pos:], self.GetLength())
        return _pos + self.GetLength()
    def Clear(self):
        self.Cmd = 0xB1
        self.SubCmd = 0x28
        self.MJLV = 0
        self.Zhanchui = 0
        self.ExpEx = 0
        self.DecomposeEx = 0
        return
    def GetLength(self):
        return sizeof(tagSCLLMJInfo)
    def GetBuffer(self):
        return string_at(addressof(self), self.GetLength())
    def OutputString(self):
        DumpString = '''// B1 28 历练秘笈信息 //tagSCLLMJInfo:
                                Cmd:%s,
                                SubCmd:%s,
                                MJLV:%d,
                                Zhanchui:%d,
                                ExpEx:%d,
                                DecomposeEx:%d
                                '''\
                                %(
                                self.Cmd,
                                self.SubCmd,
                                self.MJLV,
                                self.Zhanchui,
                                self.ExpEx,
                                self.DecomposeEx
                                )
        return DumpString
m_NAtagSCLLMJInfo=tagSCLLMJInfo()
ChNetPackDict[eval("0x%02x%02x"%(m_NAtagSCLLMJInfo.Cmd,m_NAtagSCLLMJInfo.SubCmd))] = m_NAtagSCLLMJInfo
#------------------------------------------------------
# B1 19 形象信息 #tagSCModelInfo
class  tagSCModel(Structure):
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py
New file
@@ -0,0 +1,60 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GM.Commands.LLMJ
#
# @todo:历练秘笈
# @author hxp
# @date 2025-10-20
# @version 1.0
#
# 详细描述: 历练秘笈
#
#-------------------------------------------------------------------------------
#"""Version = 2025-10-20 15:00"""
#-------------------------------------------------------------------------------
import ChConfig
import PlayerControl
import IpyGameDataPY
import PlayerLLMJ
import GameWorld
def OnExec(curPlayer, cmdList):
    if not cmdList:
        GameWorld.DebugAnswer(curPlayer, "重置秘笈: LLMJ 0")
        GameWorld.DebugAnswer(curPlayer, "秘笈等级: LLMJ l 等级 [累计消耗战锤]")
        GameWorld.DebugAnswer(curPlayer, "今日累计: LLMJ d 累计额外经验 额外分解")
        return
    value1 = cmdList[0]
    if value1 == 0:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJLVInfo, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJExp, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJDecompose, 0)
        GameWorld.DebugAnswer(curPlayer, "重置历练秘笈")
    elif value1 == "l":
        mjLV = cmdList[1] if len(cmdList) > 1 else 0
        zhanchui = cmdList[2] if len(cmdList) > 2 else 0
        ipyData = IpyGameDataPY.GetIpyGameData("LLMJ", mjLV)
        if not ipyData:
            GameWorld.DebugAnswer(curPlayer, "历练秘笈等级不存在! %s" % mjLV)
            return
        zhanchui = max(ipyData.GetCostWarhammer(), zhanchui)
        PlayerLLMJ.SetMJLVInfo(curPlayer, mjLV, zhanchui)
        GameWorld.DebugAnswer(curPlayer, "历练秘笈等级:%s, 消耗战锤:%s" % (mjLV, zhanchui))
    elif value1 == "d":
        expEx = cmdList[1] if len(cmdList) > 1 else 0
        decomposeEx = cmdList[2] if len(cmdList) > 2 else 0
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJExp, expEx)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJDecompose, decomposeEx)
        GameWorld.DebugAnswer(curPlayer, "历练秘笈累计经验:%s, 分解:%s" % (expEx, decomposeEx))
    else:
        return
    PlayerLLMJ.SyncLLMJInfo(curPlayer)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
@@ -27,6 +27,7 @@
import IPY_GameWorld
import NetPackCommon
import PlayerArena
import PlayerLLMJ
import ItemCommon
import PlayerTask
import NPCCommon
@@ -87,10 +88,16 @@
    if unXiantaoCntExp:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntExp, 0)
        perExp = IpyGameDataPY.GetFuncCfg("Mainline", 1) # 每个战锤增加经验
        totalExp = unXiantaoCntExp * perExp
        GameWorld.DebugLog("增加经验: totalExp=%s,unXiantaoCntExp=%s" % (totalExp, unXiantaoCntExp))
        PlayerControl.PlayerControl(curPlayer).AddExp(totalExp, ShareDefine.Def_ViewExpType_KillNPC)
        baseExp = unXiantaoCntExp * perExp
        mjExPer, exRemain = PlayerLLMJ.GetAddExpPerInfo(curPlayer)
        mjEx = min(int(baseExp * mjExPer / 100.0), exRemain)
        totalExp = baseExp + mjEx
        GameWorld.DebugLog("增加经验: totalExp=%s,unXiantaoCntExp=%s,baseExp=%s,mjEx=%s,mjExPer=%s,exRemain=%s"
                           % (totalExp, unXiantaoCntExp, baseExp, mjEx, mjExPer, exRemain))
        finalAddExp = PlayerControl.PlayerControl(curPlayer).AddExp(totalExp, ShareDefine.Def_ViewExpType_KillNPC)
        if mjEx and finalAddExp:
            PlayerLLMJ.AddExpEx(curPlayer, mjEx)
    __doMainDrop(curPlayer, killObjList)
    return
@@ -450,14 +457,16 @@
    
    equipCnt = len(equipDict)
    unXiantaoCntEquip = PlayerControl.GetUnXiantaoCntEquip(curPlayer)
    perEquipXiantao = unXiantaoCntEquip / float(equipCnt) if equipCnt > 1 else unXiantaoCntEquip
    perEquipXiantao = unXiantaoCntEquip / float(equipCnt) if equipCnt > 1 else unXiantaoCntEquip # 均分支持小数
    decomposeMoney = max(1, moneyBase * perEquipXiantao) # 至少1个
    mjExPer, exRemain = PlayerLLMJ.GetAddDecomposePer(curPlayer)
    mjEx = int(decomposeMoney * mjExPer / 100.0)
    GameWorld.DebugLog("unXiantaoCntEquip=%s,equipCnt=%s,perEquipXiantao=%s,equipIndexList=%s" 
                       % (unXiantaoCntEquip, equipCnt, perEquipXiantao, equipDict.keys()), playerID)
    GameWorld.DebugLog("moneyBase=%s,decomposeMoney=%s" % (moneyBase, decomposeMoney), playerID)
    GameWorld.DebugLog("moneyBase=%s,decomposeMoney=%s,mjExPer=%s,exRemain=%s,mjEx=%s" % (moneyBase, decomposeMoney, mjExPer, exRemain, mjEx), playerID)
    
    moneyTotal = 0
    mjExTotal = 0
    decomposeCnt = 0
    decomposeIndexList = []
    for itemIndex in itemIndexList:
@@ -466,8 +475,13 @@
        curEquip = equipDict[itemIndex]
        
        moneyTotal += decomposeMoney
        GameWorld.DebugLog("    itemIndex=%s,moneyBase=%s,perEquipXiantao=%s,decomposeMoney=%s,总:%s"
                           % (itemIndex, moneyBase, perEquipXiantao, decomposeMoney, moneyTotal), playerID)
        if mjEx > 0:
            mjEx = min(mjEx, exRemain)
            exRemain -= mjEx
            moneyTotal += mjEx
            mjExTotal += mjEx
        GameWorld.DebugLog("    itemIndex=%s,moneyBase=%s,perEquipXiantao=%s,decomposeMoney=%s,mjEx=%s,exRemain=%s,总:%s"
                           % (itemIndex, moneyBase, perEquipXiantao, decomposeMoney, mjEx, exRemain, moneyTotal), playerID)
        
        ItemCommon.DelItem(curPlayer, curEquip, curEquip.GetCount(), True, ChConfig.ItemDel_EquipDecompose)
        decomposeIndexList.append(itemIndex)
@@ -479,9 +493,10 @@
    
    moneyTotal = int(round(moneyTotal)) # 四舍五入取整
    unXiantaoCntEquip = PlayerControl.SetUnXiantaoCntEquip(curPlayer, unXiantaoCntEquip)
    GameWorld.DebugLog("moneyTotal=%s,unXiantaoCntEquip=%s" % (moneyTotal, unXiantaoCntEquip), playerID)
    GameWorld.DebugLog("moneyTotal=%s,mjExTotal=%s,unXiantaoCntEquip=%s" % (moneyTotal, mjExTotal, unXiantaoCntEquip), playerID)
    PlayerControl.GiveMoney(curPlayer, moneyType, moneyTotal, "DecomposeMainEquip", isSysHint=False)
    PlayerLLMJ.AddExpDecompose(curPlayer, mjExTotal)
    PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_EquipDecompose, decomposeCnt)
    PlayerActivity.AddDailyTaskValue(curPlayer, ChConfig.DailyTask_EquipDecompose, decomposeCnt)
    return
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -2421,6 +2421,15 @@
                        ("list", "EquipColorRateList2", 0),
                        ),
                "LLMJ":(
                        ("BYTE", "MJLV", 1),
                        ("DWORD", "CostWarhammer", 0),
                        ("BYTE", "ExpAddPer", 0),
                        ("DWORD", "ExpExUpper", 0),
                        ("BYTE", "DecomposeAddPer", 0),
                        ("DWORD", "DecomposeExUpper", 0),
                        ),
                "GoldRushCamp":(
                        ("BYTE", "CampID", 1),
                        ("WORD", "PanningUnlock", 0),
@@ -6046,6 +6055,20 @@
    def GetEquipColorRateList1(self): return self.attrTuple[4] # 精英产出装备品质概率列表,[0品质万分率, 1品质万分率, ...] list
    def GetEquipColorRateList2(self): return self.attrTuple[5] # boss产出装备品质概率列表,[0品质万分率, 1品质万分率, ...] list
# 历练秘笈
class IPY_LLMJ():
    def __init__(self):
        self.attrTuple = None
        return
    def GetMJLV(self): return self.attrTuple[0] # 秘笈等级 BYTE
    def GetCostWarhammer(self): return self.attrTuple[1] # 消耗战锤 DWORD
    def GetExpAddPer(self): return self.attrTuple[2] # 经验加成比例,百分比 BYTE
    def GetExpExUpper(self): return self.attrTuple[3] # 经验加成每日上限 DWORD
    def GetDecomposeAddPer(self): return self.attrTuple[4] # 分解加成比例,百分比 BYTE
    def GetDecomposeExUpper(self): return self.attrTuple[5] # 结晶加成每日上限 DWORD
# 淘金营地表
class IPY_GoldRushCamp():
    
@@ -6390,6 +6413,7 @@
        self.__LoadFileData("Xiangong", onlyCheck)
        self.__LoadFileData("TiandaoTree", onlyCheck)
        self.__LoadFileData("TreeLV", onlyCheck)
        self.__LoadFileData("LLMJ", onlyCheck)
        self.__LoadFileData("GoldRushCamp", onlyCheck)
        self.__LoadFileData("GoldRushWorker", onlyCheck)
        self.__LoadFileData("GoldRushItem", onlyCheck)
@@ -8306,6 +8330,13 @@
        self.CheckLoadData("TreeLV")
        return self.ipyTreeLVCache[index]
    def GetLLMJCount(self):
        self.CheckLoadData("LLMJ")
        return self.ipyLLMJLen
    def GetLLMJByIndex(self, index):
        self.CheckLoadData("LLMJ")
        return self.ipyLLMJCache[index]
    def GetGoldRushCampCount(self):
        self.CheckLoadData("GoldRushCamp")
        return self.ipyGoldRushCampLen
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -108,6 +108,7 @@
import PlayerCustomAward
import PlayerZhanling
import PlayerTree
import PlayerLLMJ
import PlayerLianTi
import PlayerTask
import PlayerYinji
@@ -746,6 +747,7 @@
        SyncADCntInfo(curPlayer)
        UpdatePlayerName.OnPlayerLogin(curPlayer)
        PlayerActivity.OnPlayerLogin(curPlayer)
        PlayerLLMJ.OnPlayerLogin(curPlayer)
        
        # 上线查询一次充值订单
        curPlayer.SendDBQueryRecharge()
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py
@@ -60,6 +60,7 @@
import PlayerTongTianLing
import PlayerZhanling
import PlayerGoldRush
import PlayerLLMJ
import ItemCommon
import PyGameData
import CommFunc
@@ -781,12 +782,13 @@
    #投资
    if ctgIpyData:
        ctgID = ctgIpyData.GetRecordID()
        PlayerActFamilyCTGAssist.OnPlayerCTG(curPlayer, ctgID)
        PlayerGoldInvest.InvestByCTG(curPlayer, ctgID)
        #PlayerActFamilyCTGAssist.OnPlayerCTG(curPlayer, ctgID)
        #PlayerGoldInvest.InvestByCTG(curPlayer, ctgID)
        PlayerGoldGift.OnGiftByCTGID(curPlayer, ctgID)
        PlayerZhanling.OnActiviteByCTGID(curPlayer, ctgID)
        PlayerGoldRush.OnGoldRushByCTGID(curPlayer, ctgID)
        PlayerTongTianLing.OnActiviteTTTByCTGID(curPlayer, ctgID)
        PlayerLLMJ.OnActiviteByCTGID(curPlayer, ctgID)
        
    serverDay = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ServerDay) + 1
    addDRDict.update({"gold":[goldBefore, goldAfter], "changeCoinPoint":[changeCoinPointBefore, changeCoinPointAfter], "todayCTGCoinTotal":todayCTGCoinTotal,
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -59,6 +59,7 @@
import PlayerOnline
import PlayerTask
import PlayerMail
import PlayerLLMJ
import ChPlayer
import GameObj
@@ -2798,6 +2799,7 @@
                unXiantaoCntBooty = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_UnXiantaoCntBooty % itemID)
                NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_UnXiantaoCntBooty % itemID, unXiantaoCntBooty + price)
                
        PlayerLLMJ.AddUseZhanchui(curPlayer, price)
        PlayerPrestigeSys.AddRealmTaskValue(curPlayer, PlayerPrestigeSys.RealmTaskType_UseXiantao, price)
        PlayerTask.AddTaskValue(curPlayer, ChConfig.TaskType_CutTree, price)
        
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -91,6 +91,7 @@
import PlayerMail
import PlayerHero
import PlayerTree
import PlayerLLMJ
import datetime
import time
@@ -278,6 +279,7 @@
        PlayerControl.PayCoinOnDay(curPlayer)
        ChPlayer.PlayerOnDay(curPlayer)
        PlayerActivity.OnDay(curPlayer)
        PlayerLLMJ.PlayerOnDay(curPlayer)
        
    # 特殊时间点X点过天
    elif onEventType == ShareDefine.Def_OnEventTypeEx:
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py
New file
@@ -0,0 +1,138 @@
#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package Player.PlayerLLMJ
#
# @todo:历练秘笈
# @author hxp
# @date 2025-10-20
# @version 1.0
#
# 详细描述: 历练秘笈
#
#-------------------------------------------------------------------------------
#"""Version = 2025-10-20 15:00"""
#-------------------------------------------------------------------------------
import ChConfig
import NetPackCommon
import IpyGameDataPY
import ChPyNetSendPack
import PlayerControl
import GameWorld
import ObjPool
def OnPlayerLogin(curPlayer):
    if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJLVInfo):
        return
    SyncLLMJInfo(curPlayer)
    return
def PlayerOnDay(curPlayer):
    if not curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJLVInfo):
        return
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJExp, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJDecompose, 0)
    SyncLLMJInfo(curPlayer)
    return
def SetMJLVInfo(curPlayer, mjLV, zhanchui):
    lvInfo = zhanchui * 100 + min(mjLV, 99)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJLVInfo, lvInfo)
    return
def GetMJLVInfo(curPlayer):
    lvInfo = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJLVInfo)
    mjLV = lvInfo % 100
    zhanchui = lvInfo / 100
    return mjLV, zhanchui
def OnActiviteByCTGID(curPlayer, ctgID):
    if ctgID != IpyGameDataPY.GetFuncCfg("LLMJ", 1):
        return
    if curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJLVInfo):
        # 防范重复激活
        return
    GameWorld.DebugLog("激活历练秘笈")
    SetMJLVInfo(curPlayer, 1, 0)
    SyncLLMJInfo(curPlayer)
    return
def AddUseZhanchui(curPlayer, addCnt):
    mjLV, zhanchui = GetMJLVInfo(curPlayer)
    if not mjLV:
        return
    nextIpyData = IpyGameDataPY.GetIpyGameDataNotLog("LLMJ", mjLV + 1)
    if not nextIpyData:
        #GameWorld.DebugLog("历练秘笈已满级不再累加战锤: mjLV=%s" % (mjLV))
        return
    updZhanchui = zhanchui + addCnt
    nextZhanchui = nextIpyData.GetCostWarhammer()
    GameWorld.DebugLog("累加历练秘笈战锤: mjLV=%s,addCnt=%s,updZhanchui=%s,nextZhanchui=%s" % (mjLV, addCnt, updZhanchui, nextZhanchui))
    while nextIpyData and updZhanchui >= nextZhanchui:
        mjLV += 1 # 升级
        nextIpyData = IpyGameDataPY.GetIpyGameDataNotLog("LLMJ", mjLV + 1)
        nextZhanchui = nextIpyData.GetCostWarhammer() if nextIpyData else 0
        GameWorld.DebugLog("历练秘笈升级: %s,nextZhanchui=%s" % (mjLV, nextZhanchui))
    SetMJLVInfo(curPlayer, mjLV, updZhanchui)
    SyncLLMJInfo(curPlayer)
    return
def GetAddExpPerInfo(curPlayer):
    ## 获取额外经验比例信息
    # @return: 额外比例, 剩余额外可增加经验
    mjLV, _ = GetMJLVInfo(curPlayer)
    if not mjLV:
        return 0, 0
    ipyData = IpyGameDataPY.GetIpyGameData("LLMJ", mjLV)
    if not ipyData:
        return 0, 0
    exPer = ipyData.GetExpAddPer()
    exUpper = ipyData.GetExpExUpper()
    exNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJExp)
    exRemain = max(0, exUpper - exNow)
    return exPer, exRemain
def GetAddDecomposePer(curPlayer):
    ## 获取额外分解比例信息
    # @return: 额外比例, 剩余额外可增加分解
    mjLV, _ = GetMJLVInfo(curPlayer)
    if not mjLV:
        return 0, 0
    ipyData = IpyGameDataPY.GetIpyGameData("LLMJ", mjLV)
    if not ipyData:
        return 0, 0
    exPer = ipyData.GetDecomposeAddPer()
    exUpper = ipyData.GetDecomposeExUpper()
    exNow = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJDecompose)
    exRemain = max(0, exUpper - exNow)
    return exPer, exRemain
def AddExpEx(curPlayer, expEx):
    ## 累加今日额外经验
    if expEx <= 0:
        return
    updEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJExp) + expEx
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJExp, updEx)
    SyncLLMJInfo(curPlayer)
    return
def AddExpDecompose(curPlayer, decomposeEx):
    ## 累加今日额外分解
    if decomposeEx <= 0:
        return
    updEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJDecompose) + decomposeEx
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_LLMJDecompose, updEx)
    SyncLLMJInfo(curPlayer)
    return
def SyncLLMJInfo(curPlayer):
    mjLV, zhanchui = GetMJLVInfo(curPlayer)
    clientPack = ObjPool.GetPoolMgr().acquire(ChPyNetSendPack.tagSCLLMJInfo)
    clientPack.MJLV = mjLV
    clientPack.Zhanchui = zhanchui
    clientPack.ExpEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJExp)
    clientPack.DecomposeEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_LLMJDecompose)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return