From 6feb5f6c84521cab58c523d43ba8a8fc02a5029a Mon Sep 17 00:00:00 2001
From: xdh <xiefantasy@qq.com>
Date: 星期六, 13 四月 2019 17:22:00 +0800
Subject: [PATCH] 6485 【2.0】【后端】炼丹功能开发单

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAttrFruit.py     |   66 +++
 /dev/null                                                                                         |   51 --
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini                        |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFruitAttr.py |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py                |   68 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py            |  130 +++++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py              |  105 ++---
 PySysDB/PySysDBPY.h                                                                               |   34 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py   |  395 +++++++++------------
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py                                     |   68 +++
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                 |  130 +++++-
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                   |   12 
 12 files changed, 637 insertions(+), 430 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 34507c4..763aa91 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -234,7 +234,8 @@
 {
 	DWORD		_ID;	//物品ID
 	BYTE		FuncID;	//所属功能ID
-	WORD		MaxUseCnt;	//最大可使用数量
+	dict		MaxUseCnt;	//境界对应最大可使用数量
+	list		AddItemInfo;	//[增幅丹ID,单次物品数量,单次增加上限]
 	WORD		RecycleMoney;	//回收货币值
 	DWORD		FightPowerEx;	//附加战斗力
 };
@@ -849,35 +850,34 @@
 {
 	BYTE	_StoveLV;	//炼丹炉等级
 	DWORD	UpNeedExp;	//升下一级所需经验
-	list	AddAttrType;	//等级加成属性类型	
-	list	AddAttrNum;	//等级加成属性值
 };
 
 //炼丹表
 
 struct tagAlchemy
 {
-    WORD    _AlchemyID;    //炼丹编号
-    dict    Material;    //所需所有材料和数量
+	DWORD   _ID;    //秘方唯一ID不可变更
+    DWORD   AlchemItemID;    //丹药物品ID
+    BYTE    AlchemType;    //秘方类型1-灵丹 2-仙丹
+	BYTE    AlchemyQuality;    //秘方品级
+	DWORD   LearnNeedItemID;    //丹方物品ID
+	BYTE    LearnNeedAlchemLV;    //丹方需要炼丹等级
+	WORD    LearnNeedLuck;    //丹方需要慧根
+	WORD    NeedTime;    //炼丹时间(秒)
     WORD    AlchemyExp; //炼丹获得经验值
-    list    AlchemyItem;    //产出物品及数量及权重
-	list    SpecAlchemyID;    //特殊炼丹ID组
-	list    AlchemyUp;    //产出包含的进阶丹药
-	BYTE    NeedAlchemyLV;    //所需炼丹等级
+    dict    Material;    //炼丹材料
 };
 
-//炼丹特殊产出表
+//炼丹数量表
 
-struct tagAlchemySpec
+struct tagAlchemyResult
 {
-    WORD    _SpecAlchemyID;    //特殊炼丹ID
-    DWORD	MaterialID;    //特殊材料ID
-    BYTE	MaterialCnt;    //特殊材料ID消耗个数
-    WORD    AlchemyExp; //特殊材料经验
-    list    AlchemyItem;    //产出物品及数量及权重
-	BYTE    NeedAlchemyLV;    //所需炼丹等级
+	BYTE	_AlchemyQuality;	//丹方等级
+	DWORD	LuckValue;	//慧根
+	list	CntRateList;	//数量饼图	
 };
 
+
 //BOSS信息表
 
 struct tagBOSSInfo
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
index 8f1ac92..e437179 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetPack.py
@@ -5584,6 +5584,58 @@
 
 
 #------------------------------------------------------
+# A3 17 增加果实使用上限 #tagCMAddFruitUseLimit
+
+class  tagCMAddFruitUseLimit(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemID", c_int),    #果实物品ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA3
+        self.SubCmd = 0x17
+        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 = 0xA3
+        self.SubCmd = 0x17
+        self.ItemID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMAddFruitUseLimit)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A3 17 增加果实使用上限 //tagCMAddFruitUseLimit:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemID
+                                )
+        return DumpString
+
+
+m_NAtagCMAddFruitUseLimit=tagCMAddFruitUseLimit()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMAddFruitUseLimit.Cmd,m_NAtagCMAddFruitUseLimit.SubCmd))] = m_NAtagCMAddFruitUseLimit
+
+
+#------------------------------------------------------
 # A3 07 过期物品续费 #tagCMItemRenew
 
 class  tagCMItemRenew(Structure):
@@ -10120,8 +10172,8 @@
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("RefineNum", c_ushort),    # 配方编号
-                  ("UseRateItem", c_int),    # 附加材料ID
+                  ("AlchemyID", c_int),    # 丹药ID
+                  ("DoType", c_ubyte),    # 0-学习 1-开始炼丹 2-停止炼丹 3-开炉取丹
                   ]
 
     def __init__(self):
@@ -10138,8 +10190,8 @@
     def Clear(self):
         self.Cmd = 0xA5
         self.SubCmd = 0x76
-        self.RefineNum = 0
-        self.UseRateItem = 0
+        self.AlchemyID = 0
+        self.DoType = 0
         return
 
     def GetLength(self):
@@ -10152,14 +10204,14 @@
         DumpString = '''// A5 76 玩家炼丹 //tagCMPlayerRefine:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                RefineNum:%d,
-                                UseRateItem:%d
+                                AlchemyID:%d,
+                                DoType:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.RefineNum,
-                                self.UseRateItem
+                                self.AlchemyID,
+                                self.DoType
                                 )
         return DumpString
 
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index 19eb427..cbc1371 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -12389,6 +12389,7 @@
     _fields_ = [
                   ("ItemID", c_int),    #果实物品ID
                   ("EatCnt", c_ushort),    #已使用个数
+                  ("AddItemCnt", c_int),    #增幅丹使用个数
                   ]
 
     def __init__(self):
@@ -12403,6 +12404,7 @@
     def Clear(self):
         self.ItemID = 0
         self.EatCnt = 0
+        self.AddItemCnt = 0
         return
 
     def GetLength(self):
@@ -12414,11 +12416,13 @@
     def OutputString(self):
         DumpString = '''// A3 39 玩家属性果实已使用个数信息//tagMCAttrFruitEatCntList:
                                 ItemID:%d,
-                                EatCnt:%d
+                                EatCnt:%d,
+                                AddItemCnt:%d
                                 '''\
                                 %(
                                 self.ItemID,
-                                self.EatCnt
+                                self.EatCnt,
+                                self.AddItemCnt
                                 )
         return DumpString
 
@@ -16160,20 +16164,15 @@
 #------------------------------------------------------
 # A3 BF 通知客户端炼丹炉信息 #tagMCPlayerStoveMsg
 
-class  tagMCPlayerStoveMsg(Structure):
+class  tagMCPlayerStoveInfo(Structure):
     _pack_ = 1
     _fields_ = [
-                  ("Cmd", c_ubyte),
-                  ("SubCmd", c_ubyte),
-                  ("StoveLV", c_ubyte),    # 炼丹炉等级
-                  ("StoveExp", c_int),    # 炼丹炉经验 
-                  ("ItemID", c_int),    # 合成物品id
+                  ("AlchemyID", c_int),    # 丹 ID
+                  ("StartTime", c_int),    # 开始炼的时间 
                   ]
 
     def __init__(self):
         self.Clear()
-        self.Cmd = 0xA3
-        self.SubCmd = 0xBF
         return
 
     def ReadData(self, stringData, _pos=0, _len=0):
@@ -16182,39 +16181,120 @@
         return _pos + self.GetLength()
 
     def Clear(self):
-        self.Cmd = 0xA3
-        self.SubCmd = 0xBF
-        self.StoveLV = 0
-        self.StoveExp = 0
-        self.ItemID = 0
+        self.AlchemyID = 0
+        self.StartTime = 0
         return
 
     def GetLength(self):
-        return sizeof(tagMCPlayerStoveMsg)
+        return sizeof(tagMCPlayerStoveInfo)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
         DumpString = '''// A3 BF 通知客户端炼丹炉信息 //tagMCPlayerStoveMsg:
