From f3f55bc0b986102ca0bd70063cafa11c04756fe1 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 16 四月 2019 10:14:55 +0800
Subject: [PATCH] 6459 【后端】【2.0】缥缈仙域开发单(地图刷怪逻辑修改,草园刷怪支持配置,支持开关线路保存刷怪信息)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py                                     |   38 +++++++
 PySysDB/PySysDBPY.h                                                                                                      |   14 ++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py |   69 +++++++++++++
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py                              |  112 +++++++++++++++++----
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py                              |   10 ++
 5 files changed, 220 insertions(+), 23 deletions(-)

diff --git a/PySysDB/PySysDBPY.h b/PySysDB/PySysDBPY.h
index 763aa91..89f6a1a 100644
--- a/PySysDB/PySysDBPY.h
+++ b/PySysDB/PySysDBPY.h
@@ -969,6 +969,20 @@
 	char		MoneyCount;	//单次消耗金钱数量
 };
 
+//地图标试点NPC刷新
+
+struct tagMapRefreshNPC
+{
+	DWORD		_MapID;	//地图ID
+	BYTE		RefreshNum; //刷怪规则编号
+	list		NPCIDList;	//NPCID列表
+	list		RefreshMarkList;	//标试点列表
+	BYTE		PointMaxCount;	//单个点最大存在怪物数
+	BYTE		TotalMaxCount;	//所有点总怪物数
+	BYTE		RefreshSeconds;	//刷怪间隔秒
+	BYTE		RefreshPerMinutes;	//每整X分刷怪
+};
+
 //符印合成表
 
 struct tagRuneCompound
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 d9fc0c7..0b2d18e 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
@@ -14,3 +14,72 @@
 #-------------------------------------------------------------------------------
 #"""Version = 2019-04-15 16:30"""
 #-------------------------------------------------------------------------------
+import GameWorld
+import GameWorldProcess
+import NPCCustomRefresh
+import PyGameData
+
+def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
+    return True
+
+## 开启副本
+def OnOpenFB(tick):
+    gameWorld = GameWorld.GetGameWorld()
+    realMapID, copyMapID = gameWorld.GetRealMapID(), gameWorld.GetCopyMapID()
+    key = (realMapID, copyMapID)
+    if key in PyGameData.g_crossFuncLineDataCache:
+        refreshNPCInfo = PyGameData.g_crossFuncLineDataCache[key]
+        GameWorld.DebugLog("副本开启根据保存的虚拟线路标试点刷怪信息刷怪: realMapID=%s,copyMapID=%s,refreshNPCInfo=%s" % (realMapID, copyMapID, refreshNPCInfo))
+        NPCCustomRefresh.OnFBOpenSetRandomRefreshNPCInfo(refreshNPCInfo, tick)
+        
+    return
+
+def GetCurFBFuncLineID():
+    ## 获取本线路功能线路ID
+    return GameWorld.GetGameWorld().GetPropertyID() % 10000 / 10
+
+def GetCurFBLineZoneID():
+    ## 获取本线路所属跨服分区
+    return GameWorld.GetGameWorld().GetPropertyID() / 10000
+
+## 进副本
+def DoEnterFB(curPlayer, tick):
+    playerID = curPlayer.GetPlayerID()
+    zoneID = GetCurFBLineZoneID()
+    funcLineID = GetCurFBFuncLineID()
+    GameWorld.Log("DoEnterFB zoneID=%s,funcLineID=%s" % (zoneID, funcLineID), playerID)
+    return
+
+## 副本总逻辑计时器
+def OnProcess(tick):
+    #gameFB = GameWorld.GetGameFB()
+    return
+
+## 关闭副本
+def OnCloseFB(tick):
+    gameWorld = GameWorld.GetGameWorld()
+    refreshNPCInfo = NPCCustomRefresh.GetCopyMapRandomRefreshNPCInfo()
+    if refreshNPCInfo:
+        realMapID, copyMapID = gameWorld.GetRealMapID(), gameWorld.GetCopyMapID()
+        key = (realMapID, copyMapID)
+        PyGameData.g_crossFuncLineDataCache[key] = refreshNPCInfo
+        GameWorld.DebugLog("缓存虚拟线路标试点刷怪信息: realMapID=%s,copyMapID=%s,refreshNPCInfo=%s" % (realMapID, copyMapID, refreshNPCInfo))
+        
+    GameWorld.GetGameWorld().SetPropertyID(0)
+    return
+
+## 玩家退出副本
+def DoExitFB(curPlayer, tick):
+    return
+
+##玩家主动离开副本.
+def DoPlayerLeaveFB(curPlayer, tick):
+    
+    gameWorld = GameWorld.GetGameWorld()
+    #最后一人退出副本则关闭地图
+    if gameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:
+        GameWorldProcess.CloseFB(tick)
+        
+    return
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
index db11233..e9efd34 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py
@@ -783,6 +783,17 @@
                         ("char", "MoneyCount", 0),
                         ),
 
