From c562008bec642a25245295eeec567081bc4e4c42 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期四, 18 四月 2019 14:29:23 +0800
Subject: [PATCH] 6459 【后端】【2.0】缥缈仙域开发单(草园)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearCollectNPCCnt.py                     |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py                                        |    1 
 ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py                                                         |    9 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py                                    |  108 +++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py  |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ClientServerReceiveMsg.py |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py                                        |    4 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py          |   11 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py  |   65 +++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py                               |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFairyDomain.py                           |    2 
 ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py                                                         |  108 +++++++
 ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py                                                 |    4 
 ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py                                            |    3 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py                            |   17 +
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                      |   35 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py                                    |    6 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_196.py                               |  352 +++++-----------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py                                      |   72 ++++
 PySysDB/PySysDBPY.h                                                                                                       |   13 
 ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py                                                             |    1 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                               |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py                       |   15 -
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py                                           |    7 
 24 files changed, 529 insertions(+), 316 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 48e5362..4ac2fac 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -1023,6 +1023,19 @@
 	BYTE		NotifyCollectResult;	//是否通知采集结果
 };
 
+//宝箱怪表
+
+struct tagTreasureNPC
+{
+	DWORD		_NPCID;	//宝箱怪NPCID
+	dict		AttackCountDropWeightInfo;	//攻击次数对应掉落权重饼图 {次数:[[权重, [物品ID,个数,是否拍品]], ...], ...}
+	list		AttackDropWeightList;	//常规攻击权重饼图 [[权重, [物品ID,个数,是否拍品]], ...]
+	list		AttackDropWeightListEx;	//额外掉落权重饼图库,每次攻击都会掉落  [[权重, [物品ID,个数,是否拍品]], ...]
+	BYTE		DropCountEx;	//额外库执行次数
+	BYTE		AlchemyDiffLV;	//过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
+	char		NotDropNotify;	//没有掉落时提示信息
+};
+
 //宝箱表开启
 
 struct tagChests
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
index d3f3dda..74be579 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ChPyNetSendPack.py
@@ -15532,6 +15532,114 @@
 
 
 #------------------------------------------------------