-                                Cmd:%s,
-                                SubCmd:%s,
-                                StoveLV:%d,
-                                StoveExp:%d,
-                                ItemID:%d
+                                AlchemyID:%d,
+                                StartTime:%d
                                 '''\
                                 %(
-                                self.Cmd,
-                                self.SubCmd,
+                                self.AlchemyID,
+                                self.StartTime
+                                )
+        return DumpString
+
+
+class  tagMCPlayerStoveMsg(Structure):
+    Head = tagHead()
+    StoveLV = 0    #(BYTE StoveLV)// 炼丹炉等级
+    StoveExp = 0    #(DWORD StoveExp)// 炼丹炉经验
+    ItemID = 0    #(DWORD ItemID)// 合成物品id
+    ItemCnt = 0    #(BYTE ItemCnt)// 丹药数量
+    StoveCnt = 0    #(WORD StoveCnt)// 丹药数量
+    InfoList = list()    #(vector<tagMCPlayerStoveInfo> InfoList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0xBF
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.StoveLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StoveExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ItemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ItemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StoveCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        for i in range(self.StoveCnt):
+            temInfoList = tagMCPlayerStoveInfo()
+            _pos = temInfoList.ReadData(_lpData, _pos)
+            self.InfoList.append(temInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0xBF
+        self.StoveLV = 0
+        self.StoveExp = 0
+        self.ItemID = 0
+        self.ItemCnt = 0
+        self.StoveCnt = 0
+        self.InfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 4
+        length += 4
+        length += 1
+        length += 2
+        for i in range(self.StoveCnt):
+            length += self.InfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.StoveLV)
+        data = CommFunc.WriteDWORD(data, self.StoveExp)
+        data = CommFunc.WriteDWORD(data, self.ItemID)
+        data = CommFunc.WriteBYTE(data, self.ItemCnt)
+        data = CommFunc.WriteWORD(data, self.StoveCnt)
+        for i in range(self.StoveCnt):
+            data = CommFunc.WriteString(data, self.InfoList[i].GetLength(), self.InfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                StoveLV:%d,
+                                StoveExp:%d,
+                                ItemID:%d,
+                                ItemCnt:%d,
+                                StoveCnt:%d,
+                                InfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
                                 self.StoveLV,
                                 self.StoveExp,
-                                self.ItemID
+                                self.ItemID,
+                                self.ItemCnt,
+                                self.StoveCnt,
+                                "..."
                                 )
         return DumpString
 
 
 m_NAtagMCPlayerStoveMsg=tagMCPlayerStoveMsg()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerStoveMsg.Cmd,m_NAtagMCPlayerStoveMsg.SubCmd))] = m_NAtagMCPlayerStoveMsg
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerStoveMsg.Head.Cmd,m_NAtagMCPlayerStoveMsg.Head.SubCmd))] = m_NAtagMCPlayerStoveMsg
 
 
 #------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index f03bd88..cbb88d8 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -812,7 +812,7 @@
 Writer = xdh
 Releaser = xdh
 RegType = 0
-RegisterPackCount = 2
+RegisterPackCount = 3
 
 PacketCMD_1=0xA3
 PacketSubCMD_1=0x2B
@@ -822,6 +822,10 @@
 PacketSubCMD_2=0x2A
 PacketCallFunc_2=OnRecycleAttrFruit
 
+PacketCMD_3=0xA3
+PacketSubCMD_3=0x17
+PacketCallFunc_3=OnAddFruitUseLimit
+
 
 ;开服活动
 [OpenServerCampaign]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index b6fc629..9b78803 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3468,6 +3468,8 @@
 Def_PDict_AddPointValue = "AddPointValue_%s"  # 已加属性点数, 参数(属性ID)
 Def_PDict_AttrFruitEatCnt = "AttrFruitEatCnt_%s"  # 已吃属性果实个数,参数为物品id
 Def_PDict_AttrFruitAddValue = "AttrFruitAddValue_%s"  # 已吃属性果实增加的属性,参数为物品id
+Def_PDict_AttrFruitAddItemCnt = "FruitAddItemCnt_%s"  # 已吃增幅丹个数,参数为果实物品id
+
 
 Def_PDict_NobleLV = "NobleLV" # 贵族等级, 0位为不同贵族模式版本切换标记位, 从1位开始表示每种等级贵族开通情况, 1-已开通过;9-永久
 Def_PDict_NobleEndTime = "NobleEndTime_%s" # 贵族到期结束时间<单位s>, 参数为贵族等级, 从1开始
@@ -3829,9 +3831,11 @@
 #炼丹炉
 Def_PDict_AlchemyLV = "AlchemyLV" #炼丹等级
 Def_PDict_AlchemyExp = "AlchemyExp" #炼丹经验
-Def_PDict_AlchemyCount = "AlchemyCount_%s" #特殊炼丹次数产出设定已累计次数, 参数(配方ID)
-Def_PDict_AlchemyCountSpec = "AlchemyCountSpec_%s" #特殊炼丹次数产出设定已累计次数, 参数(配方ID)
-Def_PDict_AlchemyOutputCount = "AlchemyOutputCount_%s" #炼丹特殊产出物品已产出次数,参数(物品ID)
+Def_PDict_AlchemyLearnState = "AlchemyLearnState%s" #丹方是否已学习 
+Def_PDict_AlchemyItemID = "AlchemyItemID_%s" #炼丹中的丹药ID  参数丹药类型
+Def_PDict_AlchemyStartTime = "AlchemyStartTime_%s" #炼丹开始时间    参数丹药ID
+
+
 Def_PDict_AlchemyPrayCnt = "AlchemyPrayCnt" #炼丹祈福次数
 
 Def_PDict_GFPassiveIndex = "GFP_%s_%s"   # 被动功法 页数-索引
@@ -4272,7 +4276,7 @@
 Def_CalcAttrFunc_EquipOutOfPrint, # 绝版属性随等级变化 15
 Def_CalcAttrFunc_Success, # 成就属性 16
 Def_CalcAttrFunc_VIP, # VIP属性 17
-Def_CalcAttrFunc_Stove, # 炼丹炉 18
+Def_CalcAttrFunc_Stove, # 炼丹炉 18(废弃)
 Def_CalcAttrFunc_FamilyTech, # 仙盟心法 19
 Def_CalcAttrFunc_EquipDecompose, # 装备分解属性 20
 Def_CalcAttrFunc_PetSoul, # 宠物魂石 21
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
index 8f1ac92..e437179 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetPack.py
@@ -5584,6 +5584,58 @@
 
 
 #------------------------------------------------------
+# A3 17 增加果实使用上限 #tagCMAddFruitUseLimit
+
+class  tagCMAddFruitUseLimit(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("Cmd", c_ubyte),
+                  ("SubCmd", c_ubyte),
+                  ("ItemID", c_int),    #果实物品ID
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        self.Cmd = 0xA3
+        self.SubCmd = 0x17
+        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 = 0xA3
+        self.SubCmd = 0x17
+        self.ItemID = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagCMAddFruitUseLimit)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A3 17 增加果实使用上限 //tagCMAddFruitUseLimit:
+                                Cmd:%s,
+                                SubCmd:%s,
+                                ItemID:%d
+                                '''\
+                                %(
+                                self.Cmd,
+                                self.SubCmd,
+                                self.ItemID
+                                )
+        return DumpString
+
+
+m_NAtagCMAddFruitUseLimit=tagCMAddFruitUseLimit()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagCMAddFruitUseLimit.Cmd,m_NAtagCMAddFruitUseLimit.SubCmd))] = m_NAtagCMAddFruitUseLimit
+
+
+#------------------------------------------------------
 # A3 07 过期物品续费 #tagCMItemRenew
 
 class  tagCMItemRenew(Structure):
@@ -10120,8 +10172,8 @@
     _fields_ = [
                   ("Cmd", c_ubyte),
                   ("SubCmd", c_ubyte),
-                  ("RefineNum", c_ushort),    # 配方编号
-                  ("UseRateItem", c_int),    # 附加材料ID
+                  ("AlchemyID", c_int),    # 丹药ID
+                  ("DoType", c_ubyte),    # 0-学习 1-开始炼丹 2-停止炼丹 3-开炉取丹
                   ]
 
     def __init__(self):
@@ -10138,8 +10190,8 @@
     def Clear(self):
         self.Cmd = 0xA5
         self.SubCmd = 0x76
-        self.RefineNum = 0
-        self.UseRateItem = 0
+        self.AlchemyID = 0
+        self.DoType = 0
         return
 
     def GetLength(self):