+                "MapRefreshNPC":(
+                        ("DWORD", "MapID", 1),
+                        ("BYTE", "RefreshNum", 0),
+                        ("list", "NPCIDList", 0),
+                        ("list", "RefreshMarkList", 0),
+                        ("BYTE", "PointMaxCount", 0),
+                        ("BYTE", "TotalMaxCount", 0),
+                        ("BYTE", "RefreshSeconds", 0),
+                        ("BYTE", "RefreshPerMinutes", 0),
+                        ),
+
                 "RuneCompound":(
                         ("DWORD", "TagItemID", 1),
                         ("list", "NeedItem", 0),
@@ -2986,6 +2997,29 @@
     def GetInspireMaxLV(self): return self.InspireMaxLV # 鼓舞等级限制
     def GetMoneyCount(self): return self.MoneyCount # 单次消耗金钱数量
 
+# 地图标试点NPC刷新
+class IPY_MapRefreshNPC():
+    
+    def __init__(self):
+        self.MapID = 0
+        self.RefreshNum = 0
+        self.NPCIDList = []
+        self.RefreshMarkList = []
+        self.PointMaxCount = 0
+        self.TotalMaxCount = 0
+        self.RefreshSeconds = 0
+        self.RefreshPerMinutes = 0
+        return
+        
+    def GetMapID(self): return self.MapID # 地图ID
+    def GetRefreshNum(self): return self.RefreshNum # 刷怪规则编号
+    def GetNPCIDList(self): return self.NPCIDList # NPCID列表
+    def GetRefreshMarkList(self): return self.RefreshMarkList # 标试点列表
+    def GetPointMaxCount(self): return self.PointMaxCount # 单个点最大存在怪物数
+    def GetTotalMaxCount(self): return self.TotalMaxCount # 所有点总怪物数
+    def GetRefreshSeconds(self): return self.RefreshSeconds # 刷怪间隔秒
+    def GetRefreshPerMinutes(self): return self.RefreshPerMinutes # 每整X分刷怪
+
 # 符印合成表
 class IPY_RuneCompound():
     
@@ -4484,6 +4518,8 @@
         self.ipySealDemonLen = len(self.ipySealDemonCache)
         self.ipyFbEncourageCache = self.__LoadFileData("FbEncourage", IPY_FbEncourage)
         self.ipyFbEncourageLen = len(self.ipyFbEncourageCache)
+        self.ipyMapRefreshNPCCache = self.__LoadFileData("MapRefreshNPC", IPY_MapRefreshNPC)
+        self.ipyMapRefreshNPCLen = len(self.ipyMapRefreshNPCCache)
         self.ipyRuneCompoundCache = self.__LoadFileData("RuneCompound", IPY_RuneCompound)
         self.ipyRuneCompoundLen = len(self.ipyRuneCompoundCache)
         self.ipyResourcesBackCache = self.__LoadFileData("ResourcesBack", IPY_ResourcesBack)
@@ -4938,6 +4974,8 @@
     def GetSealDemonByIndex(self, index): return self.ipySealDemonCache[index]
     def GetFbEncourageCount(self): return self.ipyFbEncourageLen
     def GetFbEncourageByIndex(self, index): return self.ipyFbEncourageCache[index]
+    def GetMapRefreshNPCCount(self): return self.ipyMapRefreshNPCLen
+    def GetMapRefreshNPCByIndex(self, index): return self.ipyMapRefreshNPCCache[index]
     def GetRuneCompoundCount(self): return self.ipyRuneCompoundLen
     def GetRuneCompoundByIndex(self, index): return self.ipyRuneCompoundCache[index]
     def GetResourcesBackCount(self): return self.ipyResourcesBackLen
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 d4c95eb..d1cbeb0 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -855,12 +855,13 @@
     ''' 地图自定义随机刷怪,支持多点随机刷多种怪,标试点不可重复,支持跨服地图
             注意:同个虚拟线路中,标试点不可重复!标试点不可重复!标试点不可重复!
     '''
-    mapID = gameWorld.GetMapID()
-    # {mapID:{编号:[[多个NPCID], [多个标试点], 单个点最大数量, 所有点总数量, 刷怪间隔秒, 每整X小时], ...}, ...}
-    randRefreshNPCDict = IpyGameDataPY.GetFuncEvalCfg("RandomRefreshNPC", 1, {})
-    if mapID not in randRefreshNPCDict:
+    if gameWorld.GetOpenState() != IPY_GameWorld.fbosOpen:
+        #已经关闭了
         return
-    mapRandRefreshNPCDict = randRefreshNPCDict[mapID]
+    mapID = gameWorld.GetMapID()
+    refreshIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("MapRefreshNPC", mapID)
+    if not refreshIpyDataList:
+        return
     
     #copyMapID = gameWorld.GetCopyMapID()
     
@@ -872,21 +873,26 @@
     
     serverTime = GameWorld.GetCurrentTime()
     curHour, curMinute = serverTime.hour, serverTime.minute
-    refreshNumList = []
-    for num, refreshInfo in mapRandRefreshNPCDict.items():
-        refreshCD = refreshInfo[4]
+    minuteTotal = curHour * 60 + curMinute
+    needRefreshIpyDataList = []
+    for ipyData in refreshIpyDataList:
+        num = ipyData.GetRefreshNum()
         numLastTick = gameFB.GetGameFBDictByKey(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num)
-        perHours = refreshInfo[5]
-        if numLastTick and perHours:
-            if curHour % perHours != 0 or curMinute != 0:
+        if numLastTick:
+            perMinutes = ipyData.GetRefreshPerMinutes()
+            if perMinutes:
+                if minuteTotal % perMinutes != 0:
+                    continue
+                refreshCD = 60 # 1分钟内不重复刷新
+            else:
+                refreshCD = ipyData.GetRefreshSeconds()
+                
+            if tick - numLastTick < refreshCD * 1000:
                 continue
-            refreshCD = 65 # 1分钟内不重复刷新
-        if numLastTick and tick - numLastTick < refreshCD * 1000:
-            continue
         gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num, tick)
-        refreshNumList.append(num)
+        needRefreshIpyDataList.append(ipyData)
         
-    if not refreshNumList:
+    if not needRefreshIpyDataList:
         #GameWorld.DebugLog("没有需要刷怪的", copyMapID)
         return
     npcCountDict = {}  # 标识点对应NPC数量
@@ -901,9 +907,12 @@
         npcCountDict[rMark] = npcCountDict.get(rMark, 0) + npcCount
         rMarkNPCRefreshDict[rMark] = npcRefresh
         
-    #GameWorld.DebugLog("npcCountDict=%s" % npcCountDict, copyMapID)
-    for num in refreshNumList:
-        npcIDList, markList, maxCount, totalMaxCount = mapRandRefreshNPCDict[num][:4]
+    #GameWorld.DebugLog("标试点怪物数: minuteTotal=%s,npcCountDict=%s" % (minuteTotal, npcCountDict), copyMapID)
+    for ipyData in needRefreshIpyDataList:
+        npcIDList = ipyData.GetNPCIDList()
+        markList = ipyData.GetRefreshMarkList()
+        maxCount = ipyData.GetPointMaxCount()
+        totalMaxCount = ipyData.GetTotalMaxCount()
         
         curTotalCount = 0
         for rMark in markList:
@@ -911,13 +920,16 @@
             
         refreshCount = totalMaxCount - curTotalCount
         
-        #GameWorld.DebugLog("    num=%s,markList=%s,curTotalCount=%s,totalMaxCount=%s,refreshCount=%s" 
-        #                   % (num, markList, curTotalCount, totalMaxCount, refreshCount), copyMapID)
+        #GameWorld.DebugLog("    npcIDList=%s,markList=%s,curTotalCount=%s,totalMaxCount=%s,refreshCount=%s" 
+        #                   % (npcIDList, markList, curTotalCount, totalMaxCount, refreshCount), copyMapID)
         if refreshCount <= 0:
             continue
         
-        random.shuffle(markList) # 随机打乱顺序
-        #GameWorld.DebugLog("    markList=%s" % markList, copyMapID)
+        isNeedRandom = len(markList) != totalMaxCount
+        if isNeedRandom:
+            markList = list(markList)
+            random.shuffle(markList) # 随机打乱顺序,如果需要随机的话就用多个不同的标试点
+        #GameWorld.DebugLog("    markList=%s" % str(markList), copyMapID)
         for rMark in markList:
             if rMark not in rMarkNPCRefreshDict:
                 #GameWorld.DebugLog("        标试点不存在: rMark=%s" % rMark, copyMapID)
@@ -940,3 +952,57 @@
             
     return
 
+def GetCopyMapRandomRefreshNPCInfo():
+    ## 获取当前虚拟线路随机刷怪点NPC信息
+    
+    gameWorld = GameWorld.GetGameWorld()
+    mapID = gameWorld.GetMapID()
+    refreshIpyDataList = IpyGameDataPY.GetIpyGameDataListNotLog("MapRefreshNPC", mapID)
+    if not refreshIpyDataList:
+        return
+    
+    lastRefreshTickDict = {}
+    gameFB = GameWorld.GetGameFB()
+    for ipyData in refreshIpyDataList:
+        num = ipyData.GetRefreshNum()
+        lastRefreshTickDict[num] = gameFB.GetGameFBDictByKey(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num)
+        
+    markNPCDict = {}  # 标识点对应NPC数量
+    gameNPC = GameWorld.GetNPCManager()
+    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
+        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
+        npcCount = npcRefresh.GetCount()
+        if not npcCount:
+            continue
+        
+        rMark = npcRefresh.GetRefreshMark()
+        npcIDCountDict = {}
+        for j in xrange(npcCount):
+            curNPC = npcRefresh.GetAt(j)
+            npcID = curNPC.GetNPCID()
+            npcIDCountDict[npcID] = npcIDCountDict.get(npcID, 0) + 1
+        markNPCDict[rMark] = npcIDCountDict
+    return lastRefreshTickDict, markNPCDict
+
+def OnFBOpenSetRandomRefreshNPCInfo(refreshNPCInfo, tick):
+    ## 副本虚拟线路启动时,根据保存的标试点刷怪信息设置刷怪
+    lastRefreshTickDict, markNPCDict = refreshNPCInfo
+        
+    gameFB = GameWorld.GetGameFB()
+    gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCTick, tick)
+    for num, setTick in lastRefreshTickDict.items():
+        gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num, setTick)
+        
+    gameNPC = GameWorld.GetNPCManager()
+    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
+        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
+        rMark = npcRefresh.GetRefreshMark()
+        if rMark not in markNPCDict:
+            continue
+        npcIDCountDict = markNPCDict[rMark]
+        for npcID, count in npcIDCountDict.items():
+            GameWorld.DebugLog("    副本启动刷怪: rMark=%s,npcID=%s,count=%s" % (rMark, npcID, count))
+            npcRefresh.Refresh(npcID, ChConfig.Def_NormalNPCAngryCount, count, False)
+            __InitNewBornNPC(npcRefresh , tick)
+            
+    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 a939d53..9948798 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -1617,6 +1617,16 @@
         NotifyCode(curPlayer, "SingleEnterPK", [mapID])
         return
     
+    fbIpyData = FBCommon.GetFBIpyData(mapID)
+    if fbIpyData:
+        fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID, False)
+        if not fbLineIpyData:
+            GameWorld.DebugLog("副本表找不到副本对应功能线路!mapID=%s,lineID=%s" % (mapID, lineID))
+            return
+        ret = FBCommon.CheckCanEnterFBComm(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData)
+        if ret != ShareDefine.EntFBAskRet_OK:
+            return
+        
     tick = GameWorld.GetGameWorld().GetTick()
     for mapIDList in ChConfig.Def_FB_MapID.values():
         if mapID not in mapIDList:

--
Gitblit v1.8.0