+# A3 25 NPC已攻击次数信息 #tagMCNPCAttackCountInfo
+
+class  tagMCNPCAttackCount(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("NPCID", c_int),    
+                  ("AttackCount", c_ubyte),    #已攻击次数
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        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.NPCID = 0
+        self.AttackCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCNPCAttackCount)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A3 25 NPC已攻击次数信息 //tagMCNPCAttackCountInfo:
+                                NPCID:%d,
+                                AttackCount:%d
+                                '''\
+                                %(
+                                self.NPCID,
+                                self.AttackCount
+                                )
+        return DumpString
+
+
+class  tagMCNPCAttackCountInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    NPCAttackCountList = list()    #(vector<tagMCNPCAttackCount> NPCAttackCountList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0x25
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temNPCAttackCountList = tagMCNPCAttackCount()
+            _pos = temNPCAttackCountList.ReadData(_lpData, _pos)
+            self.NPCAttackCountList.append(temNPCAttackCountList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0x25
+        self.Count = 0
+        self.NPCAttackCountList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.NPCAttackCountList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.NPCAttackCountList[i].GetLength(), self.NPCAttackCountList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                NPCAttackCountList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCNPCAttackCountInfo=tagMCNPCAttackCountInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNPCAttackCountInfo.Head.Cmd,m_NAtagMCNPCAttackCountInfo.Head.SubCmd))] = m_NAtagMCNPCAttackCountInfo
+
+
+#------------------------------------------------------
 # A3 26 NPCID已采集次数信息 #tagMCNPCIDCollectionCntInfo
 
 class  tagMCNPCIDCollectionCnt(Structure):
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
index 50ac56d..9aa5544 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GameWorldLogic/CrossRealmMsg.py
@@ -271,7 +271,8 @@
             PlayerFB.CrossServerMsg_EnterFBRet(msgData, tick)
             
         # 需要发送到地图服务器处理的
-        elif msgType in [ShareDefine.CrossServerMsg_RebornRet, ShareDefine.CrossServerMsg_CollectNPCOK, ShareDefine.CrossServerMsg_FBEnd]:
+        elif msgType in [ShareDefine.CrossServerMsg_RebornRet, ShareDefine.CrossServerMsg_CollectNPCOK, ShareDefine.CrossServerMsg_FBEnd,
+                         ShareDefine.CrossServerMsg_NPCAttackCount]:
             MapServer_ClientServerReceiveMsg(msgType, msgData)
             
         elif msgType == ShareDefine.CrossServerMsg_CrossServerState:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
index 845d9f9..778f451 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/CrossRealmPlayer.py
@@ -206,12 +206,12 @@
     PlayerControl.SetCrossMapID(curPlayer, 0)
     return
 
-def SendCrossRealmReg(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0):
+def SendCrossRealmReg(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0, lineID=0):
     # 发送跨服账号注册上传数据
     
     # 设置上传数据的活动类型
     curPlayer.SetDict(ChConfig.Def_PlayerKey_CrossRegisterMap, registerMap)
-    sysMsg = str([registerMap, mapID, dataMapID, copyMapID, posX, posY])
+    sysMsg = str([registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID])
     curPlayer.MapServer_QueryPlayerResult(0, 0, "CrossRealmReg", sysMsg, len(sysMsg))            
     GameWorld.Log("SendCrossRealmReg registerMap=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s" 
                   % (registerMap, mapID, dataMapID, copyMapID, posX, posY), curPlayer.GetPlayerID())
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
index 81bd7b6..b22e5d8 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFB.py
@@ -154,14 +154,14 @@
         return
     
     playerIDList = [playerID]
-    retInfo = [playerIDList, dataMapID, mapID, copyMapID]
+    retInfo = [playerIDList, dataMapID, mapID, copyMapID, funcLineID]
     CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])
     return
 
 def CrossServerMsg_EnterFBRet(msgData, tick):
     ## 收到跨服服务器动态分配的跨服副本进入信息
     
-    playerIDList, dataMapID, mapID, copyMapID = msgData
+    playerIDList, dataMapID, mapID, copyMapID, funcLineID = msgData
     
     dynamicLineMapDict = IpyGameDataPY.GetFuncEvalCfg("CrossDynamicLineMap", 1)
     if dataMapID not in dynamicLineMapDict:
@@ -176,7 +176,7 @@
         curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
         if not curPlayer:
             continue
-        CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, posX, posY)
+        CrossRealmPlayer.SendCrossRealmReg(curPlayer, dataMapID, mapID, dataMapID, copyMapID, posX, posY, lineID=funcLineID)
         
     return
 
@@ -277,6 +277,7 @@
         return
     copyMapObj = PyGameData.g_crossDynamicLineCopyMapInfo[key]
     copyMapObj.openState = 1
+    funcLineID = copyMapObj.funcLineID
     
     # 通知子服等待中的玩家可以进入副本
     serverPlayerIDListDict = {}
@@ -291,7 +292,7 @@
     GameWorld.Log("动态分配虚拟线路启动成功,通知子服等待玩家可进入: dataMapID=%s,mapID=%s,copyMapID=%s,serverPlayerIDListDict=%s" 
                   % (dataMapID, mapID, copyMapID, serverPlayerIDListDict))
     for serverGroupID, playerIDList in serverPlayerIDListDict.items():
-        retInfo = [playerIDList, dataMapID, mapID, copyMapID]
+        retInfo = [playerIDList, dataMapID, mapID, copyMapID, funcLineID]
         CrossRealmMsg.SendMsgToClientServer(ShareDefine.CrossServerMsg_EnterFBRet, retInfo, [serverGroupID])
         
     #GameWorld.DebugLog("    PyGameData.g_crossDynamicLineInfo=%s" % PyGameData.g_crossDynamicLineInfo)
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 7d79f26..1fe0aaf 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -1211,6 +1211,7 @@
 CrossServerMsg_CollectNPCOK = "CollectNPCOK"            # 采集NPC完成
 CrossServerMsg_EnterFBRet = "EnterFBRet"                # 请求进入跨服副本返回信息
 CrossServerMsg_FBEnd = "FBEnd"                          # 完成跨服副本
+CrossServerMsg_NPCAttackCount = "NPCAttackCount"        # 攻击NPC次数记录
 
 # 子服发送跨服信息定义
 ClientServerMsg_ServerInitOK = "ServerInitOK"           # 子服启动成功
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 945c1a5..c0661a5 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -3026,6 +3026,8 @@
 Def_PlayerKey_CopyFuncAttr = "CopyFuncAttr%s"     # 玩家属性刷新中的计算属性缓存,便于buff刷新计算
 Def_Player_RefreshAttrByBuff = "PlayerAttrByBuff"   # 玩家属性刷新功能属性缓存,便于buff刷新计算, 间隔刷新
 Def_PlayerKey_ClientCustomScene = "ClientCustomScene"     # 客户端自定义场景状态
+Def_PlayerKey_ClientCustomSceneMapID = "ClientCustomSceneMapID"     # 客户端自定义场景地图ID
+Def_PlayerKey_ClientCustomSceneLineID = "ClientCustomSceneLineID"     # 客户端自定义场景功能线路ID
 Def_PlayerKey_ChangeMapID = "ChangeMapID"     # 请求切换的地图ID
 Def_PlayerKey_ResetFBLinePosX = "ResetFBLinePosX"     # 请求切换副本多合一地图功能线路ID
 Def_PlayerKey_ResetFBLinePosY = "ResetFBLinePosY"     # 请求切换副本多合一地图功能线路ID
@@ -3331,6 +3333,7 @@
 Def_Player_Dict_FBFirstEnterRecord = "FBFEntRec"  # 记录副本是否参与过,按位0 1 存储表示
 Def_FBStar_MaxKeyCnt = 5 # 暂时每个副本ID支持9*5个lineID记录
 Def_Player_Dict_ReqFBFuncLine = "ReqFBFuncLine" # 请求进入的副本功能线路
+Def_Player_Dict_ReqCrossFBFuncLine = "ReqCrossFBFuncLine" # 请求进入跨服的副本功能线路
 Def_Player_Dict_TeamFBAverageLV = "TeamFBAverageLV" # 请求进入的组队副本平均等级, 临时用,进入副本设置完后删除
 Def_Player_Dict_TeamFBMaxLV = "TeamFBMaxLV" # 请求进入的组队副本最大等级, 临时用,进入副本设置完后删除
 Def_Player_Dict_TeamFBPlayerCnt = "TeamFBPlayerCnt" # 请求进入的组队副本玩家个数, 临时用,进入副本设置完后删除
@@ -3488,6 +3491,7 @@
 Def_PDict_RecoverGainLastTime = "RecoverGainLastTime" # 上一次资源找回时的时间
 
 Def_PDict_NPCKillCount = "NPCKillCount_%s"   # NPC已击杀次数, 参数(NPCID) CCBBAA, AA存储公共装备次数,BB存储公共ID次数,CC存储私有次数
+Def_PDict_NPCAttackCount = "NPCAttackCount_%s"   # NPC已攻击次数, 参数(NPCID)
 
 Def_PDict_RedPacketInviteGet = "RedPacketInviteGet"  # 红包邀请领取
 Def_PDict_RedPacketGetState = "RedPacketGetState"  # 红包领取状态
@@ -4414,9 +4418,6 @@
 TriggerType_IsDealy,    # 是否触发致命一击 72 暂且理解为和概率是独立,有新概念产生则重定义  
 ) = range(1, 73)
 
-
-# NPC功能类型定义
-Def_NPCFuncType_Goblin = 70 # 盗宝哥布林
 
 #不可以佩戴翅膀的地图
 CanNotWearWingMapIDList = []
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
index d3f3dda..74be579 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChPyNetSendPack.py
@@ -15532,6 +15532,114 @@
 
 
 #------------------------------------------------------
+# A3 25 NPC已攻击次数信息 #tagMCNPCAttackCountInfo
+
+class  tagMCNPCAttackCount(Structure):
+    _pack_ = 1
+    _fields_ = [
+                  ("NPCID", c_int),    
+                  ("AttackCount", c_ubyte),    #已攻击次数
+                  ]
+
+    def __init__(self):
+        self.Clear()
+        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.NPCID = 0
+        self.AttackCount = 0
+        return
+
+    def GetLength(self):
+        return sizeof(tagMCNPCAttackCount)
+
+    def GetBuffer(self):
+        return string_at(addressof(self), self.GetLength())
+
+    def OutputString(self):
+        DumpString = '''// A3 25 NPC已攻击次数信息 //tagMCNPCAttackCountInfo:
+                                NPCID:%d,
+                                AttackCount:%d
+                                '''\
+                                %(
+                                self.NPCID,
+                                self.AttackCount
+                                )
+        return DumpString
+
+
+class  tagMCNPCAttackCountInfo(Structure):
+    Head = tagHead()
+    Count = 0    #(BYTE Count)
+    NPCAttackCountList = list()    #(vector<tagMCNPCAttackCount> NPCAttackCountList)
+    data = None
+
+    def __init__(self):
+        self.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0x25
+        return
+
+    def ReadData(self, _lpData, _pos=0, _Len=0):
+        self.Clear()
+        _pos = self.Head.ReadData(_lpData, _pos)
+        self.Count,_pos = CommFunc.ReadBYTE(_lpData, _pos)
+        for i in range(self.Count):
+            temNPCAttackCountList = tagMCNPCAttackCount()
+            _pos = temNPCAttackCountList.ReadData(_lpData, _pos)
+            self.NPCAttackCountList.append(temNPCAttackCountList)
+        return _pos
+
+    def Clear(self):
+        self.Head = tagHead()
+        self.Head.Clear()
+        self.Head.Cmd = 0xA3
+        self.Head.SubCmd = 0x25
+        self.Count = 0
+        self.NPCAttackCountList = list()
+        return
+
+    def GetLength(self):
+        length = 0
+        length += self.Head.GetLength()
+        length += 1
+        for i in range(self.Count):
+            length += self.NPCAttackCountList[i].GetLength()
+
+        return length
+
+    def GetBuffer(self):
+        data = ''
+        data = CommFunc.WriteString(data, self.Head.GetLength(), self.Head.GetBuffer())
+        data = CommFunc.WriteBYTE(data, self.Count)
+        for i in range(self.Count):
+            data = CommFunc.WriteString(data, self.NPCAttackCountList[i].GetLength(), self.NPCAttackCountList[i].GetBuffer())
+        return data
+
+    def OutputString(self):
+        DumpString = '''
+                                Head:%s,
+                                Count:%d,
+                                NPCAttackCountList:%s
+                                '''\
+                                %(
+                                self.Head.OutputString(),
+                                self.Count,
+                                "..."
+                                )
+        return DumpString
+
+
+m_NAtagMCNPCAttackCountInfo=tagMCNPCAttackCountInfo()
+ChNetPackDict[eval("0x%02x%02x"%(m_NAtagMCNPCAttackCountInfo.Head.Cmd,m_NAtagMCNPCAttackCountInfo.Head.SubCmd))] = m_NAtagMCNPCAttackCountInfo
+
+
+#------------------------------------------------------
 # A3 26 NPCID已采集次数信息 #tagMCNPCIDCollectionCntInfo
 
 class  tagMCNPCIDCollectionCnt(Structure):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearCollectNPCCnt.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearCollectNPCCnt.py
index e2b742e..88c7341 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearCollectNPCCnt.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/ClearCollectNPCCnt.py
@@ -50,5 +50,8 @@
         NPCCommon.SyncCollNPCTime(curPlayer, resetNPCIDList)
         
     GameWorld.DebugAnswer(curPlayer, "重置采集NPC成功")
+    
+    npcID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
+    NPCCommon.UpdateNPCAttackCount(curPlayer, npcID, 0)
     return
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py
index 7754419..301da44 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py
@@ -188,7 +188,7 @@
             ownerName = curPlayer.GetPlayerName()
         giveItemList = __GetDemonKingPrizeItemList(curPlayer, mapID, funcLineID, eventID, isOwner)
         GameWorld.Log("玩家奖励: %s" % giveItemList, playerID)
-        ChItem.DropItem(curPlayer, giveItemList, bossID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True)
+        ChItem.DoMapDropItem(curPlayer, giveItemList, bossID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True)
         #curPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)
         if not isCrossServer:
             __SetDemonKingVisitState(curPlayer, mapID, funcLineID, PlayerFairyDomain.FDEventState_Visited)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py
index 4bf5191..d71abe4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py
@@ -22,15 +22,21 @@
 import IpyGameDataPY
 import PyGameData
 import NPCCommon
+import PlayerControl
+import ChConfig
 
-def DoResetCrossGrassland(curPlayer, eventType):
+def DoResetCrossGrassland(curPlayer, eventType, fdeventID):
     ## 草园重置
     
     resetCollectType = 10 + eventType
     NPCCommon.DoResetCollectNPCTimeByType(curPlayer, [resetCollectType])
     
     # 宝箱怪次数重置
-    
+    if eventType == PlayerFairyDomain.FDEventType_GrasslandXian:
+        npcID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
+        if npcID:
+            NPCCommon.UpdateNPCAttackCount(curPlayer, [npcID], 0)
+            
     return
     
 def __SetGrasslandVisitState(curPlayer, mapID, lineID, state):
@@ -111,10 +117,55 @@
     __SetGrasslandVisitState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visiting)
     return
 
-## 给自定义副本奖励后续处理
-## @return: 返回结算副本over信息字典,不含jsonItem信息
-def OnGiveCustomFBPrizeOK(curPlayer, mapID, lineID):
+def DoCheckUpdateGrasslandEnd(curPlayer):
+    ## 检查更新草园已拜访完成
+    
+    grasslandMapIDList = [ChConfig.Def_FBMapID_CrossGrasslandLing, ChConfig.Def_FBMapID_CrossGrasslandXian]
+    crossMapID = PlayerControl.GetCrossMapID(curPlayer)
+    clientCustomSceneMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneMapID)
+    if crossMapID in grasslandMapIDList:
+        mapID = crossMapID
+        lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqCrossFBFuncLine)
+    elif clientCustomSceneMapID in grasslandMapIDList:
+        mapID = clientCustomSceneMapID
+        lineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomSceneLineID)
+    else:
+        return
+    
+    # 采集次数是否已用完
+    collNPCIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("MapRefreshNPC", mapID)
+    if not collNPCIpyDataList:
+        return
+    
+    for collIpyData in collNPCIpyDataList:
+        npcIDList = collIpyData.GetNPCIDList()
+        for npcID in npcIDList:
+            collectNPCIpyData = IpyGameDataPY.GetIpyGameData("CollectNPC", npcID)
+            if not collectNPCIpyData:
+                return
+            limitMaxTime = collectNPCIpyData.GetMaxCollectCount()
+            totalCollTime = NPCCommon.GetTodayCollectCount(curPlayer, npcID)
+            if totalCollTime < limitMaxTime:
+                GameWorld.DebugLog("草园NPC采集次数未用完! npcID=%s,totalCollTime=%s < limitMaxTime=%s" % (npcID, totalCollTime, limitMaxTime))
+                return
+            
+    # 宝箱怪攻击次数是否已用完
+    if mapID == ChConfig.Def_FBMapID_CrossGrasslandXian:
+        boxNPCID = IpyGameDataPY.GetFuncCfg("CrossGrasslandCfg", 1)
+        boxNPCIpyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", boxNPCID)
+        if not boxNPCIpyData:
+            return
+        attackCountDropWeightInfo = boxNPCIpyData.GetAttackCountDropWeightInfo()
+        if not attackCountDropWeightInfo:
+            return
+        maxAttackCount = max(attackCountDropWeightInfo)
+        attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % boxNPCID)
+        if attackCount < maxAttackCount:
+            GameWorld.DebugLog("草园宝箱怪攻击次数未用完! boxNPCID=%s,attackCount=%s < maxAttackCount=%s" % (boxNPCID, attackCount, maxAttackCount))
+            return
+        
     __SetGrasslandVisitState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visited)
-    overDict = {}
-    return overDict
+    GameWorld.DebugLog("设置草园已完成!mapID=%s, lineID=%s" % (mapID, lineID))
+    return
+
 
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index ed73d5e..8eaff69 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -825,6 +825,16 @@
                         ("BYTE", "NotifyCollectResult", 0),
                         ),
 
+                "TreasureNPC":(
+                        ("DWORD", "NPCID", 1),
+                        ("dict", "AttackCountDropWeightInfo", 0),
+                        ("list", "AttackDropWeightList", 0),
+                        ("list", "AttackDropWeightListEx", 0),
+                        ("BYTE", "DropCountEx", 0),
+                        ("BYTE", "AlchemyDiffLV", 0),
+                        ("char", "NotDropNotify", 0),
+                        ),
+
                 "Chests":(
                         ("DWORD", "ChestsItemID", 1),
                         ("DWORD", "CostItemID", 0),
@@ -3096,6 +3106,27 @@
     def GetAlchemyDiffLV(self): return self.AlchemyDiffLV # 过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
     def GetNotifyCollectResult(self): return self.NotifyCollectResult # 是否通知采集结果
 
+# 宝箱怪表
+class IPY_TreasureNPC():
+    
+    def __init__(self):
+        self.NPCID = 0
+        self.AttackCountDropWeightInfo = {}
+        self.AttackDropWeightList = []
+        self.AttackDropWeightListEx = []
+        self.DropCountEx = 0
+        self.AlchemyDiffLV = 0
+        self.NotDropNotify = ""
+        return
+        
+    def GetNPCID(self): return self.NPCID # 宝箱怪NPCID
+    def GetAttackCountDropWeightInfo(self): return self.AttackCountDropWeightInfo # 攻击次数对应掉落权重饼图 {次数:[[权重, [物品ID,个数,是否拍品]], ...], ...}
+    def GetAttackDropWeightList(self): return self.AttackDropWeightList # 常规攻击权重饼图 [[权重, [物品ID,个数,是否拍品]], ...]
+    def GetAttackDropWeightListEx(self): return self.AttackDropWeightListEx # 额外掉落权重饼图库,每次攻击都会掉落  [[权重, [物品ID,个数,是否拍品]], ...]
+    def GetDropCountEx(self): return self.DropCountEx # 额外库执行次数
+    def GetAlchemyDiffLV(self): return self.AlchemyDiffLV # 过滤炼丹等级差,0-不过滤,>0过滤大于自身炼丹等级X级的物品
+    def GetNotDropNotify(self): return self.NotDropNotify # 没有掉落时提示信息
+
 # 宝箱表开启
 class IPY_Chests():
     
@@ -4560,6 +4591,8 @@
         self.ipyResourcesBackLen = len(self.ipyResourcesBackCache)
         self.ipyCollectNPCCache = self.__LoadFileData("CollectNPC", IPY_CollectNPC)
         self.ipyCollectNPCLen = len(self.ipyCollectNPCCache)
+        self.ipyTreasureNPCCache = self.__LoadFileData("TreasureNPC", IPY_TreasureNPC)
+        self.ipyTreasureNPCLen = len(self.ipyTreasureNPCCache)
         self.ipyChestsCache = self.__LoadFileData("Chests", IPY_Chests)
         self.ipyChestsLen = len(self.ipyChestsCache)
         self.ipyChestsAwardCache = self.__LoadFileData("ChestsAward", IPY_ChestsAward)
@@ -5018,6 +5051,8 @@
     def GetResourcesBackByIndex(self, index): return self.ipyResourcesBackCache[index]
     def GetCollectNPCCount(self): return self.ipyCollectNPCLen
     def GetCollectNPCByIndex(self, index): return self.ipyCollectNPCCache[index]
+    def GetTreasureNPCCount(self): return self.ipyTreasureNPCLen
+    def GetTreasureNPCByIndex(self, index): return self.ipyTreasureNPCCache[index]
     def GetChestsCount(self): return self.ipyChestsLen
     def GetChestsByIndex(self, index): return self.ipyChestsCache[index]
     def GetChestsAwardCount(self): return self.ipyChestsAwardLen
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
index d6ece9a..94d6e0b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/ChItem.py
@@ -53,6 +53,7 @@
 import NPCCommon
 import FBCommon
 
+import random
 import json
 #---------------------------------------------------------------------
 #导入
@@ -1781,7 +1782,7 @@
 
 #---------------------------------------------------------------------
 
-def DropItem(curPlayer, itemList, npcID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True):
+def DoMapDropItem(curPlayer, itemList, npcID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True):
     if not itemList:
         return
     if isDropDisperse:
@@ -1800,6 +1801,7 @@
     else:
         dropItemList = itemList
         
+    random.shuffle(dropItemList) # 打乱顺序
     index = 0
     playerID = curPlayer.GetPlayerID()
     gameMap = GameWorld.GetMap()
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
index 0b599b0..ba70411 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Item/UseItem/ItemCommon.py
@@ -2074,6 +2074,23 @@
             itemDict["UserData"] = itemInfo.GetUserData()
     return itemDict
 
+def GetWeightItemListByAlchemyDiffLV(curPlayer, weightList, alchemyDiffLV):
+    ## 根据炼丹等级差异等级过滤权重列表中不满足的物品,返回新的权重列表
+    resultWeightList = []
+    if alchemyDiffLV:
+        curAlchemyLV = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_AlchemyLV)
+        for itemInfo in weightList:
+            itemID = itemInfo[1][0]
+            itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
+            if not itemData:
+                continue
+            if GetItemClassLV(itemData) > curAlchemyLV + alchemyDiffLV:
+                continue
+            resultWeightList.append(itemInfo)
+    else:
+        resultWeightList = weightList
+    return resultWeightList
+
 ## =======================================================================================
 
 def SyncMakeItemAnswer(curPlayer, makeType, isSuccess, makeItemID):
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_196.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_196.py
index c3c6f73..c290592 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_196.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_196.py
@@ -1,70 +1,38 @@
 #!/usr/bin/python
 # -*- coding: GBK -*-
-#---------------------------------------------------------------------
+#-------------------------------------------------------------------------------
 #
-#---------------------------------------------------------------------
-##@package AIType_196
-# @todo: 盗宝哥布林AI
+##@package NPCAI.AIType_196
 #
-# @author: hxp
-# @date 2013-11-05
-# @version 1.9
+# @todo:盗宝哥布林/宝箱怪
+# @author hxp
+# @date 2019-04-18
+# @version 1.0
 #
-# @note: 
-# @change: "2013-11-08 18:00" hxp 修改逻辑
-# @change: "2013-11-12 14:50" hxp 掉落矩阵改为按掉落个数掉落
-# @change: "2013-12-27 12:40" hxp 增加地精夺宝地图不广播 
-# @change: "2014-01-17 11:00" hxp 修改不掉落物品由NPC是否掉落决定,增加指定可掉落配置
-# @change: "2015-03-05 11:30" hxp 修复可能会停在无法攻击区域的问题
-# @change: "2015-03-30 19:30" hxp 增加击杀流向; 击杀广播可配置特殊NPCID对应广播
-# @change: "2015-04-21 16:00" hxp 检查纠正哥布林位置(防止处于安全区或障碍点)
-# @change: "2015-04-22 11:20" xmnathan NPC死亡时防范取到NPCID为0的情况
-# @change: "2015-07-13 11:30" ljd 非一线隐藏哥布林
-#---------------------------------------------------------------------
-"""Version = 2015-07-13 11:30"""
-#---------------------------------------------------------------------
-import IPY_GameWorld
+# 详细描述: 盗宝哥布林/宝箱怪
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-04-18 15:00"""
+#-------------------------------------------------------------------------------
+
+import GameMap
+import ChConfig
 import GameWorld
 import NPCCommon
-import ChConfig
-import ReadChConfig
-import PetControl
-import GameMap
-import DataRecordPack
+import IPY_GameWorld
 import PlayerControl
+import IpyGameDataPY
+import AttackCommon
+import ItemCommon
+import GameObj
+import ChItem
 
 import random
+
 #---------------------------------------------------------------------
-#---SetDict NPC字典KEY,不存于数据库---
+
 Def_NPCKey_Goblin_AttackedTick = 'Goblin_AttackedTick'  # 哥布林被攻击时间
 Def_NPCKey_Goblin_MoveDir = 'Goblin_MoveDir'  # 哥布林移动方向
-
-(
-Def_DropItemType_Money, # 掉落物品类型 - 金钱
-Def_DropItemType_Goods, # 掉落物品类型 - 道具
-Def_DropItemType_Equip, # 掉落物品类型 - 装备
-) = range(3)
-
-(
-Def_StopTime, # 多长时间未被攻击则进入呆滞状态,毫秒
-Def_AttackedDropItemCountRate, # 每次被攻击掉落的物品个数饼图概率
-Def_AttackedDropItemTypeRate, # 每次被攻击掉落的物品类型饼图概率
-Def_DieDropGoodsCountRate, # 死亡掉落的道具个数饼图概率
-Def_DieDropEquipCountRate, # 死亡掉落的装备个数饼图概率
-Def_DieDropCountRate, # 死亡掉落物品总个数饼图概率
-Def_DropGoodsRate, # 移动/死亡掉落的道具掉落饼图概率及道具id
-Def_DropEquipModelNum, # 移动/死亡掉落装备规则模板编号,模板文件GoblinDropEquip_模板文件编号.txt
-) = range(8)
-
-
-g_filterEquipDict = {} # 装备掉落过滤字典缓存
-(
-Def_EquipModel_EquipType, # 掉落装备类型
-Def_EquipModel_LVLimit, # 掉落装备等级限制
-Def_EquipModel_QualityRate, # 掉落装备品质概率
-Def_EquipModel_DropItemList, # NPC不掉落,但这里可掉落的物品id列表
-) = range(4)
-
 
 # 移动方向
 MoveDirList = (
@@ -87,9 +55,7 @@
 #  @remarks 函数详细说明.
 def DoInit(curNPC):
     curNPC.GetNPCAngry().Init(ChConfig.Def_NormalNPCAngryCount)
-    curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # 设置被攻击时间
-    
-    DoHideGoblin(curNPC)
+    #curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, 0) # 设置被攻击时间
     return
 
 
@@ -99,15 +65,13 @@
 #  @return None
 #  @remarks 函数详细说明.
 def ProcessAI(curNPC, tick):
-    if DoHideGoblin(curNPC):
-        return
     
     npcControl = NPCCommon.NPCControl(curNPC)
     if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
         #NPC死亡, 进入死亡倒计时
         if npcControl.DieTick(tick) == 0:
             return
-
+        
     # 上一次被攻击时间
     attackedTick = curNPC.GetDictByKey(Def_NPCKey_Goblin_AttackedTick)
     
@@ -116,10 +80,8 @@
         __CheckCorrectGoblinPos(curNPC)
         return
     
-    aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
-    
     # 一定时间内未被攻击,则停止
-    if tick - attackedTick >= aiConfig[Def_StopTime]:
+    if tick - attackedTick >= 3000:
         __GoblinStop(curNPC)
         return
     
@@ -127,7 +89,7 @@
     # 如果不是移动状态,则执行移动
     if curNPCAction != IPY_GameWorld.laNPCMove:
         __Runaway(curNPC, npcControl, tick)
-
+        
     return
 
 
@@ -157,7 +119,7 @@
     
     dist = ChConfig.Def_Screen_Area * 2
     cPosX, cPosY = 0, 0
-    for i in range(0, dist * dist):
+    for _ in xrange(0, dist * dist):
         cPosX = random.randint(posX - dist, posX + dist)
         cPosY = random.randint(posY - dist, posY + dist)
         
@@ -176,11 +138,7 @@
     return
 
 
-## 哥布林移动走开
-#  @param curNPC 当前npc
-#  @param npcControl 
-#  @param tick 
-#  @return None
+## 移动走开
 def __Runaway(curNPC, npcControl, tick):
     posX = curNPC.GetPosX()
     posY = curNPC.GetPosY()
@@ -189,7 +147,7 @@
     tagPosX, tagPosY = 0, 0
     
     # 寻找目标坐标点
-    for i in range(len(MoveDirList)):
+    for _ in range(len(MoveDirList)):
         tagPosX, tagPosY = __GetRandomPos(posX, posY, moveArea, moveDir)
         # 如果返回0,0点,或者位置不变,则改变移动方向
         if (tagPosX == 0 and tagPosY == 0) or (tagPosX == posX and tagPosY == posY):
@@ -247,7 +205,7 @@
         GameWorld.ErrLog("moveDir=%s not in MoveDirList" % moveDir)
         return (0, 0)
      
-    for i in range(0, dist * dist):
+    for _ in range(0, dist * dist):
         if moveDir == Def_MoveDir_Up: # 上
             resultX = posX
             resultY = posY + dist
@@ -288,210 +246,78 @@
 #  @param tick 
 #  @return 具体伤害值
 def OnAttacked(atkObj, curNPC, skill, tick):
+    npcControl = NPCCommon.NPCControl(curNPC)
+    if GameObj.GetHP(curNPC) < GameObj.GetMaxHP(curNPC) / 2:
+        GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))
+        GameWorld.DebugLog("半血回满血!")
     curNPC.SetDict(Def_NPCKey_Goblin_AttackedTick, tick) # 设置被攻击时间
     
     # 每次被攻击掉落物品
-    __OnAttackedDropItem(atkObj, curNPC)
+    __OnAttackedDropItem(atkObj, curNPC, npcControl)
     return
+
+def OnCheckCanDie(atkObj, curNPC, skill, tick):
+    ## 检查NPC是否可死亡
+    GameObj.SetHP(curNPC, GameObj.GetMaxHP(curNPC))
+    GameWorld.DebugLog("死亡回满血!")
+    return False
 
 
 ## 每次被攻击掉落物品
 #  @param atkObj 攻击发起者
 #  @param curNPC 被攻击NPC
 #  @return None
-def __OnAttackedDropItem(atkObj, curNPC):
-    npcControl = NPCCommon.NPCControl(curNPC)
-    dropType = ChConfig.Def_NPCHurtTypeAll
-    ownerID = 0
-    
-    atkObjType = atkObj.GetGameObjType()
-    
-    # 如果是玩家,则物品拥有者属于该玩家
-    if atkObjType == IPY_GameWorld.gotPlayer:
-        dropType = ChConfig.Def_NPCHurtTypePlayer
-        ownerID = atkObj.GetPlayerID()
-        
-    # 如果是召唤兽或宠物,则物品拥有者属于对应主人
-    elif atkObjType == IPY_GameWorld.gotNPC:
-        npcObjType = atkObj.GetGameNPCObjType()
-        # 判断召唤兽主人
-        if npcObjType == IPY_GameWorld.gnotSummon:
-            curNPCDetail = GameWorld.GetObjDetail(atkObj)
-            
-            if curNPCDetail != None:
-                curNPCOwner = curNPCDetail.GetOwner()
-                summonOwner = GameWorld.GetObjDetail(curNPCOwner)
-                if summonOwner != None:
-                    # 召唤兽主人为玩家
-                    if summonOwner.GetGameObjType() == IPY_GameWorld.gotPlayer:
-                        dropType = ChConfig.Def_NPCHurtTypePlayer
-                        ownerID = summonOwner.GetPlayerID()
-                        
-        # 判断宠物主人
-        elif npcObjType == IPY_GameWorld.gnotPet:
-            curPlayer = PetControl.GetPetOwner(atkObj)
-            if curPlayer != None:
-                dropType = ChConfig.Def_NPCHurtTypePlayer
-                ownerID = curPlayer.GetPlayerID()
-    
-    aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
-    # 掉落个数
-    dropCount = GameWorld.GetResultByRandomList(aiConfig[Def_AttackedDropItemCountRate])
-    
-## 掉落规则修改,暂屏蔽,之后有用到该AI再做修改
-#    # 循环掉落
-#    for i in range(dropCount):
-#        dropItemType = GameWorld.GetResultByRandomList(aiConfig[Def_AttackedDropItemTypeRate])
-#        
-#        # 金钱
-#        if dropItemType == Def_DropItemType_Money:
-#            npcControl.DropMoney(ChConfig.Def_NPCMapDropRate, dropType, ownerID)
-#        # 道具
-#        elif dropItemType == Def_DropItemType_Goods:
-#            goodsID = GameWorld.GetResultByRandomList(aiConfig[Def_DropGoodsRate])
-#            npcControl.DropItem(goodsID, dropType, ownerID)
-#        # 装备
-#        elif dropItemType == Def_DropItemType_Equip:
-#            equipID = __GetRadomDropEquipID(aiConfig[Def_DropEquipModelNum])
-#            npcControl.DropItem(equipID, dropType, ownerID)
-    return
-
-
-## NPC死亡处理
-#  @param curNPC 死亡NPC
-#  @param HurtType 掉落类型
-#  @param HurtID 对应拥有者id
-#  @param modulus 掉落系数
-#  @return None
-def OnDie(curNPC, HurtType, HurtID):
-    #GameWorld.DebugLog("OnDieDropItem...dropType=%s, ownerID=%s" % (dropType, ownerID))
-    # 该死亡掉落无物品保护
-    dropType = ChConfig.Def_NPCHurtTypeAll
-    ownerID = 0
-    npcControl = NPCCommon.NPCControl(curNPC)
-    
-    if curNPC.GetNPCID() == 0:
-        GameWorld.ErrLog("AIType_196 OnDie NPCID=0")
+def __OnAttackedDropItem(atkObj, curNPC, npcControl):
+    attackPlayer, npcObjType = AttackCommon.GetAttackPlayer(atkObj)
+    if npcObjType:
         return
-    aiConfig = __GetGoblinConfig(curNPC.GetNPCID())
-    dropItemIDList = [] # [[itemID, count],...]
+    if not attackPlayer:
+        return
+    npcID = curNPC.GetNPCID()
+    ipyData = IpyGameDataPY.GetIpyGameDataNotLog("TreasureNPC", npcID)
+    if not ipyData:
+        return
+    attackCountDropWeightInfo = ipyData.GetAttackCountDropWeightInfo()
+    attackDropWeightList = ipyData.GetAttackDropWeightList()
+    attackDropWeightListEx = ipyData.GetAttackDropWeightListEx()
+    dropCountEx = ipyData.GetDropCountEx()
+    alchemyDiffLV = ipyData.GetAlchemyDiffLV()
     
-    # 道具掉落个数
-    dropGoodsCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropGoodsCountRate])
-    for i in range(dropGoodsCount):
-        goodsID = GameWorld.GetResultByRandomList(aiConfig[Def_DropGoodsRate])
-        dropItemIDList.append([goodsID, 1]) # 增加一个掉落道具
+    mainItemWeightList = []
+    if attackCountDropWeightInfo:
+        maxCount = max(attackCountDropWeightInfo)
+        attackCount = attackPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID) + 1
+        if attackCount <= maxCount:
+            if attackCount in attackCountDropWeightInfo:
+                mainItemWeightList = attackCountDropWeightInfo[attackCount]
+            NPCCommon.UpdateNPCAttackCount(attackPlayer, npcID, attackCount, maxCount)
+                
+    if not mainItemWeightList and attackDropWeightList:
+        mainItemWeightList = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightList, alchemyDiffLV)
         
-    # 装备掉落个数
-    dropEquipCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropEquipCountRate])
-    for i in range(dropEquipCount):
-        equipID = __GetRadomDropEquipID(aiConfig[Def_DropEquipModelNum])
-        dropItemIDList.append([equipID, 1]) # 增加一个掉落装备
+    mainItemInfo = GameWorld.GetResultByWeightList(mainItemWeightList)
     
-    # 掉落总个数
-    dropCount = GameWorld.GetResultByRandomList(aiConfig[Def_DieDropCountRate])
-    # npc超爆
-    #npcControl.NPCSuperDropByItemIDExMoney(dropItemIDList, dropType, ownerID, dropCount)
-    # 全服广播
-    mapID = GameWorld.GetMap().GetMapID()
-    if mapID not in []:
-        notifyMarkDict = ReadChConfig.GetEvalChConfig("GoblinNotify")
-        notifyMark = notifyMarkDict.get(curNPC.GetNPCID())
-        if notifyMark:
-            PlayerControl.WorldNotify(0, notifyMark, [GameWorld.GetMap().GetMapID()])  
+    if not mainItemInfo:
+        notDropNotify = ipyData.GetNotDropNotify()
+        if notDropNotify:
+            PlayerControl.NotifyCode(attackPlayer, notDropNotify)
+        return
+    
+    dropItemList = []
+    if mainItemInfo:
+        dropItemList.append(mainItemInfo)
+        
+    if attackDropWeightListEx and dropCountEx:
+        weightListEx = ItemCommon.GetWeightItemListByAlchemyDiffLV(attackPlayer, attackDropWeightListEx, alchemyDiffLV)
+        for _ in xrange(dropCountEx):
+            itemInfo = GameWorld.GetResultByWeightList(weightListEx)
+            if itemInfo:
+                dropItemList.append(itemInfo)
+                
+    if not dropItemList:
+        return
+    
+    dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY()
+    ChItem.DoMapDropItem(attackPlayer, dropItemList, npcID, dropPosX, dropPosY, isOnlySelfSee=False)
     return
 
-
-## 玩家击杀哥布林
-#  @param curNPC
-#  @param curPlayer
-#  @param skill
-#  @return 
-def OnAttackDieByPlayer(curNPC, curPlayer, skill):
-    DataRecordPack.DR_KillNPC(curPlayer, "Goblin", curNPC.GetNPCID())
-    return
-
-
-## 获取对应哥布林配置
-#  @param npcID
-#  @return 配置信息
-def __GetGoblinConfig(npcID):
-    return ReadChConfig.GetEvalChConfig('Goblin_%s' % npcID)
-
-
-## 获取随机掉落装备id
-#  @param dropEquipModelNum 装备掉落规则模板编号
-#  @return >0掉落装备id,返回0表示无法获取掉落装备id
-def __GetRadomDropEquipID(dropEquipModelNum):
-    global g_filterEquipDict
-    
-    dropEquipModel = ReadChConfig.GetEvalChConfig('GoblinDropEquip_%s' % dropEquipModelNum)
-    
-    filterItemList = g_filterEquipDict.get(dropEquipModelNum)
-    # 如果没有,则加载
-    if not filterItemList:
-        GameWorld.DebugLog("加载哥布林掉落装备模板GoblinDropEquip_%s.txt" % dropEquipModelNum)
-        itemTypeList = dropEquipModel[Def_EquipModel_EquipType]
-        itemMinLV = dropEquipModel[Def_EquipModel_LVLimit][0]
-        itemMaxLV = dropEquipModel[Def_EquipModel_LVLimit][1]
-        dropIDList = dropEquipModel[Def_EquipModel_DropItemList]
-        filterItemList = __FilterItemFromDB(itemTypeList, itemMinLV, itemMaxLV, dropIDList)
-        g_filterEquipDict[dropEquipModelNum] = filterItemList
-    
-    # 随机是否卓越
-    quality = GameWorld.GetResultByRandomList(dropEquipModel[Def_EquipModel_QualityRate])
-    
-    dropEquipIdList = filterItemList[quality]
-    
-    if not dropEquipIdList:
-        GameWorld.ErrLog("__GetRadomDropEquipID() can not find filter equip," + \
-                         "please check GoblinDropEquip_%s.txt!!!" % dropEquipModelNum)
-        return 0
-    
-    return random.choice(dropEquipIdList)
-
-
-## 从数据库中查找满足要求的物品ID
-#  @param itemTypeList: 获得的物品类型列表
-#  @param itemMinLV: 获得的物品最低等级
-#  @param itemMaxLV: 获得的物品最高等级
-#  @param dropIDList: NPC不掉落,但这里可掉落的物品id列表
-#  @return 找到的物品ID列表:[[非卓越装id列表], [卓越装id列表]]
-def __FilterItemFromDB(itemTypeList, itemMinLV, itemMaxLV, dropIDList):
-    findItemIdList = [[], []] # [[非卓越装], [卓越装]]
-    
-    for itemType in itemTypeList:
-    
-        gameData = GameWorld.GetGameData()
-        gameData.FilterItemByType(itemType) # 过滤物品类型
-        for i in range(0, gameData.GetFilterItemCount()):
-            curFindItem = gameData.GetFilterItem(i)
-            itemID = curFindItem.GetItemTypeID()
-            
-            # NPC不掉落的,且不在特定掉落id列表里的不掉落
-            if not curFindItem.GetCanNPCDrop() and itemID not in dropIDList:
-                continue
-            
-            # 不在过滤等级内,跳过
-            if curFindItem.GetLV() < itemMinLV or curFindItem.GetLV() > itemMaxLV:
-                continue
-
-            findItemIdList[1 if curFindItem.GetItemQuality() else 0].append(curFindItem.GetItemTypeID())
-    
-    GameWorld.DebugLog("哥布林掉落装备id列表=%s,卓越装备id列表=%s" % (str(findItemIdList[0]), str(findItemIdList[1])))
-    return findItemIdList
-
-## 隐藏NPC
-def DoHideGoblin(curNPC):
-    
-    # 只在一线刷, 非一线设置该NPC隐身
-    lineID = GameWorld.GetGameWorld().GetLineID()
-    if lineID != 0:
-        goblinNPCIDList = [30000,30001,30002,30003,30004,30005,30006,30007,30008,30009]
-        npcID = curNPC.GetNPCID()
-        if npcID in goblinNPCIDList and curNPC.GetVisible():
-            curNPC.SetVisible(False)
-            GameWorld.Log("非一线,隐藏该NPCID=%s!" % npcID)
-            return True
-        
-    return False
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
index fffc49e..f99b5dd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -51,6 +51,7 @@
 import PlayerFairyCeremony
 import PlayerNewFairyCeremony
 import GameLogic_CrossDemonKing
+import GameLogic_CrossGrassland
 import PlayerWeekParty
 import PlayerActLogin
 import FamilyRobBoss
@@ -5675,31 +5676,34 @@
     if collectCnt <= 0:
         return
     
+    isMaxTime = False # 是否达到了采集最大次数
     limitMaxTime = collectNPCIpyData.GetMaxCollectCount()
     if limitMaxTime > 0:
         todayCollTime = GetTodayCollectCount(curPlayer, npcID)
         canCollectCnt = max(0, limitMaxTime - todayCollTime)
         collectCnt = min(collectCnt, canCollectCnt)
         if collectCnt <= 0:
-            GameWorld.DebugLog("    该NPC已达到最大采集次数: todayCollTime=%s,limitMaxTime=%s" % (todayCollTime, limitMaxTime))
+            GameWorld.DebugLog("    该NPC已达到最大采集次数: npcID=%s,todayCollTime=%s,limitMaxTime=%s" % (npcID, todayCollTime, limitMaxTime))
             return
         
-        updCollTime = todayCollTime + collectCnt
+        curCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTime % npcID)
+        updCollTime = curCollTime + collectCnt
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
         SyncCollNPCTime(curPlayer, [npcID])
-        GameWorld.DebugLog("        增加采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime))
+        GameWorld.DebugLog("        增加采集次数: npcID=%s,todayCollTime=%s,curCollTime=%s,updCollTime=%s" % (npcID, todayCollTime, curCollTime, updCollTime))
+        isMaxTime = todayCollTime + collectCnt >= limitMaxTime
         
-    awardIitemList = []
+    awardItemList = []
     collectAwardCfg = collectNPCIpyData.GetCollectAward()
     collectAppointAwardCfg = collectNPCIpyData.GetCollectAppointAward()
     if collectAppointAwardCfg:
         collTotalTime = min(curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID) + 1, ChConfig.Def_UpperLimit_DWord)
         if collTotalTime in collectAppointAwardCfg:
-            awardIitemList.append(collectAppointAwardCfg[collTotalTime])
+            awardItemList.append(collectAppointAwardCfg[collTotalTime])
         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTimeTotal % npcID, collTotalTime)
-        #GameWorld.DebugLog("采集次数定制奖励: collTotalTime=%s,awardIitemList=%s" % (collTotalTime, awardIitemList))
+        #GameWorld.DebugLog("采集次数定制奖励: collTotalTime=%s,awardItemList=%s" % (collTotalTime, awardItemList))
         
-    if not awardIitemList:
+    if not awardItemList:
         alchemyDiffLV = collectNPCIpyData.GetAlchemyDiffLV()
         giveItemWeightList = []
         if alchemyDiffLV:
@@ -5716,15 +5720,15 @@
             giveItemWeightList = collectAwardCfg
             
         giveItemInfo = GameWorld.GetResultByWeightList(giveItemWeightList)
-        awardIitemList.append(giveItemInfo)
+        awardItemList.append(giveItemInfo)
         
-    if awardIitemList:
-        for itemID, itemCount, isAuctionItem in awardIitemList:
+    if awardItemList:
+        for itemID, itemCount, isAuctionItem in awardItemList:
             ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isAuctionItem, [IPY_GameWorld.rptItem])
         if collectNPCIpyData.GetNotifyCollectResult():
             awardPack = ChPyNetSendPack.tagMCCollectAwardItemInfo()
             awardPack.CollectNPCID = npcID
-            for itemID, itemCount, isAuctionItem in awardIitemList:
+            for itemID, itemCount, isAuctionItem in awardItemList:
                 awardItem = ChPyNetSendPack.tagMCCollectAwardItem()
                 awardItem.ItemID = itemID
                 awardItem.Count = itemCount
@@ -5736,6 +5740,10 @@
     #采集成就
     PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, collectCnt, [npcID])
     #SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
+    
+    if isMaxTime:
+        GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
+        
     return
 
 ## 采集结果同步
@@ -6097,3 +6105,45 @@
     sendPack.Value = speed
     curNPC.NotifyAll(sendPack.GetBuffer(), sendPack.GetLength())
     return
+
+def UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount=0):
+    ## 更新玩家攻击NPC次数
+    GameWorld.DebugLog("更新玩家攻击NPC次数: npcID=%s,attackCount=%s,maxCount=%s" % (npcID, attackCount, maxCount))
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_NPCAttackCount % npcID, attackCount)
+    
+    if GameWorld.IsCrossServer():
+        serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)
+        msgInfo = {"PlayerID":curPlayer.GetPlayerID(), "NPCID":npcID, "AttackCount":attackCount, "MaxCount":maxCount}
+        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_NPCAttackCount, msgInfo, [serverGroupID])
+    else:
+        SyncNPCAttackCount(curPlayer, [npcID])
+        if attackCount and attackCount >= maxCount:
+            GameLogic_CrossGrassland.DoCheckUpdateGrasslandEnd(curPlayer)
+    return
+
+def CrossServerMsg_NPCAttackCount(curPlayer, msgData):
+    ## 收到跨服服务器同步的攻击NPC次数
+    npcID = msgData["NPCID"]
+    attackCount = msgData["AttackCount"]
+    maxCount = msgData["MaxCount"]
+    UpdateNPCAttackCount(curPlayer, npcID, attackCount, maxCount)
+    return
+
+def SyncNPCAttackCount(curPlayer, npcIDList):
+    ## 同步NPC攻击次数
+    if not npcIDList:
+        return
+    
+    clientPack = ChPyNetSendPack.tagMCNPCAttackCountInfo()
+    for npcID in npcIDList:
+        attackCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_NPCAttackCount % npcID)
+        atkCountObj = ChPyNetSendPack.tagMCNPCAttackCount()
+        atkCountObj.NPCID = npcID
+        atkCountObj.AttackCount = attackCount
+        clientPack.NPCAttackCountList.append(atkCountObj)
+    clientPack.Count = len(clientPack.NPCAttackCountList)
+    NetPackCommon.SendFakePack(curPlayer, clientPack)
+    return
+
+
+                
\ No newline at end of file
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
index 266e4d9..b0f4183 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -889,6 +889,8 @@
             else:
                 refreshCD = ipyData.GetRefreshSeconds()
                 
+            if not refreshCD:
+                continue
             if tick - numLastTick < refreshCD * 1000:
                 continue
         gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num, tick)
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 9a8a79b..6b5a192 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/ChPlayer.py
@@ -259,7 +259,9 @@
     if curPet:
         curPet.SetVisible(False)
         
-    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1) # 由于前端不一定有发mapID,所以这里额外记录这个状态,不能直接用mapID判断
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, mapID)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, lineID)
     GameWorld.Log("玩家开始自定义场景!", curPlayer.GetPlayerID())
     if mapID:
         FBLogic.OnEnterCustomScene(curPlayer, mapID, lineID)
@@ -277,6 +279,8 @@
     if curPet:
         curPet.SetVisible(True)
     curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 0)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneMapID, 0)
+    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneLineID, 0)
     GameWorld.Log("玩家退出自定义场景!", curPlayer.GetPlayerID())
     return
 
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 a0a0b93..ec414fe 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -1650,7 +1650,7 @@
         GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_EnterFB, msgDict)
         return
     
-    GY_Query_CrossRealmReg.RegisterEnterCrossServer(curPlayer, mapID)
+    GY_Query_CrossRealmReg.RegisterEnterCrossServer(curPlayer, mapID, lineID=lineID)
     return
 
 ##玩家进入副本
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFairyDomain.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFairyDomain.py
index ee256ce..15b3f21 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFairyDomain.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFairyDomain.py
@@ -240,7 +240,7 @@
         
         # 草园重置
         if ipyData.GetEventType() in [FDEventType_GrasslandXian, FDEventType_GrasslandLing]:
-            GameLogic_CrossGrassland.DoResetCrossGrassland(curPlayer, ipyData.GetEventType())
+            GameLogic_CrossGrassland.DoResetCrossGrassland(curPlayer, ipyData.GetEventType(), fdeventID)
             
     elif state == FDEventState_Visited:
         if curState != FDEventState_Visiting:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ClientServerReceiveMsg.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ClientServerReceiveMsg.py
index c1cd578..9b42a4d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ClientServerReceiveMsg.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_ClientServerReceiveMsg.py
@@ -46,6 +46,9 @@
     elif msgType == ShareDefine.CrossServerMsg_CollectNPCOK:
         NPCCommon.CrossServerMsg_CollectNPCOK(curPlayer, msgData)
         
+    elif msgType == ShareDefine.CrossServerMsg_NPCAttackCount:
+        NPCCommon.CrossServerMsg_NPCAttackCount(curPlayer, msgData)
+        
     elif msgType == ShareDefine.CrossServerMsg_FBEnd:
         mapID, lineID = msgData[:2]
         exData = msgData[2:]
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py
index f0bdca9..5565fdd 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_CrossRealmReg.py
@@ -50,11 +50,11 @@
     GameWorld.Log("GY_Query_CrossRealmReg DoResult %s" % funResult, curPlayer.GetPlayerID())
     if not resultInfo:
         return
-    registerMap, mapID, dataMapID, copyMapID, posX, posY = resultInfo
-    RegisterEnterCrossServer(curPlayer, registerMap, mapID, dataMapID, copyMapID, posX, posY)
+    registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID = resultInfo
+    RegisterEnterCrossServer(curPlayer, registerMap, mapID, dataMapID, copyMapID, posX, posY, lineID)
     return
 
-def RegisterEnterCrossServer(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0):
+def RegisterEnterCrossServer(curPlayer, registerMap, mapID=0, dataMapID=0, copyMapID=0, posX=0, posY=0, lineID=0):
     '''
     @param registerMap: 一般是dataMapID
     '''
@@ -88,11 +88,12 @@
         prepareEnterCrossServer.DataMapID = registerMap
         NetPackCommon.SendFakePack(curPlayer, prepareEnterCrossServer)
     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PlayerKey_CrossRegisterMap, registerMap)
+    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_ReqCrossFBFuncLine, lineID)
     CrossPlayerData.OnPlayerCrossReg(curPlayer)
     #curPlayer.SendMergeRegisterPlayer(mapID, dataMapID, copyMapID, posX, posY)
     curPlayer.SendMergeRegisterPlayerAfterChange(CrossRealmPlayer.GetCrossPlayerName(curPlayer), mapID, dataMapID, copyMapID, posX, posY)
-    GameWorld.Log("    发送跨服玩家数据注册: registerMap=%s,zoneID=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s,GetVsRoomId=%s" 
-                  % (registerMap, zoneID, mapID, dataMapID, copyMapID, posX, posY, curPlayer.GetVsRoomId()), playerID)
+    GameWorld.Log("    发送跨服玩家数据注册: registerMap=%s,lineID=%s,zoneID=%s,mapID=%s,dataMapID=%s,copyMapID=%s,posX=%s,posY=%s,GetVsRoomId=%s" 
+                  % (registerMap, lineID, zoneID, mapID, dataMapID, copyMapID, posX, posY, curPlayer.GetVsRoomId()), playerID)
     return
 
 ## 跨服赛报名结果(上传数据)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 7d79f26..1fe0aaf 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -1211,6 +1211,7 @@
 CrossServerMsg_CollectNPCOK = "CollectNPCOK"            # 采集NPC完成
 CrossServerMsg_EnterFBRet = "EnterFBRet"                # 请求进入跨服副本返回信息
 CrossServerMsg_FBEnd = "FBEnd"                          # 完成跨服副本
+CrossServerMsg_NPCAttackCount = "NPCAttackCount"        # 攻击NPC次数记录
 
 # 子服发送跨服信息定义
 ClientServerMsg_ServerInitOK = "ServerInitOK"           # 子服启动成功
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
index 4716142..87b5128 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Skill/GameSkills/SkillCommon.py
@@ -1222,20 +1222,6 @@
             
     return
 
-## 获取哥布林功能NPC类型掉血值
-def GetGoblinLostHP(defender, hurtValue):
-    if not defender:
-        return hurtValue
-    
-    defObjType = defender.GetGameObjType()
-    if defObjType == IPY_GameWorld.gotNPC:
-        npcFuncType = defender.GetFunctionType()
-        if npcFuncType == ChConfig.Def_NPCFuncType_Goblin:
-            goblinHurtValue = int(ReadChConfig.GetEvalChConfig('GoblinHurtValue'))
-            hurtValue = min(hurtValue, goblinHurtValue)
-            
-    return hurtValue
-
 ## 技能伤血
 #  @param curObj 当前对象
 #  @param skillTypeID 技能类型ID
@@ -1257,7 +1243,6 @@
         ## 后续有其他情况也应考虑进来,如镖车是否某状态不掉血
         return
     
-    #lostValue = GetGoblinLostHP(curObj, lostValue)
     curObjType = curObj.GetGameObjType()
     curSkill = GameWorld.GetGameData().FindSkillByType(skillTypeID, 1)
     

--
Gitblit v1.8.0