@@ -10152,14 +10204,14 @@
         DumpString = '''// A5 76 玩家炼丹 //tagCMPlayerRefine:
                                 Cmd:%s,
                                 SubCmd:%s,
-                                RefineNum:%d,
-                                UseRateItem:%d
+                                AlchemyID:%d,
+                                DoType:%d
                                 '''\
                                 %(
                                 self.Cmd,
                                 self.SubCmd,
-                                self.RefineNum,
-                                self.UseRateItem
+                                self.AlchemyID,
+                                self.DoType
                                 )
         return DumpString
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index 19eb427..cbc1371 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -12389,6 +12389,7 @@
     _fields_ = [
                   ("ItemID", c_int),    #果实物品ID
                   ("EatCnt", c_ushort),    #已使用个数
+                  ("AddItemCnt", c_int),    #增幅丹使用个数
                   ]
 
     def __init__(self):
@@ -12403,6 +12404,7 @@
     def Clear(self):
         self.ItemID = 0
         self.EatCnt = 0
+        self.AddItemCnt = 0
         return
 
     def GetLength(self):
@@ -12414,11 +12416,13 @@
     def OutputString(self):
         DumpString = '''// A3 39 玩家属性果实已使用个数信息//tagMCAttrFruitEatCntList:
                                 ItemID:%d,
-                                EatCnt:%d
+                                EatCnt:%d,
+                                AddItemCnt:%d
                                 '''\
                                 %(
                                 self.ItemID,
-                                self.EatCnt
+                                self.EatCnt,
+                                self.AddItemCnt
                                 )
         return DumpString
 
@@ -16160,20 +16164,15 @@
 #------------------------------------------------------
 # A3 BF 通知客户端炼丹炉信息 #tagMCPlayerStoveMsg
 
-class  tagMCPlayerStoveMsg(Structure):
+class  tagMCPlayerStoveInfo(Structure):
     _pack_ = 1
     _fields_ = [
-                  ("Cmd", c_ubyte),
-                  ("SubCmd", c_ubyte),
-                  ("StoveLV", c_ubyte),    # 炼丹炉等级
-                  ("StoveExp", c_int),    # 炼丹炉经验 
-                  ("ItemID", c_int),    # 合成物品id
+                  ("AlchemyID", c_int),    # 丹 ID
+                  ("StartTime", c_int),    # 开始炼的时间 
                   ]
 
     def __init__(self):
         self.Clear()
-        self.Cmd = 0xA3
-        self.SubCmd = 0xBF
         return
 
     def ReadData(self, stringData, _pos=0, _len=0):
@@ -16182,39 +16181,120 @@
         return _pos + self.GetLength()
 
     def Clear(self):
-        self.Cmd = 0xA3
-        self.SubCmd = 0xBF
-        self.StoveLV = 0
-        self.StoveExp = 0
-        self.ItemID = 0
+        self.AlchemyID = 0
+        self.StartTime = 0
         return
 
     def GetLength(self):
-        return sizeof(tagMCPlayerStoveMsg)
+        return sizeof(tagMCPlayerStoveInfo)
 
     def GetBuffer(self):
         return string_at(addressof(self), self.GetLength())
 
     def OutputString(self):
         DumpString = '''// A3 BF 通知客户端炼丹炉信息 //tagMCPlayerStoveMsg:
-                                Cmd:%s,
-                                SubCmd:%s,
-                                StoveLV:%d,
-                                StoveExp:%d,
-                                ItemID:%d
+                                AlchemyID:%d,
+                                StartTime:%d
                                 '''\
                                 %(
-                                self.Cmd,
-                                self.SubCmd,
+                                self.AlchemyID,
+                                self.StartTime
+                                )
+        return DumpString
+
+
+class  tagMCPlayerStoveMsg(Structure):
+    Head = tagHead()
+    StoveLV = 0    #(BYTE StoveLV)// 炼丹炉等级
+    StoveExp = 0    #(DWORD StoveExp)// 炼丹炉经验
+    ItemID = 0    #(DWORD ItemID)// 合成物品id
+    ItemCnt = 0    #(BYTE ItemCnt)// 丹药数量
+    StoveCnt = 0    #(WORD StoveCnt)// 丹药数量
+    InfoList = list()    #(vector<tagMCPlayerStoveInfo> InfoList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0xBF
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.StoveLV,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StoveExp,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ItemID,_pos = CommFunc.ReadDWORD(_lpData, _pos)
+        self.ItemCnt,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        self.StoveCnt,_pos = CommFunc.ReadWORD(_lpData, _pos)
+        for i in range(self.StoveCnt):
+            temInfoList = tagMCPlayerStoveInfo()
+            _pos = temInfoList.ReadData(_lpData, _pos)
+            self.InfoList.append(temInfoList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0xBF
+        self.StoveLV = 0
+        self.StoveExp = 0
+        self.ItemID = 0
+        self.ItemCnt = 0
+        self.StoveCnt = 0
+        self.InfoList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        length += 4
+        length += 4
+        length += 1
+        length += 2
+        for i in range(self.StoveCnt):
+            length += self.InfoList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.StoveLV)
+        data = CommFunc.WriteDWORD(data, self.StoveExp)
+        data = CommFunc.WriteDWORD(data, self.ItemID)
+        data = CommFunc.WriteBYTE(data, self.ItemCnt)
+        data = CommFunc.WriteWORD(data, self.StoveCnt)
+        for i in range(self.StoveCnt):
+            data = CommFunc.WriteString(data, self.InfoList[i].GetLength(), self.InfoList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                StoveLV:%d,
+                                StoveExp:%d,
+                                ItemID:%d,
+                                ItemCnt:%d,
+                                StoveCnt:%d,
+                                InfoList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
                                 self.StoveLV,
                                 self.StoveExp,
-                                self.ItemID
+                                self.ItemID,
+                                self.ItemCnt,
+                                self.StoveCnt,
+                                "..."
                                 )
         return DumpString
 
 
 m_NAtagMCPlayerStoveMsg=tagMCPlayerStoveMsg()
-ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerStoveMsg.Cmd,m_NAtagMCPlayerStoveMsg.SubCmd))] = m_NAtagMCPlayerStoveMsg
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCPlayerStoveMsg.Head.Cmd,m_NAtagMCPlayerStoveMsg.Head.SubCmd))] = m_NAtagMCPlayerStoveMsg
 
 
 #------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFruitAttr.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFruitAttr.py
index d90846e..455a187 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFruitAttr.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearFruitAttr.py
@@ -79,7 +79,7 @@
                 curPlayer.SetDict(attrKey, 0)
                 
             if isGiveFruitItem:
-                giveFruitItemList.append([itemID, ipyData.GetMaxUseCnt()])
+                giveFruitItemList.append([itemID, PlayerAttrFruit.GetMaxEatCnt(curPlayer, itemID)])
                 
     PlayerAttrFruit.Sync_AttrFruitEatCnt(curPlayer)
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetAlchemyCount.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetAlchemyCount.py
deleted file mode 100644
index 5307e56..0000000
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetAlchemyCount.py
+++ /dev/null
@@ -1,51 +0,0 @@
-#!/usr/bin/python
-# -*- coding: GBK -*-
-#-------------------------------------------------------------------------------
-#
-##@package GM.Commands.SetAlchemyCount
-#
-# @todo:设置炼丹次数
-# @author hxp
-# @date 2018-03-19
-# @version 1.0
-#
-# 详细描述: 设置炼丹次数
-#
-#-------------------------------------------------------------------------------
-#"""Version = 2018-03-19 19:30"""
-#-------------------------------------------------------------------------------
-
-import GameWorld
-import PlayerControl
-import IpyGameDataPY
-import ChConfig
-
-
-## 逻辑实现
-#  @param curPlayer
-#  @param cmdList 参数列表
-#  @return None
-def OnExec(curPlayer, cmdList):
-    if not cmdList:
-        #GameWorld.DebugAnswer(curPlayer, "SetAlchemyCount 炼丹编号 次数 是否特殊炼丹")
-        GameWorld.DebugAnswer(curPlayer, "SetAlchemyCount 所有炼丹次数")
-        return
-    
-    SpecialAlchemyDictComm = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 1)
-    SpecialAlchemyDictSpec = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 2)
-    
-    alchemyCount = cmdList[0]
-    for alchemyID in SpecialAlchemyDictComm.keys():
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyCount % alchemyID, alchemyCount)
-        GameWorld.DebugAnswer(curPlayer, "设置普通炼丹次数,ID=%s,次数=%s" % (alchemyID, alchemyCount))
-    for specID in SpecialAlchemyDictSpec.keys():
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyCountSpec % specID, alchemyCount)
-        GameWorld.DebugAnswer(curPlayer, "设置特殊炼丹次数,ID=%s,次数=%s" % (specID, alchemyCount))
-        
-    if alchemyCount == 0:
-        outPutCountLimitDict = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 3)
-        for itemID in outPutCountLimitDict.keys():
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyOutputCount % itemID, 0)
-        GameWorld.DebugAnswer(curPlayer, "重置特殊物品产出次数: %s" % str(outPutCountLimitDict.keys()))
-        
-    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index a00ba7b..db11233 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -205,7 +205,8 @@
                 "AttrFruit":(
                         ("DWORD", "ID", 1),
                         ("BYTE", "FuncID", 0),
-                        ("WORD", "MaxUseCnt", 0),
+                        ("dict", "MaxUseCnt", 0),
+                        ("list", "AddItemInfo", 0),
                         ("WORD", "RecycleMoney", 0),
                         ("DWORD", "FightPowerEx", 0),
                         ),
