6459 【后端】【2.0】缥缈仙域开发单(地图刷怪逻辑修改,草园刷怪支持配置,支持开关线路保存刷怪信息)
5个文件已修改
243 ■■■■■ 已修改文件
PySysDB/PySysDBPY.h 14 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossGrassland.py 69 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/IpyGameDataPY.py 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py 112 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py 10 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
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
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
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
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
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: