From d2350a9a6ec29bdd9fc2cb63cdc9e27b57bc9574 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 20 十月 2025 14:40:03 +0800
Subject: [PATCH] 232 【付费内容】历练秘笈-服务端

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py                             |   60 ++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                              |   64 +++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py |   37 +++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                |   31 ++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                              |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py                            |    6 
 PySysDB/PySysDBPY.h                                                                                                 |   14 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                         |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py                    |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py                            |  138 +++++++++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                     |    5 
 11 files changed, 347 insertions(+), 14 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 34064ab..672e3f8 100644
--- a/PySysDB/PySysDBPY.h
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 36c80b4..84a85ca 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/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,参数(任务组)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 09cf941..6366384 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/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):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py
new file mode 100644
index 0000000..35873b0
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/LLMJ.py
@@ -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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
index 60ad60c..c09cd7f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_MainLevel.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index c38bb47..9fe2fa6 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/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
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
index 4d3cf94..97b296f 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/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()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py
index 5be3bc0..ae360c7 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerCoin.py
+++ b/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,
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index daf3e6f..93a6a3d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/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)
         
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index da8cf30..c6896d3 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/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:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py
new file mode 100644
index 0000000..197a470
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerLLMJ.py
@@ -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

--
Gitblit v1.8.0