@@ -698,27 +699,25 @@
                 "RefineStove":(
                         ("BYTE", "StoveLV", 1),
                         ("DWORD", "UpNeedExp", 0),
-                        ("list", "AddAttrType", 0),
-                        ("list", "AddAttrNum", 0),
                         ),
 
                 "Alchemy":(
-                        ("WORD", "AlchemyID", 1),
-                        ("dict", "Material", 0),
+                        ("DWORD", "ID", 1),
+                        ("DWORD", "AlchemItemID", 0),
+                        ("BYTE", "AlchemType", 0),
+                        ("BYTE", "AlchemyQuality", 0),
+                        ("DWORD", "LearnNeedItemID", 0),
+                        ("BYTE", "LearnNeedAlchemLV", 0),
+                        ("WORD", "LearnNeedLuck", 0),
+                        ("WORD", "NeedTime", 0),
                         ("WORD", "AlchemyExp", 0),
-                        ("list", "AlchemyItem", 0),
-                        ("list", "SpecAlchemyID", 0),
-                        ("list", "AlchemyUp", 0),
-                        ("BYTE", "NeedAlchemyLV", 0),
+                        ("dict", "Material", 0),
                         ),
 
-                "AlchemySpec":(
-                        ("WORD", "SpecAlchemyID", 1),
-                        ("DWORD", "MaterialID", 0),
-                        ("BYTE", "MaterialCnt", 0),
-                        ("WORD", "AlchemyExp", 0),
-                        ("list", "AlchemyItem", 0),
-                        ("BYTE", "NeedAlchemyLV", 0),
+                "AlchemyResult":(
+                        ("BYTE", "AlchemyQuality", 1),
+                        ("DWORD", "LuckValue", 0),
+                        ("list", "CntRateList", 0),
                         ),
 
                 "BOSSInfo":(
@@ -1781,14 +1780,16 @@
     def __init__(self):
         self.ID = 0
         self.FuncID = 0
-        self.MaxUseCnt = 0
+        self.MaxUseCnt = {}
+        self.AddItemInfo = []
         self.RecycleMoney = 0
         self.FightPowerEx = 0
         return
         
     def GetID(self): return self.ID # 物品ID
     def GetFuncID(self): return self.FuncID # 所属功能ID
-    def GetMaxUseCnt(self): return self.MaxUseCnt # 最大可使用数量
+    def GetMaxUseCnt(self): return self.MaxUseCnt # 境界对应最大可使用数量
+    def GetAddItemInfo(self): return self.AddItemInfo # [增幅丹ID,单次物品数量,单次增加上限]
     def GetRecycleMoney(self): return self.RecycleMoney # 回收货币值
     def GetFightPowerEx(self): return self.FightPowerEx # 附加战斗力
 
@@ -2804,55 +2805,51 @@
     
     def __init__(self):
         self.StoveLV = 0
-        self.UpNeedExp = 0
-        self.AddAttrType = []
-        self.AddAttrNum = []
+        self.UpNeedExp = 0
         return
         
     def GetStoveLV(self): return self.StoveLV # 炼丹炉等级
-    def GetUpNeedExp(self): return self.UpNeedExp # 升下一级所需经验
-    def GetAddAttrType(self): return self.AddAttrType # 等级加成属性类型
-    def GetAddAttrNum(self): return self.AddAttrNum # 等级加成属性值
+    def GetUpNeedExp(self): return self.UpNeedExp # 升下一级所需经验
 
 # 炼丹表
 class IPY_Alchemy():
     
     def __init__(self):
-        self.AlchemyID = 0
-        self.Material = {}
+        self.ID = 0
+        self.AlchemItemID = 0
+        self.AlchemType = 0
+        self.AlchemyQuality = 0
+        self.LearnNeedItemID = 0
+        self.LearnNeedAlchemLV = 0
+        self.LearnNeedLuck = 0
+        self.NeedTime = 0
         self.AlchemyExp = 0
-        self.AlchemyItem = []
-        self.SpecAlchemyID = []
-        self.AlchemyUp = []
-        self.NeedAlchemyLV = 0
+        self.Material = {}
         return
         
-    def GetAlchemyID(self): return self.AlchemyID # 炼丹编号
-    def GetMaterial(self): return self.Material # 所需所有材料和数量
+    def GetID(self): return self.ID # 秘方唯一ID不可变更
+    def GetAlchemItemID(self): return self.AlchemItemID # 丹药物品ID
+    def GetAlchemType(self): return self.AlchemType # 秘方类型1-灵丹 2-仙丹
+    def GetAlchemyQuality(self): return self.AlchemyQuality # 秘方品级
+    def GetLearnNeedItemID(self): return self.LearnNeedItemID # 丹方物品ID
+    def GetLearnNeedAlchemLV(self): return self.LearnNeedAlchemLV # 丹方需要炼丹等级
+    def GetLearnNeedLuck(self): return self.LearnNeedLuck # 丹方需要慧根
+    def GetNeedTime(self): return self.NeedTime # 炼丹时间(秒)
     def GetAlchemyExp(self): return self.AlchemyExp # 炼丹获得经验值
-    def GetAlchemyItem(self): return self.AlchemyItem # 产出物品及数量及权重
-    def GetSpecAlchemyID(self): return self.SpecAlchemyID # 特殊炼丹ID组
-    def GetAlchemyUp(self): return self.AlchemyUp # 产出包含的进阶丹药
-    def GetNeedAlchemyLV(self): return self.NeedAlchemyLV # 所需炼丹等级
+    def GetMaterial(self): return self.Material # 炼丹材料
 
-# 炼丹特殊产出表
-class IPY_AlchemySpec():
+# 炼丹数量表
+class IPY_AlchemyResult():
     
     def __init__(self):
-        self.SpecAlchemyID = 0
-        self.MaterialID = 0
-        self.MaterialCnt = 0
-        self.AlchemyExp = 0
-        self.AlchemyItem = []
-        self.NeedAlchemyLV = 0
+        self.AlchemyQuality = 0
+        self.LuckValue = 0
+        self.CntRateList = []
         return
         
-    def GetSpecAlchemyID(self): return self.SpecAlchemyID # 特殊炼丹ID
-    def GetMaterialID(self): return self.MaterialID # 特殊材料ID
-    def GetMaterialCnt(self): return self.MaterialCnt # 特殊材料ID消耗个数
-    def GetAlchemyExp(self): return self.AlchemyExp # 特殊材料经验
-    def GetAlchemyItem(self): return self.AlchemyItem # 产出物品及数量及权重
-    def GetNeedAlchemyLV(self): return self.NeedAlchemyLV # 所需炼丹等级
+    def GetAlchemyQuality(self): return self.AlchemyQuality # 丹方等级
+    def GetLuckValue(self): return self.LuckValue # 慧根
+    def GetCntRateList(self): return self.CntRateList # 数量饼图
 
 # BOSS信息表
 class IPY_BOSSInfo():
@@ -4467,8 +4464,8 @@
         self.ipyRefineStoveLen = len(self.ipyRefineStoveCache)
         self.ipyAlchemyCache = self.__LoadFileData("Alchemy", IPY_Alchemy)
         self.ipyAlchemyLen = len(self.ipyAlchemyCache)
-        self.ipyAlchemySpecCache = self.__LoadFileData("AlchemySpec", IPY_AlchemySpec)
-        self.ipyAlchemySpecLen = len(self.ipyAlchemySpecCache)
+        self.ipyAlchemyResultCache = self.__LoadFileData("AlchemyResult", IPY_AlchemyResult)
+        self.ipyAlchemyResultLen = len(self.ipyAlchemyResultCache)
         self.ipyBOSSInfoCache = self.__LoadFileData("BOSSInfo", IPY_BOSSInfo)
         self.ipyBOSSInfoLen = len(self.ipyBOSSInfoCache)
         self.ipyElderGodAreaCache = self.__LoadFileData("ElderGodArea", IPY_ElderGodArea)
@@ -4921,8 +4918,8 @@
     def GetRefineStoveByIndex(self, index): return self.ipyRefineStoveCache[index]
     def GetAlchemyCount(self): return self.ipyAlchemyLen
     def GetAlchemyByIndex(self, index): return self.ipyAlchemyCache[index]
-    def GetAlchemySpecCount(self): return self.ipyAlchemySpecLen
-    def GetAlchemySpecByIndex(self, index): return self.ipyAlchemySpecCache[index]
+    def GetAlchemyResultCount(self): return self.ipyAlchemyResultLen
+    def GetAlchemyResultByIndex(self, index): return self.ipyAlchemyResultCache[index]
     def GetBOSSInfoCount(self): return self.ipyBOSSInfoLen
     def GetBOSSInfoByIndex(self, index): return self.ipyBOSSInfoCache[index]
     def GetElderGodAreaCount(self): return self.ipyElderGodAreaLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAttrFruit.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAttrFruit.py
index a4f10f9..5f9e96a 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAttrFruit.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAttrFruit.py
@@ -98,7 +98,7 @@
         if not ipyData:
             continue
         
-        maxEatCnt = ipyData.GetMaxUseCnt()
+        maxEatCnt = GetMaxEatCnt(curPlayer, itemID)
         eatCntKey = ChConfig.Def_PDict_AttrFruitEatCnt % itemID
         limitType = Def_LimitType_Cnt
         if limitType == Def_LimitType_Attr:
@@ -216,7 +216,7 @@
 
     funcIndex = ipyData.GetFuncID()
     limitType = Def_LimitType_Cnt
-    maxEatCnt = ipyData.GetMaxUseCnt()
+    maxEatCnt = GetMaxEatCnt(curPlayer, itemID)
     
     if funcIndex not in ShareDefine.Def_AttrFruitFuncList:
         GameWorld.ErrLog("该属性果实功能未开放!funcIndex=%s"%funcIndex)
@@ -446,7 +446,7 @@
         eatCntPack.Clear()
         eatCntPack.ItemID = fruitItemID
         eatCntPack.EatCnt = curPlayer.NomalDictGetProperty(eatCntKey)
-        #eatCntPack.AddAttr = curPlayer.NomalDictGetProperty(addValueKey)
+        eatCntPack.AddItemCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AttrFruitAddItemCnt % fruitItemID)
         eatPack.EatCntList.append(eatCntPack)
     
     eatPack.count = len(eatPack.EatCntList)
@@ -480,11 +480,7 @@
 
 def IsFruitEatFull(curPlayer, itemID):
     #使用次数是否已满
-    ipyData = GetAttrFruitIpyData(itemID)
-    if not ipyData:
-        return
-    
-    maxEatCnt = ipyData.GetMaxUseCnt()
+    maxEatCnt = GetMaxEatCnt(curPlayer, itemID)
     eatCntKey = ChConfig.Def_PDict_AttrFruitEatCnt % itemID
     limitType = Def_LimitType_Cnt
     if limitType == Def_LimitType_Attr:
@@ -492,4 +488,56 @@
     eatCnt = curPlayer.NomalDictGetProperty(eatCntKey) # 已吃次数/属性值
     if eatCnt >= maxEatCnt:
         return True
-    return
\ No newline at end of file
+    return
+
+def GetMaxEatCnt(curPlayer, itemID):
+    ##获取果实最大可用个数
+    ipyData = GetAttrFruitIpyData(itemID)
+    if not ipyData:
+        return 0
+    maxEatCntDict = ipyData.GetMaxUseCnt()
+    realmLV = curPlayer.GetOfficialRank()
+    orderList = sorted(maxEatCntDict.keys(), reverse=True)
+    maxEatCnt = 0
+    for order in orderList:
+        if realmLV >= order:
+            maxEatCnt = maxEatCntDict[order]
+            break
+    addItemUseCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AttrFruitAddItemCnt % itemID)
+    if addItemUseCnt:
+        addItemInfo = ipyData.GetAddItemInfo()
+        if addItemInfo:
+            singleItemCnt, singleAddCnt = addItemInfo[1:]
+            maxEatCnt += (addItemUseCnt/singleItemCnt*singleAddCnt)
+    return maxEatCnt
+
+
+#// A3 17 增加果实使用上限 #tagCMAddFruitUseLimit
+#
+#struct    tagCMAddFruitUseLimit
+#{
+#    tagHead        Head;
+#    DWORD        ItemID;        //果实物品ID
+#};
+def OnAddFruitUseLimit(index, packData, tick):
+    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+    itemID = packData.ItemID
+    ipyData = GetAttrFruitIpyData(itemID)
+    if not ipyData:
+        return
+    addItemInfo = ipyData.GetAddItemInfo()
+    if not addItemInfo:
+        return
+    addItemUseCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AttrFruitAddItemCnt % itemID)
+    needItemID, singleItemCnt, singleAddCnt = addItemInfo
+    if addItemUseCnt + singleItemCnt> ChConfig.Def_UpperLimit_DWord:
+        return
+    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+    enough, indexList, hasBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(needItemID, itemPack, singleItemCnt)
+    if not enough:
+        return
+    ItemCommon.ReduceItem(curPlayer, itemPack, indexList, singleItemCnt, False, "AddFruitUseLimit")
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AttrFruitAddItemCnt % itemID, addItemUseCnt+singleItemCnt)
+    
+    Sync_AttrFruitEatCnt(curPlayer, [itemID])
+    return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
index 3c5bf18..b6abbcf 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerRefineStove.py
@@ -6,13 +6,13 @@
 ##@package PlayerRefineStove
 # @todo: 玩家炼丹炉
 #
-# @author: sgj
-# @date 2017-11-07
+# @author: xdh
+# @date 2019-4-12
 # @version 1.0
 #
 # @note: 
 #---------------------------------------------------------------------
-#"""Version = 2017-11-07 16:40"""
+#"""Version = 2019-4-12 16:40"""
 #---------------------------------------------------------------------
 import ChConfig
 import GameWorld
@@ -35,6 +35,9 @@
 import PlayerVip
 
 import copy
+import time
+
+DefStoveTypeList = [1, 2]  #1灵丹 2仙丹
 
 
 ##功能开启
@@ -44,24 +47,27 @@
     Sycn_AlchemyMsg(curPlayer)
     return True
 
+
 ##登录处理
 def DoOnLogin(curPlayer, tick):
     Sycn_AlchemyMsg(curPlayer)
     Sycn_AlchemyPrayMsg(curPlayer)
     return
 
+
 def OnDay(curPlayer):
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyPrayCnt, 0)
     Sycn_AlchemyPrayMsg(curPlayer)
     return
+
 
 #// A5 76 玩家炼丹 #tagCMPlayerRefine
 #
 #struct tagCMPlayerRefine
 #{
 #    tagHead    Head;
-#    WORD    RefineNum;    // 配方编号
-#    DWORD   UseRateItem;  // 附加材料ID
+#    DWORD    AlchemyID;    // 丹药ID
+#    BYTE   DoType;  // 0-学习 1-开始炼丹 2-停止炼丹 3-开炉取丹
 #};
 def PlayerRefineItem(index, clientPack, tick):
     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
@@ -70,193 +76,147 @@
         GameWorld.DebugLog("炼丹炉功能未开启!", playerID)
         return
     
-    alchemyID = clientPack.RefineNum
-    specID = clientPack.UseRateItem # 特殊炼丹ID
-    GameWorld.DebugLog("玩家炼丹: alchemyID=%s,specID=%s" % (alchemyID, specID), playerID)
+    alchemyID = clientPack.AlchemyID
+    doType = clientPack.DoType
+    GameWorld.DebugLog("玩家炼丹: alchemyID=%s, doType=%s" % (alchemyID, doType), playerID)
     alchemyIpyData = IpyGameDataPY.GetIpyGameData("Alchemy", alchemyID)
     if not alchemyIpyData:
         GameWorld.DebugLog("配方不存在!alchemyID=%s" % alchemyID, playerID)
         return
