ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCustomRefresh.py
@@ -17,6 +17,8 @@
import ShareDefine
import ReadChConfig
import GameLogic_SealDemon
import GameLogic_ZhuXianBoss
import PlayerControl
import IPY_GameWorld
import IpyGameDataPY
import GameWorld
@@ -24,6 +26,7 @@
import FBLogic
import random
import time
#---------------------------------------------------------------------
## 所有npc刷新
@@ -335,7 +338,50 @@
def NPCRefresh_98(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_99(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_100(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_180(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_181(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_182(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_183(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_184(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_185(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_186(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_187(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_188(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_189(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_190(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_191(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_192(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_193(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_194(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_195(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_196(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_197(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_198(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_199(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def NPCRefresh_200(npcRefresh, tick):__DoRefreshWorldBoss(npcRefresh, tick)
def ResetActivityBossRefreshCount():
    ## 重置活动boss刷怪个数
    # gameFb 要取活动线
    activityLineIndex = 0 # 活动线, 默认1线
    mapID = GameWorld.GetMap().GetMapID()
    activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})
    if mapID in activityMapLineDict:
        activityLineIndex = max(0, activityMapLineDict[mapID] - 1)
    gameWorld = IPY_GameWorld.IPY_GameWorld(activityLineIndex)
    gameFB = gameWorld.GetGameFBByFbIndex(activityLineIndex)
    gameNPC = GameWorld.GetNPCManager() # NPC标识点的无所谓,哪条线都可以,因为都一样
    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
        refreshMark = npcRefresh.GetRefreshMark()
        if gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark):
            gameFB.SetGameFBDict(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark, 0)
            GameWorld.DebugLog("重置活动boss刷怪点刷怪个数: activityLineIndex=%s,refreshMark=%s" % (activityLineIndex, refreshMark))
    return
## 世界boss刷怪
#  @param npcRefresh 刷新实例
@@ -345,12 +391,19 @@
    '''非分流地图boss只在一线刷
       分流地图boss每条线都刷新,其他分流线路boss在没人打的情况下同生同死
    '''
    if GameWorld.IsCrossServer():
        __DoRefreshWorldBossCrossServer(npcRefresh, tick)
        return
    mapID = GameWorld.GetMap().GetMapID()
    refreshMark = npcRefresh.GetRefreshMark()
    lineID = GameWorld.GetGameWorld().GetLineID()
    relatedType, relatedID = 0, 0
    isNeedShunt = 0
    if mapID == ChConfig.Def_FBMapID_SealDemon:
        bossID = GameLogic_SealDemon.CurFBLineBOSSID()
        stoneNPCID = 0
    elif mapID == ChConfig.Def_FBMapID_ZhuXianBoss:
        bossID = GameLogic_ZhuXianBoss.CurFBLineBOSSID()
        stoneNPCID = 0
    else:
        ipyData = IpyGameDataPY.GetIpyGameDataByCondition('BOSSInfo', {'RefreshMark':refreshMark, 'MapID':mapID}, isLogNone=False)
@@ -358,14 +411,47 @@
            return
        stoneNPCID = ipyData.GetStoneNPCID()
        bossID = ipyData.GetNPCID()
        relatedType = ipyData.GetRelatedType()
        relatedID = ipyData.GetRelatedID()
        isNeedShunt = ipyData.GetIsNeedShunt()
    if not bossID and not stoneNPCID:
        return
    gameFB = GameWorld.GetGameFB()
    gameWorldMgr = GameWorld.GetGameWorld()
    bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
    rebornBossState = gameWorldMgr.GetGameWorldDictByKey(bosskey)
    isNeedShunt = NPCCommon.IsMapNeedBossShunt(mapID)
    isActivityBoss = False # 是否活动boss
    # 关联日常活动
    if relatedType == 1:
        actionKey = ShareDefine.Def_Notify_WorldKey_DailyActionState % relatedID
        rebornBossState = 1 if gameWorldMgr.GetGameWorldDictByKey(actionKey) else 0
        isActivityBoss = True
    # 关联运营活动,待扩展
    elif relatedType == 2:
        pass
    else:
        bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID
        rebornBossState = gameWorldMgr.GetGameWorldDictByKey(bosskey)
    rebornLineID = 0
    activityLineID = 0 # 活动线, 默认1线
    activityMapLineDict = IpyGameDataPY.GetFuncEvalCfg("MapLine", 2, {})
    if mapID in activityMapLineDict:
        activityLineID = max(0, activityMapLineDict[mapID] - 1)
    # 活动boss只在活动线路刷
    if isActivityBoss:
        activityBossRebornCount = gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark)
        rebornLineID = activityLineID # 活动boss只刷在活动线
        # 不是活动线
        if rebornBossState and lineID != rebornLineID:
            rebornBossState = 0
    # 非活动boss活动线不刷, 1线除外
    else:
        if activityLineID and lineID == activityLineID:
            rebornBossState = 0
            stoneNPCID = 0 # 活动线暂不刷墓碑
    isNeedShunt = NPCCommon.IsMapNeedBossShunt(mapID) and isNeedShunt
    
    curNPC = None
    if npcRefresh.GetCount() > 0:
@@ -379,8 +465,13 @@
            #去掉非bossNPC
            NPCCommon.SetDeadEx(curNPC)
            
        # 非一线 且 不需要分流的地图 且 不是封魔坛  不允许复活
        if lineID != 0 and not isNeedShunt and mapID != ChConfig.Def_FBMapID_SealDemon:
        # 非复活线 且 不需要分流的地图 且 不是封魔坛  不允许复活
        if lineID != rebornLineID and not isNeedShunt and mapID not in [ChConfig.Def_FBMapID_SealDemon, ChConfig.Def_FBMapID_ZhuXianBoss]:
            return
        if isActivityBoss and activityBossRebornCount > 0:
            #GameWorld.DebugLog("活动线已经刷过不再刷活动boss: lineID=%s,rebornLineID=%s,refreshMark=%s,bossID=%s,activityBossRebornCount=%s"
            #                   % (lineID, rebornLineID, refreshMark, bossID, activityBossRebornCount))
            return
        
    # 死亡状态
@@ -391,6 +482,11 @@
                return
            if curNPC.GetNPCID() == stoneNPCID:
                return 
            # 活动的boss
            if curNPC.GetNPCID() == bossID and isActivityBoss:
                GameWorld.Log("活动boss,活动结束,系统设置boss死亡!bossID=%s" % bossID)
                PlayerControl.FBNotify("FairyGrabBossNoDead", [bossID])
            #去掉非墓碑NPC
            NPCCommon.SetDeadEx(curNPC)
        
@@ -415,25 +511,109 @@
    #初始化NPC
    __InitNewBornNPC(npcRefresh, tick)
    gameFB.SetGameFBDict(key, tick)
    GameWorld.DebugLog("BossRefresh mapID=%s,refreshMark=%s,rebornNPCID=%s,isNeedShunt=%s,OK!" % (mapID, refreshMark, rebornNPCID, isNeedShunt), lineID)
    if isActivityBoss and rebornBossState:
        gameFB.SetGameFBDict(ChConfig.Map_NPC_ActivityBossRebornCount % refreshMark, activityBossRebornCount + 1)
    GameWorld.DebugLog("BossRefresh mapID=%s,rebornLineID=%s,refreshMark=%s,rebornNPCID=%s,isNeedShunt=%s,OK!"
                       % (mapID, rebornLineID, refreshMark, rebornNPCID, isNeedShunt), lineID)
    return
def IsShuntBossNeedProcess(curNPC):
    '''分流boss是否需要处理
        无伤血、仇恨、没人看到他、他没看到别人
    '''
    if curNPC.GetPlayerHurtList().GetHurtCount():
        #GameWorld.DebugLog("分流boss有伤血,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
        return True
    if curNPC.GetAttentionPlayersCount() or curNPC.GetInSightObjCount():
        #GameWorld.DebugLog("分流boss有人看到,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
        return True
    GameWorld.DebugLog("分流boss不需要处理了,可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
    return False
    # 策划暂时修改分流boss不同步死亡
    return True
#    if curNPC.GetPlayerHurtList().GetHurtCount():
#        #GameWorld.DebugLog("分流boss有伤血,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
#        return True
#
#    if curNPC.GetAttentionPlayersCount() or curNPC.GetInSightObjCount():
#        #GameWorld.DebugLog("分流boss有人看到,不可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
#        return True
#
#    GameWorld.DebugLog("分流boss不需要处理了,可以清除!npcID=%s" % curNPC.GetNPCID(), GameWorld.GetGameWorld().GetLineID())
#    return False
#===================================================================================================
def __DoRefreshWorldBossCrossServer(npcRefresh, tick):
    ## 跨服服务器刷boss
    mapID = GameWorld.GetGameWorld().GetMapID() # dataMapID
    if mapID not in ChConfig.Def_CrossMapIDList:
        return
    refreshMark = npcRefresh.GetRefreshMark()
    lineID = GameWorld.GetGameWorld().GetLineID()
    bossIpyData = IpyGameDataPY.GetIpyGameDataByCondition('BOSSInfo', {'RefreshMark':refreshMark, 'MapID':mapID}, isLogNone=False)
    if not bossIpyData:
        return
    stoneNPCID = bossIpyData.GetStoneNPCID()
    bossID = bossIpyData.GetNPCID()
    if not bossID and not stoneNPCID:
        return
    if mapID not in ChConfig.Def_CrossZoneTableName:
        return
    tableName = ChConfig.Def_CrossZoneTableName[mapID]
    realMapID = GameWorld.GetGameWorld().GetRealMapID()
    copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
    zoneIpyData = IpyGameDataPY.GetIpyGameDataNotLog(tableName, realMapID, mapID, copyMapID)
    if not zoneIpyData:
        return
    zoneID = zoneIpyData.GetZoneID()
    gameFB = GameWorld.GetGameFB()
    bosskey = ShareDefine.Def_Notify_WorldKey_GameWorldBossRebornCross % (zoneID, bossID)
    rebornBossState = GameWorld.GetGameWorld().GetGameWorldDictByKey(bosskey)
    curNPC = None
    if npcRefresh.GetCount() > 0:
        curNPC = npcRefresh.GetAt(0)
    # 复活状态
    if rebornBossState:
        if curNPC:
            if curNPC.GetNPCID() == bossID:
                return
            #去掉非bossNPC
            NPCCommon.SetDeadEx(curNPC)
    # 死亡状态
    else:
        if curNPC:
            if curNPC.GetNPCID() == stoneNPCID:
                return
            #去掉非墓碑NPC
            NPCCommon.SetDeadEx(curNPC)
        # 延迟刷墓碑
        bossDeadTick = gameFB.GetGameFBDictByKey(ChConfig.Map_NPC_WorldBossDeadTick % bossID)
        bossStoneDelayTime = IpyGameDataPY.GetFuncCfg('BossStoneDelayTime')
        if tick - bossDeadTick <= bossStoneDelayTime:
            return
        gameFB.SetGameFBDict(ChConfig.Map_NPC_WorldBossDeadTick % bossID, tick)
    rebornNPCID = bossID if rebornBossState else stoneNPCID
    if not rebornNPCID:
        return
    rebornTickKey = ChConfig.Map_NPC_WorldBossLastReBornTick % rebornNPCID
    lastRebornTick = gameFB.GetGameFBDictByKey(rebornTickKey)
    if tick - lastRebornTick <= 50 * 1000:
        GameWorld.DebugLog("CrossBossRefresh mapID=%s,realMapID=%s,copyMapID=%s,refreshMark=%s,rebornNPCID=%s,tick=%s,lastRebornTick=%s 不重复刷新!"
                           % (mapID, realMapID, copyMapID, refreshMark, rebornNPCID, tick, lastRebornTick))
        return
    npcRefresh.Refresh(rebornNPCID, ChConfig.Def_SuperBossAngryCount, 1, False)
    #初始化NPC
    __InitNewBornNPC(npcRefresh, tick)
    gameFB.SetGameFBDict(rebornTickKey, tick)
    GameWorld.DebugLog("CrossBossRefresh mapID=%s,realMapID=%s,copyMapID=%s,refreshMark=%s,rebornNPCID=%s,OK!"
                       % (mapID, realMapID, copyMapID, refreshMark, rebornNPCID), lineID)
    return
################################ 通用刷怪逻辑 ####################################
def GetNPCRefreshCountList(refreshID):
@@ -723,3 +903,92 @@
################################################################################
def ProcessMapRandomRefreshNPC(gameWorld, tick):
    ''' 地图自定义随机刷怪,支持多点随机刷多种怪,标试点不可重复,支持跨服地图
            注意:同个虚拟线路中,标试点不可重复!标试点不可重复!标试点不可重复!
    '''
    mapID = gameWorld.GetMapID()
    # {mapID:{编号:[[多个NPCID], [多个标试点], 单个点最大数量, 所有点总数量, 刷怪间隔秒, 每整X小时], ...}, ...}
    randRefreshNPCDict = IpyGameDataPY.GetFuncEvalCfg("RandomRefreshNPC", 1, {})
    if mapID not in randRefreshNPCDict:
        return
    mapRandRefreshNPCDict = randRefreshNPCDict[mapID]
    #copyMapID = gameWorld.GetCopyMapID()
    gameFB = GameWorld.GetGameFB()
    lastCheckTick = gameFB.GetGameFBDictByKey(ChConfig.Def_RMark_RandomRefreshNPCTick)
    if lastCheckTick and tick - lastCheckTick < 1000:
        return
    gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCTick, tick)
    serverTime = GameWorld.GetCurrentTime()
    curHour, curMinute = serverTime.hour, serverTime.minute
    refreshNumList = []
    for num, refreshInfo in mapRandRefreshNPCDict.items():
        refreshCD = refreshInfo[4]
        numLastTick = gameFB.GetGameFBDictByKey(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num)
        perHours = refreshInfo[5]
        if numLastTick and perHours:
            if curHour % perHours != 0 or curMinute != 0:
                continue
            refreshCD = 65 # 1分钟内不重复刷新
        if numLastTick and tick - numLastTick < refreshCD * 1000:
            continue
        gameFB.SetGameFBDict(ChConfig.Def_RMark_RandomRefreshNPCNumTime % num, tick)
        refreshNumList.append(num)
    if not refreshNumList:
        #GameWorld.DebugLog("没有需要刷怪的", copyMapID)
        return
    npcCountDict = {}  # 标识点对应NPC数量
    rMarkNPCRefreshDict = {} # 标试点对应标试点实例 {标试点:IPY_CustomNPCRefresh, ...}
    gameNPC = GameWorld.GetNPCManager()
    for i in xrange(gameNPC.GetCustomNPCRefreshCount()):
        npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)
        npcCount = npcRefresh.GetCount()
        #if not npcCount: # 因为要记录刷怪点实例,所以0的不屏蔽
        #    continue
        rMark = npcRefresh.GetRefreshMark()
        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]
        curTotalCount = 0
        for rMark in markList:
            curTotalCount += npcCountDict.get(rMark, 0)
        refreshCount = totalMaxCount - curTotalCount
        #GameWorld.DebugLog("    num=%s,markList=%s,curTotalCount=%s,totalMaxCount=%s,refreshCount=%s"
        #                   % (num, markList, curTotalCount, totalMaxCount, refreshCount), copyMapID)
        if refreshCount <= 0:
            continue
        random.shuffle(markList) # 随机打乱顺序
        #GameWorld.DebugLog("    markList=%s" % markList, copyMapID)
        for rMark in markList:
            if rMark not in rMarkNPCRefreshDict:
                #GameWorld.DebugLog("        标试点不存在: rMark=%s" % rMark, copyMapID)
                continue
            if refreshCount <= 0:
                #GameWorld.DebugLog("        不需要刷怪了: rMark=%s" % rMark, copyMapID)
                break
            curCount = npcCountDict.get(rMark, 0)
            if curCount >= maxCount:
                #GameWorld.DebugLog("        该点已经达到单点最大数: rMark=%s" % rMark, copyMapID)
                continue
            needRefreshCount = min(refreshCount, maxCount - curCount)
            refreshCount -= needRefreshCount
            npcID = npcIDList[0] if len(npcIDList) == 1 else random.choice(npcIDList)
            #GameWorld.DebugLog("        刷怪: rMark=%s,needRefreshCount=%s,还需=%s" % (rMark, needRefreshCount, refreshCount), copyMapID)
            npcRefresh = rMarkNPCRefreshDict[rMark]
            npcRefresh.Refresh(npcID, ChConfig.Def_NormalNPCAngryCount, needRefreshCount, False)
            __InitNewBornNPC(npcRefresh , tick)
    return