-    
-    specAlchemyIpyData = None
-    if specID:
-        specAlchemyIDList = alchemyIpyData.GetSpecAlchemyID()
-        if specID not in specAlchemyIDList:
-            GameWorld.DebugLog("非法特殊配方!alchemyID=%s,specID=%s" % (alchemyID, specID), playerID)
-            return
-        specAlchemyIpyData = IpyGameDataPY.GetIpyGameData("AlchemySpec", specID)
-        if not specAlchemyIpyData:
-            GameWorld.DebugLog("特殊配方不存在!alchemyID=%s,specID=%s" % (alchemyID, specID), playerID)
-            return
-        
-    # 等级判断
+    alchemType = alchemyIpyData.GetAlchemType()
+    alchemyItemID = alchemyIpyData.GetAlchemItemID()
+    hasLearn = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_AlchemyLearnState, alchemyID)
     alchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
-    if alchemyLV < alchemyIpyData.GetNeedAlchemyLV():        
-        GameWorld.DebugLog("配方未开启!alchemyID=%s,needAlchemyLV=%s,curAlchemyLV=%s" 
-                           % (alchemyID, alchemyIpyData.GetNeedAlchemyLV(), alchemyLV), playerID)
-        return
-    if specAlchemyIpyData:
-        if alchemyLV < specAlchemyIpyData.GetNeedAlchemyLV():        
-            GameWorld.DebugLog("特殊配方未开启!alchemyID=%s,specID=%s,needAlchemyLV=%s,curAlchemyLV=%s" 
-                               % (alchemyID, specID, specAlchemyIpyData.GetNeedAlchemyLV(), alchemyLV), playerID)
+    curAlchemyItemID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyItemID % alchemType)  #正在炼的丹
+    curLuckValue = curPlayer.GetLuckValue()
+    curTime = int(time.time())
+    
+    if doType == 0:
+        if hasLearn:
+            GameWorld.DebugLog('丹方已学习!,不可重复学')
             return
+        learnNeedAlchemLV = alchemyIpyData.GetLearnNeedAlchemLV()
+        if alchemyLV < learnNeedAlchemLV:
+            GameWorld.DebugLog('丹方学习需要炼丹等级 %s' % learnNeedAlchemLV)
+            return
+        learnNeedLuck = alchemyIpyData.GetLearnNeedLuck()
+        if curLuckValue < learnNeedLuck:
+            GameWorld.DebugLog('丹方学习需要慧根 %s' % learnNeedLuck)
+            return
+        learnNeedItemID = alchemyIpyData.GetLearnNeedItemID()
+        itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+        enough, indexList, hasBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(learnNeedItemID, itemPack, 1)
+        if not enough:
+            return
+        ItemCommon.ReduceItem(curPlayer, itemPack, indexList, 1, False, "RefineStove")
+        GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_PDict_AlchemyLearnState, alchemyID, 1)
+        Sycn_AlchemyMsg(curPlayer, alchemyID, False)
+    elif doType == 1:
+        if not hasLearn:
+            GameWorld.DebugLog('丹方未学习!,不可炼丹')
+            return
+        if curAlchemyItemID:
+            GameWorld.DebugLog('当前丹类型已在炼丹中! curAlchemyItemID=%s' % curAlchemyItemID)
+            return
+        # 基础固定消耗
+        needMaterialDict = alchemyIpyData.GetMaterial()
+               
+        itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
+        lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needMaterialDict, itemPack, False)
+        if lackItemDict:
+            GameWorld.DebugLog("配方材料不足!alchemyID=%s,needMaterialDict=%s,lackItemDict=%s,hasItemDict=%s" 
+                               % (alchemyItemID, needMaterialDict, lackItemDict, delInfoDict), playerID)
+            return
+        #扣消耗
+        ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, ChConfig.ItemDel_Alchemy)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyItemID % alchemType, alchemyItemID)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyStartTime % alchemyID, curTime)
         
-        alchemyItemList = specAlchemyIpyData.GetAlchemyItem()
-        alchemyCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyCountSpec % specID)
-        SpecialAlchemyDict = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 2)
-        SpecialAlchemyCountItemDict = SpecialAlchemyDict.get(specID, {})
-    else:
-        alchemyItemList = alchemyIpyData.GetAlchemyItem()
-        alchemyCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyCount % alchemyID)
-        SpecialAlchemyDict = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 1)
-        SpecialAlchemyCountItemDict = SpecialAlchemyDict.get(alchemyID, {})
+        Sycn_AlchemyMsg(curPlayer, alchemyID, False)
+        #日常任务
+        costItemCnt = sum(needMaterialDict.values())
+        PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_RefineStove, costItemCnt)
         
-    updAlchemyCount = 0
-    if SpecialAlchemyCountItemDict:
-        nextAlchemyCount = alchemyCount + 1
-        if nextAlchemyCount <= max(SpecialAlchemyCountItemDict):
-            updAlchemyCount = nextAlchemyCount # 只要还没达到最大洗练次数特殊产出,则每次累加次数
-            # 非特殊材料配方的情况下,达到指定次数则使用特殊次数指定产出库
-            if nextAlchemyCount in SpecialAlchemyCountItemDict:
-                alchemyItemList = SpecialAlchemyCountItemDict[nextAlchemyCount]
-                GameWorld.DebugLog("炼丹次数特殊产出库: 炼丹编号=%s,特殊ID=%s,次数=%s,特殊产出库=%s" 
-                                   % (alchemyID, specID, nextAlchemyCount, alchemyItemList), playerID)
-                
-    # 去除限制产出的物品
-    outPutCountLimitDict = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 3)
-    if outPutCountLimitDict:
-        limitItemInfoList = []
-        alchemyItemList = copy.copy(alchemyItemList)
-        for itemInfo in alchemyItemList:
-            itemID = itemInfo[1]
-            if itemID not in outPutCountLimitDict:
-                continue
-            limitCount = outPutCountLimitDict[itemID]
-            outputCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyOutputCount % itemID)
-            if outputCount >= limitCount:
-                limitItemInfoList.append(itemInfo)
-                GameWorld.DebugLog("已达到最大产出次数,从产出库中移除! alchemyItemList=%s,itemID=%s,outputCount=%s,limitCount=%s" 
-                                   % (alchemyItemList, itemID, outputCount, limitCount), playerID)
-                
-        for limitItemInfo in limitItemInfoList:
-            alchemyItemList.remove(limitItemInfo)
-            
-    if not alchemyItemList:
-        GameWorld.DebugLog("配方产出物品配置错误!alchemyID=%s,specID=%s" % (alchemyID, specID), playerID)
-        return
-        
-    packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, 1) 
-    if not packSpace:
-        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")
-        return
-    
-    # 基础固定消耗
-    needMaterialDict = alchemyIpyData.GetMaterial()
-    # 特殊配方额外消耗
-    if specAlchemyIpyData:
-        needMaterialDict = copy.deepcopy(needMaterialDict)
-        needMaterialDict[specAlchemyIpyData.GetMaterialID()] = specAlchemyIpyData.GetMaterialCnt()
-        
-    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
-    lackItemDict, delInfoDict = ItemCommon.GetCostItemIndexList(needMaterialDict, itemPack, False)
-    if lackItemDict:
-        GameWorld.DebugLog("配方材料不足!alchemyID=%s,specID=%s,needMaterialDict=%s,lackItemDict=%s,hasItemDict=%s" 
-                           % (alchemyID, specID, needMaterialDict, lackItemDict, delInfoDict), playerID)
-        return
-    
-    makeItemInfo = GameWorld.GetResultByWeightList(alchemyItemList)
-    if not makeItemInfo:
-        GameWorld.ErrLog("配方合成结果错误!alchemyID=%s,specID=%s" % (alchemyID, specID), playerID)
-        return
-    makeItemID, itemCount = makeItemInfo
-    GameWorld.DebugLog("合成配方: alchemyID=%s,specID=%s,makeItemID=%s,itemCount=%s,alchemyItemList=%s" 
-                       % (alchemyID, specID, makeItemID, itemCount, alchemyItemList), playerID)
-    #检查按丹炉等级进阶的丹药
-    makeItemID = __GetAlchemyUpItemID(makeItemID, alchemyLV, alchemyIpyData.GetAlchemyUp())
-    makeItemData = GameWorld.GetGameData().GetItemByTypeID(makeItemID)
-    if not makeItemData:
-        return
-    
-    if updAlchemyCount:
-        if specID:
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyCountSpec % specID, updAlchemyCount)
+    elif doType == 2:
+        if curAlchemyItemID != alchemyItemID:
+            GameWorld.DebugLog('停止丹药ID错误 curAlchemyItemID=%s' % curAlchemyItemID)
+            return
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyItemID % alchemType, 0)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyStartTime % alchemyID, 0)
+        Sycn_AlchemyMsg(curPlayer, alchemyID, False)
+    elif doType == 3:
+        if curAlchemyItemID != alchemyItemID:
+            GameWorld.DebugLog('开炉丹药ID错误 curAlchemyItemID=%s' % curAlchemyItemID)
+            return
+        startTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyStartTime % alchemyID)
+        passTime = max(0, curTime - startTime)
+        if passTime < alchemyIpyData.GetNeedTime():
+            GameWorld.DebugLog('开炉丹药,时间未到  passTime=%s' % passTime)
+            return
+        #成功率
+        if alchemType == 2:
+            successRate = ShareDefine.Def_MaxRateValue  #仙丹必定成功
         else:
-            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyCount % alchemyID, updAlchemyCount)
-        GameWorld.DebugLog("更新炼丹次数累计: alchemyID=%s,特殊ID=%s,次数=%s" % (alchemyID, specID, updAlchemyCount), playerID)
+            #灵丹成功率公式 参数 curLuckValue:慧根  alchemyLV:炼丹等级 alchemyQuality:丹药等级  qualityNeedLuck:要求慧根
+            alchemyQuality = alchemyIpyData.GetAlchemyQuality()
+            qualityNeedLuck = IpyGameDataPY.GetFuncEvalCfg('alchemySuccess', 2, {}).get(alchemyQuality, 0)
+            successRate = eval(IpyGameDataPY.GetFuncCompileCfg('alchemySuccess'))
+        isSuccess = GameWorld.CanHappen(successRate)
+        resultCnt = 0  #丹药数量 0代表失败
+        if isSuccess:
+            needSpace = 1
+            packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
+            if needSpace > packSpace:
+                PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")
+                return
+            ipyData = IpyGameDataPY.InterpolationSearch('AlchemyResult', 'LuckValue', curLuckValue, {'AlchemyQuality':alchemyIpyData.GetAlchemyQuality()})
+            if not ipyData:
+                GameWorld.ErrLog('AlchemyResult 配置错误 未找到该丹方数量 alchemyItemID=%s' % alchemyItemID, playerID)
+                return
+            resultCnt = GameWorld.GetResultByRandomList(ipyData.GetCntRateList())
+            if not resultCnt:
+                GameWorld.ErrLog('AlchemyResult 配置错误 未随机出该丹方数量alchemyItemID=%s' % alchemyItemID, playerID)
+                return
+            makeItemData = GameWorld.GetGameData().GetItemByTypeID(alchemyItemID)
+            if not makeItemData:
+                return
+            ItemControler.GivePlayerItem(curPlayer, alchemyItemID, resultCnt, 0, [IPY_GameWorld.rptItem],
+                                     event=[ChConfig.ItemGive_Refine, False, {}])
+            #紫色及以上全服广播
+            notifyColor = IpyGameDataPY.GetFuncCfg("AlchemyNotify", 1)
+            needNotifyItemIDList = IpyGameDataPY.GetFuncEvalCfg("AlchemyNotify", 2)
+            notNotifyItemIDList = IpyGameDataPY.GetFuncEvalCfg("AlchemyNotify", 3)
+            if alchemyItemID not in notNotifyItemIDList and (alchemyItemID in needNotifyItemIDList or makeItemData.GetItemColor() >= notifyColor):
+                PlayerControl.WorldNotify(0, "AchemyGreatSuccess", [curPlayer.GetPlayerName(), alchemyItemID])
+
+        #重置
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyItemID % alchemType, 0)
+        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyStartTime % alchemyID, 0)
+        #加经验
+        addExp = alchemyIpyData.GetAlchemyExp()
+        AddRefineExp(curPlayer, addExp, alchemyLV)
+        GameWorld.DebugLog('炼丹结果 alchemyItemID=%s,successRate=%s,isSuccess=%s,resultCnt=%s' % (alchemyItemID, successRate, isSuccess, resultCnt), playerID)
+    
+        Sycn_AlchemyMsg(curPlayer, alchemyID, False, alchemyItemID, resultCnt)
+                    
+        #完成1次炼丹成就
+        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_RefineItem, 1)
+        #完成1次X品质物品炼丹成就
+        #PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_RefineStoveColor, 1, [makeItemData.GetItemColor()])
+        #任务
+        #EventShell.EventRespons_RefineItem(curPlayer, alchemyIpyData.GetNeedAlchemyLV())
         
-    #扣消耗
-    delItemHasBind = ItemCommon.DelCostItem(curPlayer, itemPack, delInfoDict, ChConfig.ItemDel_Alchemy)
-    
-    #加经验
-    addExp = alchemyIpyData.GetAlchemyExp()
-    if specAlchemyIpyData:
-        addExp += specAlchemyIpyData.GetAlchemyExp()
-    AddRefineExp(curPlayer, addExp)
-    
-    #加产出次数
-    if makeItemID in outPutCountLimitDict:
-        outputCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyOutputCount % makeItemID) + 1
-        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyOutputCount % makeItemID, outputCount)
-        GameWorld.DebugLog("更新炼丹产出特殊物品次数: makeItemID=%s,outputCount=%s" % (makeItemID, outputCount), playerID)
-        
-    #给物品
-    notBindItemList = IpyGameDataPY.GetFuncEvalCfg("SpecialAlchemy", 4) # 固定不绑定的物品
-    if makeItemID in notBindItemList:
-        makeItemBind = False
-    else:
-        makeItemBind = delItemHasBind
-    ItemControler.GivePlayerItem(curPlayer, makeItemID, itemCount, 0, [IPY_GameWorld.rptItem], 
-                                 event=[ChConfig.ItemGive_Refine, False, {}])
-    
-    Sycn_AlchemyMsg(curPlayer, makeItemID)
-    
-    #紫色及以上全服广播
-    notifyColor = IpyGameDataPY.GetFuncCfg("AlchemyNotify", 1)
-    needNotifyItemIDList = IpyGameDataPY.GetFuncEvalCfg("AlchemyNotify", 2)
-    notNotifyItemIDList = IpyGameDataPY.GetFuncEvalCfg("AlchemyNotify", 3)
-    if makeItemID not in notNotifyItemIDList and (makeItemID in needNotifyItemIDList or makeItemData.GetItemColor() >= notifyColor):
-        PlayerControl.WorldNotify(0, "AchemyGreatSuccess", [curPlayer.GetPlayerName(), makeItemID])
-        
-    #完成1次炼丹成就
-    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_RefineItem, 1)
-    #完成1次X品质物品炼丹成就
-    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_RefineStoveColor, 1, [makeItemData.GetItemColor()])
-    #任务
-    EventShell.EventRespons_RefineItem(curPlayer, alchemyIpyData.GetNeedAlchemyLV())
-    #日常任务
-    costItemCnt = sum(needMaterialDict.values())
-    PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_RefineStove, costItemCnt)
-    PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, 1)
-    PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, 1)
-    PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_Alchemy, 1)
+        PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, 1)
+        PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_RefineStove, 1)
+        PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_Alchemy, 1)
     return 
 
-def __GetAlchemyUpItemID(itemID, alchemyLV, alchemyUpCfg):
-    #获取按丹炉等级进阶的丹药ID
-    if not alchemyUpCfg:
-        return itemID
-    itemIDStr = str(itemID)
-    upItemList = []
-    for alchemyUpItemDict in alchemyUpCfg:
-        if itemIDStr in alchemyUpItemDict:
-            for upID, upLV in alchemyUpItemDict.items():
-                upItemList.append([upLV, int(upID)])
-                
-    if not upItemList:
-        return itemID
-    upItemList.sort(reverse=True)
-    for upLV, makeItemID in upItemList:
-        if alchemyLV >= upLV:
-            GameWorld.DebugLog("    获得进阶丹药: itemID=%s to upItemID=%s" % (itemID, makeItemID))
-            return makeItemID
-    return itemID
 
-def AddRefineExp(curPlayer, addExp):
+def AddRefineExp(curPlayer, addExp, alchemyLV):
     #增加炼丹炉经验
     if addExp <= 0:
         return
     
-    alchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
     alchemyExp = min(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyExp) + addExp, ShareDefine.Def_UpperLimit_DWord)
     GameWorld.DebugLog("增加炼丹经验: alchemyLV=%s,addExp=%s,alchemyExp=%s" % (alchemyLV, addExp, alchemyExp), curPlayer.GetPlayerID())
     
@@ -282,34 +242,45 @@
     GameWorld.DebugLog("升级后剩余经验: %s" % alchemyExp, curPlayer.GetPlayerID())
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyLV, alchemyLV)
     PlayerSuccess.UptateSuccessProgress(curPlayer, ShareDefine.SuccType_AlchemyLV, alchemyLV)
-    
-    RefreshStoveAttr(curPlayer)
-    
-    # 解锁广播
-    ipyGameData = IpyGameDataPY.IPY_Data()
-    for i in xrange(ipyGameData.GetAlchemyCount()):
-        ipyData = ipyGameData.GetAlchemyByIndex(i)
-        if alchemyLV == ipyData.GetNeedAlchemyLV():
-            PlayerControl.WorldNotify(0, "FurnaceLVUp", [curPlayer.GetPlayerName(), alchemyLV, ipyData.GetAlchemyID()])
-            break
-        
     return True
 
-def Sycn_AlchemyMsg(curPlayer, itemID=0):
+
+def Sycn_AlchemyMsg(curPlayer, alchemyID=0, isAll=True, itemID=0, itemCnt=0):
     # 通知客户端炼丹炉信息
-    if not itemID and not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_RefineStove):
+    if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_RefineStove):
         return
     pack = ChPyNetSendPack.tagMCPlayerStoveMsg()
     pack.StoveExp = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyExp)
     pack.StoveLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
     pack.ItemID = itemID
+    pack.ItemCnt = itemCnt
+    pack.InfoList = []
+    syncItemIDList = []
+    if isAll:
+        ipyMgr = IpyGameDataPY.IPY_Data()
+        for i in xrange(ipyMgr.GetAlchemyCount()):
+            ipyData = ipyMgr.GetAlchemyByIndex(i)
+            alchemyID = ipyData.GetID()
+            if GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_AlchemyLearnState, alchemyID):
+                syncItemIDList.append(alchemyID)
+    elif alchemyID and GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_PDict_AlchemyLearnState, alchemyID):
+        syncItemIDList = [alchemyID]
+    
+    for alchemyID in syncItemIDList:
+        StoveInfo = ChPyNetSendPack.tagMCPlayerStoveInfo()
+        StoveInfo.AlchemyID = alchemyID
+        StoveInfo.StartTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyStartTime % alchemyID)
+        pack.InfoList.append(StoveInfo)
+    pack.StoveCnt = len(pack.InfoList)
     NetPackCommon.SendFakePack(curPlayer, pack)
     return
+
 
 def RefreshStoveAttr(curPlayer):
     CalcStoveAttr(curPlayer)
     PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()
     return
+
 
 def CalcStoveAttr(curPlayer):
     # 果实加成
@@ -317,38 +288,7 @@
     fightPowerEx = PlayerAttrFruit.CalcAttrFruitAddAtrr(curPlayer, allAttrYaoList, ShareDefine.Def_AttrFruitFunc_Stove)
     PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_StoveYao, allAttrYaoList)
     curPlayer.SetDict(ChConfig.Def_PlayerKey_MFPEx % ShareDefine.Def_MFPType_StoveYao, fightPowerEx)
-    
-    allAttrList = [{} for _ in range(4)]
-    alchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
-    stoveIpyData = IpyGameDataPY.GetIpyGameData("RefineStove", alchemyLV)
-    if stoveIpyData:
-        attrTypeList = stoveIpyData.GetAddAttrType()
-        attrValueList = stoveIpyData.GetAddAttrNum()
-        for i, attrID in enumerate(attrTypeList):
-            PlayerControl.CalcAttrDict_Type(attrID, attrValueList[i], allAttrList)
-    
-    PlayerControl.SetCalcAttrListValue(curPlayer, ChConfig.Def_CalcAttrFunc_Stove, allAttrList)
     return
-
-g_needAlchemyLVDict = {}
-def GetIsCanOutByAlchemyLV(curPlayer, itemID):
-    #判断当前丹炉等级是否可产出该丹药
-    global g_needAlchemyLVDict
-    if not g_needAlchemyLVDict:
-        ipyMgr = IpyGameDataPY.IPY_Data()
-        for i in xrange(ipyMgr.GetAlchemyCount()):
-            ipyData = ipyMgr.GetAlchemyByIndex(i)
-            needAlchemyLV = ipyData.GetNeedAlchemyLV()
-            itemList = ipyData.GetAlchemyItem()
-            for itemInfo in itemList:
-                g_needAlchemyLVDict[itemInfo[1]] = needAlchemyLV
-        for i in xrange(ipyMgr.GetAlchemySpecCount()):
-            ipyData = ipyMgr.GetAlchemySpecByIndex(i)
-            needAlchemyLV = ipyData.GetNeedAlchemyLV()
-            itemList = ipyData.GetAlchemyItem()
-            for itemInfo in itemList:
-                g_needAlchemyLVDict[itemInfo[1]] = needAlchemyLV
-    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV) >= g_needAlchemyLVDict.get(itemID, 0)
 
 
 #// A5 14 祈福丹药 #tagCMPrayElixir
@@ -363,7 +303,7 @@
     prayCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyPrayCnt)
     limitCnt = PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_PrayElixir)
     if prayCnt >= limitCnt:
-        GameWorld.DebugLog('今日祈福丹药次数已满!prayCnt=%s'%prayCnt)
+        GameWorld.DebugLog('今日祈福丹药次数已满!prayCnt=%s' % prayCnt)
         return
     packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, 1) 
     if not packSpace:
@@ -375,9 +315,9 @@
     newItemInfoList = []
     for itemInfo in alchemyItemList:
         itemID = itemInfo[1]
-        if not GetIsCanOutByAlchemyLV(curPlayer, itemID):
-            #GameWorld.DebugLog('祈福丹药,炼丹等级未达到,移除产出库!itemID=%s'%itemID)
-            continue
+#        if not GetIsCanOutByAlchemyLV(curPlayer, itemID):
+#            #GameWorld.DebugLog('祈福丹药,炼丹等级未达到,移除产出库!itemID=%s'%itemID)
+#            continue
         if PlayerAttrFruit.IsFruitEatFull(curPlayer, itemID):
             #GameWorld.DebugLog('祈福丹药,使用次数已满,移除产出库!itemID=%s'%itemID)
             continue
@@ -400,10 +340,9 @@
     if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costMoney, ChConfig.Def_Cost_AlchemyPray):
         return
     #给物品
-    ItemControler.GivePlayerItem(curPlayer, makeItemID, itemCount, 0, [IPY_GameWorld.rptItem], 
+    ItemControler.GivePlayerItem(curPlayer, makeItemID, itemCount, 0, [IPY_GameWorld.rptItem],
                                  event=[ChConfig.ItemGive_Refine, False, {}])
     #GameWorld.DebugLog('makeItemID=%s,newItemInfoList=%s'%(makeItemID, newItemInfoList))
-    
     
     #紫色及以上全服广播
     notifyColor = IpyGameDataPY.GetFuncCfg("AlchemyNotify", 1)
@@ -413,11 +352,13 @@
         PlayerControl.WorldNotify(0, "BlastfurnaceBlessing", [curPlayer.GetPlayerName(), makeItemID])
         
     #更新次数
-    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyPrayCnt, prayCnt+1)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_AlchemyPrayCnt, prayCnt + 1)
     Sycn_AlchemyPrayMsg(curPlayer, makeItemID)
     return
 
+
 def Sycn_AlchemyPrayMsg(curPlayer, itemID=0):
+    return
     #祈福丹药结果
     if not itemID and not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_RefineStove):
         return
@@ -425,4 +366,4 @@
     pack.PrayCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyPrayCnt)
     pack.ItemID = itemID
     NetPackCommon.SendFakePack(curPlayer, pack)
-    return
\ No newline at end of file
+    return

--
Gitblit v1.8.0