hxp
2020-02-23 0dda6b752c530be0648384a499da549b44d3ec11
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -30,8 +30,9 @@
import EventReport
import PlayerFamily
import PlayerActivity
import ItemControler
import PlayerSuccess
import PlayerMagicWeapon
import GameFuncComm
import PyGameData
import PlayerVip
import GameObj
@@ -57,6 +58,7 @@
Help_wheel = 'wheel' #当前波数(关卡编号),从1开始,1~n
Help_npc = 'npc' #NPC已击杀个数 [{"NPCID":150,"killCnt":100}]
Help_npcTotal = 'npcTotal' #NPC总已击杀个数
Help_npcTotalNeed = 'npcTotalNeed' #NPC总需击杀个数
Help_exp = 'exp' #已获得经验
Help_expPoint = 'expPoint' #已获得经验点
Help_money = 'money' #已获得钱 [{"moneyType":3,"moneyValue":1000}]
@@ -67,6 +69,9 @@
Help_helpCount = 'helpCount' #该副本今日已助战次数
Help_relation = 'relation' #该副本关系加成信息 [优先关系, 总加成]
Help_robotJob = 'robotJob' #机器人职业 {"ObjID":job, ...}
Help_isAuto = 'isAuto' #是否自动召唤
Help_hasRefreshBoss = 'hasRefreshBoss' #是否已刷新boss
Help_gsItemInfo = 'gsItemInfo' #聚魂副本物品信息 {"波数":[[{"ItemID":101, "ItemCount":10}]]}
#副本结算信息通用key
Over_dataMapID = 'dataMapID' #数据地图ID
@@ -86,12 +91,15 @@
Over_grade = 'grade' #评级(5-S,4-A,3-B,2-C,1-D)
Over_itemInfo = 'itemInfo' #物品列表 [{"ItemID":101, "ItemCount":10, "IsBind":1, "IsSuite":1, "UserData":"自定义属性字符串"}]
Over_succItemInfo = 'succItemInfo' #物品列表
Over_firstPassItem = 'firstPassItem' #物品列表
Over_score = 'score' #已获得积分
Over_extrScore = 'extrScore' #已获得额外积分
Over_enterLV = 'enterLV' #进入时等级
Over_leaderID = 'leaderID' #渡劫玩家ID
Over_xianyuanCoin = 'xianyuanCoin' #获得仙缘币信息 [获得仙缘币数, 没有获得的原因] 原因: 1-达到助战次数上限,2-达到每日获得仙缘币上限
Over_helpPlayer = 'helpPlayer' #助战玩家信息 {"玩家ID":{玩家信息key:value, ...}, ...}
Over_ownerID = 'ownerID' #归属玩家ID
Over_ownerName = 'ownerName' #归属玩家名
Over_isAssist = 'isAssist' #是否协助
#副本行为
(
@@ -159,6 +167,10 @@
def CheckCanEnterFBComm(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, reqEnterCnt=1, isNotify=True, isTeamAsk=False):
    # 可否进入副本通用检查, 扫荡通用
    playerID = curPlayer.GetPlayerID()
    if not FBLogic.OnNeedCheckCanEnterFBComm(curPlayer, mapID, lineID):
        return ShareDefine.EntFBAskRet_OK
    # 总表通用检查
    if fbIpyData:
        #开服天开放检查
@@ -169,7 +181,7 @@
            return ShareDefine.EntFBAskRet_FBClose
        
        #进入次数判断
        canEnter, notifyMark = __CheckCanEnterFBByTime(curPlayer, mapID, fbIpyData, reqEnterCnt, isTeamAsk)
        canEnter, notifyMark = __CheckCanEnterFBByTime(curPlayer, mapID, lineID, fbIpyData, reqEnterCnt, isTeamAsk)
        if not canEnter:
            if notifyMark:
                PlayerControl.NotifyCode(curPlayer, notifyMark, [mapID])
@@ -199,15 +211,6 @@
                PlayerControl.NotifyCode(curPlayer, "FbLV", [mapID])
            return ShareDefine.EntFBAskRet_LVLimit
        
        #职业阶判断
        jobRankLimit = fbLineIpyData.GetJobRankLimit()
        if jobRankLimit and PlayerControl.GetJobRank(curPlayer) < jobRankLimit:
            GameWorld.Log("玩家职业阶级不足, 无法进入副本!mapID=%s,lineID=%s,jobRank=%s < jobRankLimit=%s"
                          % (mapID, lineID, PlayerControl.GetJobRank(curPlayer), jobRankLimit), playerID)
            if isNotify:
                PlayerControl.NotifyCode(curPlayer, "SingleEnterJob", [mapID])
            return ShareDefine.EntFBAskRet_JobRankLimit
        #门票判断
        if not GetFBEnterTicket(curPlayer, mapID, lineID, fbLineIpyData, reqEnterCnt, isTeamAsk)[0]:
            if isNotify:
@@ -216,12 +219,19 @@
        
    return ShareDefine.EntFBAskRet_OK
def __CheckCanEnterFBByTime(curPlayer, mapID, fbIpyData, reqEnterCnt, isTeamAsk):
def __CheckCanEnterFBByTime(curPlayer, mapID, lineID, fbIpyData, reqEnterCnt, isTeamAsk):
    #进入次数判断
    maxTimes = fbIpyData.GetDayTimes()
    if not maxTimes:
        return True, ""
    
    # 首次进入免费
    if mapID in [ChConfig.Def_FBMapID_PersonalBoss]:
        curfbStar = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, False, [mapID])
        if not curfbStar:
            GameWorld.DebugLog("OnEnterFBEvent 首次进入该副本线路免费!mapID=%s,lineID=%s" % (mapID, lineID))
            return True, ""
    #playerID = curPlayer.GetPlayerID()
    enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)
    maxCnt = GetEnterFBMaxCnt(curPlayer, mapID)
@@ -445,18 +455,18 @@
#  @return
def SetFBPropertyMark(propertyMark, setPlayer=None):
    GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_FBDict_PropertyMark, propertyMark + 1) # 存储时+1才能判断是否存储过
    if setPlayer != None:
        PlayerControl.SetFBFuncLineID(setPlayer, propertyMark)
        GameWorld.DebugLog("SetFBPropertyMark 设置玩家副本功能线路ID: %s" % propertyMark, setPlayer.GetPlayerID())
        return
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        if not curPlayer.GetPlayerID():
            continue
        PlayerControl.SetFBFuncLineID(curPlayer, propertyMark)
        GameWorld.DebugLog("SetFBPropertyMark 广播玩家副本功能线路ID: %s" % propertyMark, curPlayer.GetPlayerID())
#    if setPlayer != None:
#        PlayerControl.SetFBFuncLineID(setPlayer, propertyMark)
#        GameWorld.DebugLog("SetFBPropertyMark 设置玩家副本功能线路ID: %s" % propertyMark, setPlayer.GetPlayerID())
#        return
#
#    playerManager = GameWorld.GetMapCopyPlayerManager()
#    for index in xrange(playerManager.GetPlayerCount()):
#        curPlayer = playerManager.GetPlayerByIndex(index)
#        if not curPlayer.GetPlayerID():
#            continue
#        PlayerControl.SetFBFuncLineID(curPlayer, propertyMark)
#        GameWorld.DebugLog("SetFBPropertyMark 广播玩家副本功能线路ID: %s" % propertyMark, curPlayer.GetPlayerID())
    return
## 是否已经扣除入场券/进入次数等
@@ -470,6 +480,15 @@
#  @return
def SetHadDelTicket(curPlayer, delSign=1):
    GameWorld.GetGameFB().SetPlayerGameFBDict(curPlayer.GetID(), ChConfig.FBPlayerDict_IsDelTicket, delSign)
    return
## 自定义场景阶段
def GetCustomMapStep(curPlayer, mapID, lineID):
    return curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_CustomMapStep % (mapID, lineID))
def SetCustomMapStep(curPlayer, mapID, lineID, step):
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_CustomMapStep % (mapID, lineID), step)
    if step == ChConfig.CustomMapStep_Over:
        PlayerControl.SetCustomMap(curPlayer, 0, 0)
    return
def GetCurSingleFBPlayer():
@@ -579,7 +598,7 @@
    return
def GetJsonItemList(itemList):
    ## [[itemID,itemCount,isBind], curItem] -> [{"ItemID":101, "Count":10, "IsBind":1, "IsSuite":1, "UserData":"自定义属性字符串"}]
    ## [[itemID,itemCount,isAuctionItem], curItem] -> [{"ItemID":101, "Count":10, "IsAuctionItem":1, "UserData":"自定义属性字符串"}]
    jsonItemList = []
    for itemInfo in itemList:
        itemDict = {}
@@ -590,7 +609,7 @@
            if infolen > 1:
                itemDict['Count'] = itemInfo[1]
            if infolen > 2:
                itemDict['IsBind'] = int(itemInfo[2])
                itemDict['IsAuctionItem'] = int(itemInfo[2])
        elif isinstance(itemInfo, int):
            itemDict['ItemID'] = itemInfo
        else: #物品实例
@@ -598,8 +617,8 @@
                continue
            itemDict['ItemID'] = itemInfo.GetItemTypeID()
            itemDict['Count'] = itemInfo.GetCount()
            itemDict['IsBind'] = int(itemInfo.GetIsBind())
            itemDict['IsSuite'] = int(itemInfo.GetIsSuite())
            itemDict['IsAuctionItem'] = ItemControler.GetIsAuctionItem(itemInfo)
            #itemDict['IsSuite'] = int(itemInfo.GetIsSuite())
            itemDict['UserData'] = itemInfo.GetUserData()
        jsonItemList.append(itemDict)
    return jsonItemList
@@ -627,7 +646,7 @@
#---------------------------------------------------------------------
def SyncDynamicBarrierState(barrierPointList, state, curPlayer=None):
    '''同步动态障碍物是否有效性
    @param barrierPointList: 障碍物点列表 [[aPosX,aPosY,bPosX,bPosY], [aPosX,aPosY,bPosX,bPosY], ...]
    @param barrierPointList: 障碍物点列表 [[aPosX,aPosY,bPosX,bPosY,angle可选], [aPosX,aPosY,bPosX,bPosY,angle可选], ...]
    @param state: 是否有效
    @param curPlayer: 指定通知目标玩家,为None时广播本地图所有玩家
    '''
@@ -635,12 +654,15 @@
    barrierStatePack.Clear()
    barrierStatePack.State = state
    barrierStatePack.BarrierList = []
    for aPosX, aPosY, bPosX, bPosY in barrierPointList:
    for posInfo in barrierPointList:
        aPosX, aPosY, bPosX, bPosY = posInfo[:4]
        angle = posInfo[4] if len(posInfo) > 4 else 0
        barrier = ChPyNetSendPack.tagMCDynamicBarrier()
        barrier.APosX = aPosX
        barrier.APosY = aPosY
        barrier.BPosX = bPosX
        barrier.BPosY = bPosY
        barrier.Angle = angle
        barrierStatePack.BarrierList.append(barrier)
    barrierStatePack.Count = len(barrierStatePack.BarrierList)
    if curPlayer:
@@ -1014,6 +1036,35 @@
    #可以进入
    return True
#---------------------------------------------------------------------
def Sync_FBNPC(mapID=0, npcIDList=[], curPlayer=None):
    ## 同步当前副本NPC给副本中的所有玩家
    if not mapID:
        mapID = GameWorld.GetMap().GetMapID()
        mapID = GetRecordMapID(mapID)
    npcCntDict = {}
    gameNPCManager = GameWorld.GetNPCManager()
    for index in xrange(gameNPCManager.GetNPCCount()):
        curNPC = gameNPCManager.GetNPCByIndex(index)
        npcID = curNPC.GetNPCID()
        if not npcID:
            continue
        if curNPC.GetGameNPCObjType() == IPY_GameWorld.gnotPet:
            continue
        if npcIDList and npcID not in npcIDList:
            continue
        npcCntDict[npcID] = npcCntDict.get(npcID, 0) + 1
    if curPlayer:
        NPCCommon.SyncNPCCntInfo(curPlayer, mapID, npcCntDict)
    else:
        playerManager = GameWorld.GetMapCopyPlayerManager()
        for i in xrange(playerManager.GetPlayerCount()):
            curPlayer = playerManager.GetPlayerByIndex(i)
            if curPlayer.GetID() == 0:
                continue
            NPCCommon.SyncNPCCntInfo(curPlayer, mapID, npcCntDict)
    return npcCntDict
##获得地图上的NPC列表
# @param 无参数
# @return 返回值, NPC实例列表[curNPC,curNPC,,,,,]
@@ -1430,8 +1481,10 @@
## ---------------------------------- TD ---------------------------------------
def GetEnterFBMaxCnt(curPlayer, mapID):
    ## 获取副本最大可进入次数: 基本次数 + VIP额外次数 + 购买次数 + 找回次数
    ## 获取副本最大可进入次数: 基本次数 + 时间已恢复次数 + VIP额外次数 + 购买次数 + 找回次数 + 使用道具增加次数
    fbIpyData = GetFBIpyData(mapID)
    if not fbIpyData:
        return 0
    maxTimes = fbIpyData.GetDayTimes()
    MWPrivilegeID = fbIpyData.GetExtraTimesMWPriID()
    
@@ -1441,14 +1494,20 @@
    buyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_BuyFbCntDay % mapID)
    recoverFbCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RecoverFbCnt % mapID)
    itemAddCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ItemAddFbCnt % mapID)
    maxCnt = maxTimes + extraCnt + buyCnt + recoverFbCnt + mwAddCnt + itemAddCnt
    regainFbCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RegainFbCnt % mapID)
    maxCnt = maxTimes + regainFbCnt + extraCnt + buyCnt + recoverFbCnt + mwAddCnt + itemAddCnt
    return maxCnt
def GetFBDetailCntInfo(curPlayer, mapID):
    #返回FB剩余正常次数、vip额外次数、已买次数、道具增加次数、未买次数
    #返回FB剩余正常次数、时间恢复次数、vip额外次数、已买次数、道具增加次数、未买次数
    fbIpyData = GetFBIpyData(mapID)
    enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)
    maxTimes = fbIpyData.GetDayTimes()
    maxRegainFbCnt = 0
    recoverIntervalDict = IpyGameDataPY.GetFuncEvalCfg('FBCntRegainInterval', 1)
    if str(mapID) in recoverIntervalDict:
        maxRegainFbCnt = recoverIntervalDict[str(mapID)][0]
    MWPrivilegeID = fbIpyData.GetExtraTimesMWPriID()
    
    mwAddCnt = 0#wmpIpyData.GetEffectValue() if wmpIpyData else 0
@@ -1458,8 +1517,8 @@
    buyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_BuyFbCntDay % mapID)
    recoverFbCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RecoverFbCnt % mapID)
    itemAddCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ItemAddFbCnt % mapID)
    #先用找回来的次数,再用Vip额外次数,再用每日刷新次数和Vip买回来的次数,最后用卷轴加的次数
    cntList = [recoverFbCnt, extraCnt, maxTimes, buyCnt, itemAddCnt]
    #先用找回来的次数,再用Vip额外次数,再用每日刷新次数、时间恢复次数、和Vip买回来的次数,最后用卷轴加的次数
    cntList = [recoverFbCnt, extraCnt, maxTimes, maxRegainFbCnt, buyCnt, itemAddCnt]
    rCntList = copy.deepcopy(cntList)
    sumCnt = 0
    for i, cnt in enumerate(cntList):
@@ -1467,13 +1526,13 @@
        rCntList[i] = max(0, sumCnt - enterCnt)
        if enterCnt <= sumCnt:
            break
    rRecoverFbCnt, rExtraCnt,rCommonCnt,rBuyCnt,rItemAddCnt = rCntList
    rRecoverFbCnt, rExtraCnt, rCommonCnt, rRegainFbCnt, rBuyCnt, rItemAddCnt = rCntList
    #未买次数
    buyTimesVIPPriID = fbIpyData.GetBuyTimesVIPPriID()
    canBuyCnt = PlayerVip.GetPrivilegeValue(curPlayer, buyTimesVIPPriID)
    noBuyCnt = max(0, canBuyCnt-buyCnt)
    return [[rCommonCnt, rExtraCnt, rBuyCnt, rItemAddCnt, noBuyCnt], [maxTimes, extraCnt, canBuyCnt, 10000, canBuyCnt]]
    noBuyCnt = max(0, canBuyCnt - buyCnt)
    return [[rCommonCnt, rRegainFbCnt, rExtraCnt, rBuyCnt, rItemAddCnt, noBuyCnt], [maxTimes, maxRegainFbCnt, extraCnt, canBuyCnt, 10000, canBuyCnt]]
## 玩家进入副本次数
#  @param curPlayer 玩家实例
@@ -1491,7 +1550,10 @@
#  @param fbID 副本id
#  @param addCount 增加次数
#  @return 返回值无意义
def AddEnterFBCount(curPlayer, fbID, addCount=1, lineBit=-1):
def AddEnterFBCount(curPlayer, fbID, addCount=1, lineBit=-1, isFree=False):
    ## @param isFree: 是否免费进入的,免费的不增加实际进入次数,但需要触发进入次数额外处理,如活跃、成就等
    addCountEx = addCount
    addCount = 0 if isFree else addCount
    fbID = GetRecordMapID(fbID)
    enterCntKey = ChConfig.Def_Player_Dict_EnterFbCntDay % fbID
    enterCnt = curPlayer.NomalDictGetProperty(enterCntKey)
@@ -1508,80 +1570,127 @@
        addCount = updCnt-enterCnt
        PlayerControl.NomalDictSetProperty(curPlayer, enterCntKey, updCnt)
        
        PlayerActivity.OnEnterFBActivity(curPlayer, fbID, updCnt, addCount)
        PlayerSuccess.AddEnterFBSuccess(curPlayer, fbID, addCount)
        PlayerActivity.OnEnterFBActivity(curPlayer, fbID, updCnt, addCountEx)
        PlayerSuccess.AddEnterFBSuccess(curPlayer, fbID, addCountEx)
        updValue = updCnt
        #由满到未满时记录开始恢复的时间
        if fbID == ChConfig.Def_FBMapID_SealDemon:
            fbIpyData = GetFBIpyData(fbID)
            dayTimes = fbIpyData.GetDayTimes()
            if maxCnt - enterCnt >= dayTimes and maxCnt - updCnt < dayTimes:
                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % fbID, int(time.time()))
                NotifyFBCntRegainInfo(curPlayer)
    GameWorld.DebugLog("    AddEnterFBCount fbID=%s, addCount=%s, lineBit=%s, enterCnt=%s,updValue=%s" 
                       % (fbID, addCount, lineBit, enterCnt, updValue), curPlayer.GetPlayerID())
    Sync_FBPlayerFBInfoData(curPlayer, fbID)
    OnFBCountChangeEffectRecoverCount(curPlayer, fbID)
    return True
def RegainFBCntProcess(curPlayer):
    #目前只有封魔坛可恢复次数 先特殊做
    mapID = ChConfig.Def_FBMapID_SealDemon
    enterCnt = GetEnterFBCount(curPlayer, mapID)
    fbIpyData = GetFBIpyData(mapID)
    maxDayTimes = fbIpyData.GetDayTimes()
    maxCnt = GetEnterFBMaxCnt(curPlayer, mapID)
    maxCanAdd = max(0, maxDayTimes - (maxCnt-enterCnt))
    #GameWorld.DebugLog('封魔坛最大可恢复次数 %s'%maxCanAdd)
    if not maxCanAdd:
def OnFBCountChangeEffectRecoverCount(curPlayer, mapID):
    ## 副本相关次数变更,包含增加、扣除等影响副本按时间恢复次数相关逻辑处理
    recoverIntervalDict = IpyGameDataPY.GetFuncEvalCfg('FBCntRegainInterval', 1)
    if str(mapID) not in recoverIntervalDict:
        return
    curTime = int(time.time())
    recoverInterval = IpyGameDataPY.GetFuncCfg('FBCntRegainInterval')
    lastRegainTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
    needTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID)
    if not needTime:
        needTime = recoverInterval
    passTime = curTime - lastRegainTime
    if passTime < needTime:
        return
    recoverCnt = min(maxCanAdd, 1 + (passTime-needTime) / recoverInterval) # 恢复次数
    enterCntKey = ChConfig.Def_Player_Dict_EnterFbCntDay % mapID
    newEnterCnt = max(0, enterCnt-recoverCnt)
    PlayerControl.NomalDictSetProperty(curPlayer, enterCntKey, newEnterCnt)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, 0)
    if recoverCnt == maxCanAdd:
    maxCanRecoverCnt, recoverInterval = recoverIntervalDict[str(mapID)]
    curRegainFbCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RegainFbCnt % mapID) # 当前已恢复次数
    if curRegainFbCnt >= maxCanRecoverCnt:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, 0)
        GameWorld.DebugLog("副本时间恢复次数已达当日上限!")
    else:
        startTime = curTime- (passTime-needTime)%recoverInterval
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, startTime)
    GameWorld.DebugLog('    封魔坛恢复次数%s, passTime=%s, needTime=%s'%(recoverCnt, passTime, needTime))
    Sync_FBPlayerFBInfoData(curPlayer, mapID)
    NotifyFBCntRegainInfo(curPlayer)
        curTime = int(time.time())
        fbIpyData = GetFBIpyData(mapID)
        maxFreeTimes = fbIpyData.GetDayTimes() # 常规封顶次数
        enterCnt = GetEnterFBCount(curPlayer, mapID) # 已经进入次数
        maxCnt = GetEnterFBMaxCnt(curPlayer, mapID) # 当前可用最大次数
        remainCanEnterCnt = maxCnt - enterCnt # 剩余可进入次数
        regainStartTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
        passTime = curTime - regainStartTime
        # 到达常规次数上限,暂时恢复时间
        if remainCanEnterCnt >= maxFreeTimes:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, 0)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, 0)
            GameWorld.DebugLog("副本时间恢复次数已达常规次数!")
        elif passTime < recoverInterval:
            pass
            #GameWorld.DebugLog("副本时间恢复次数还未到达恢复CD!")
        else:
            if not regainStartTime:
                updRegainTotalTime = recoverInterval
            else:
                updRegainTotalTime = recoverInterval - passTime % recoverInterval
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, curTime)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, updRegainTotalTime)
            GameWorld.DebugLog("副本还可按时间恢复次数!curTime=%s,regainStartTime=%s,passTime=%s,updRegainTotalTime=%s"
                               % (curTime, regainStartTime, passTime, updRegainTotalTime))
    NotifyFBCntRegainInfo(curPlayer, [mapID])
    return
def NotifyFBCntRegainInfo(curPlayer):
    ##通知副本次数恢复剩余时间
    curTime = int(time.time())
    recoverInterval = IpyGameDataPY.GetFuncCfg('FBCntRegainInterval')
def RegainFBCntProcess(curPlayer):
    ## 按时间恢复副本次数
    
    regainData = ChPyNetSendPack.tagMCFBCntRegainRemainTime()
    regainData.Clear()
    regainData.InfoList = []
    for mapID in [ChConfig.Def_FBMapID_SealDemon]:
    curTime = int(time.time())
    recoverIntervalDict = IpyGameDataPY.GetFuncEvalCfg('FBCntRegainInterval', 1)
    for mapIDStr, recoverInfo in recoverIntervalDict.items():
        mapID = int(mapIDStr)
        maxCanRecoverCnt, recoverInterval = recoverInfo
        curRegainFbCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RegainFbCnt % mapID) # 当前已恢复次数
        if maxCanRecoverCnt and curRegainFbCnt >= maxCanRecoverCnt:
            #GameWorld.DebugLog("已到达副本恢复次数上限!mapID=%s,curRegainFbCnt(%s) >= maxCanRecoverCnt(%s)" % (mapID, curRegainFbCnt, maxCanRecoverCnt))
            continue
        fbIpyData = GetFBIpyData(mapID)
        maxFreeTimes = fbIpyData.GetDayTimes() # 常规封顶次数
        enterCnt = GetEnterFBCount(curPlayer, mapID) # 已经进入次数
        maxCnt = GetEnterFBMaxCnt(curPlayer, mapID) # 当前可用最大次数
        remainCanEnterCnt = maxCnt - enterCnt # 剩余可进入次数
        if remainCanEnterCnt >= maxFreeTimes:
            #GameWorld.DebugLog("可进入次数已经到达常规封顶次数!mapID=%s,remainCanEnterCnt=%s" % (mapID, remainCanEnterCnt))
            continue
        regainStartTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
        if not regainStartTime:
            #GameWorld.DebugLog("还未设置副本恢复次数倒计时!mapID=%s" % mapID)
            continue
        needTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID)
        passTime = curTime - regainStartTime
        if passTime < needTime:
            continue
        remainTime = passTime - needTime # 扣除恢复单次后剩余的时间,离线上线后可能一次性恢复多次
        recoverCnt = 1 + remainTime / recoverInterval # 倒计时时间可恢复总次数
        realRecoverCnt = min(maxFreeTimes - remainCanEnterCnt, recoverCnt) # 实际最大可恢复总次数
        if maxCanRecoverCnt:
            realRecoverCnt = min(realRecoverCnt, maxCanRecoverCnt - curRegainFbCnt)
        if realRecoverCnt <= 0:
            continue
        # 更新时间倒计时已恢复次数
        updRegainFbCnt = curRegainFbCnt + realRecoverCnt
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_RegainFbCnt % mapID, updRegainFbCnt)
        OnFBCountChangeEffectRecoverCount(curPlayer, mapID)
    return
def NotifyFBCntRegainInfo(curPlayer, syncMapIDList=[]):
    ##通知副本次数恢复剩余时间
    recoverIntervalDict = IpyGameDataPY.GetFuncEvalCfg('FBCntRegainInterval', 1) # {mapID:[次数, 每次间隔], ...}
    if not recoverIntervalDict:
        return
    if not syncMapIDList:
        syncMapIDList = [int(mapIDStr) for mapIDStr in recoverIntervalDict.keys()]
    infoList = []
    curTime = int(time.time())
    for mapID in syncMapIDList:
        if str(mapID) not in recoverIntervalDict:
            continue
        mapInfo = ChPyNetSendPack.tagMCFBCntRegain()
        mapInfo.Clear()
        mapInfo.DataMapID = mapID
        lastRegainTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
        needTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID)
        if not needTime:
            needTime = recoverInterval
        passTime = curTime - lastRegainTime
        if passTime >= needTime:
            continue
        mapInfo.RemainTime = needTime - passTime
        regainData.InfoList.append(mapInfo)
    if not regainData.InfoList:
        mapInfo.RemainTime = max(0, needTime - passTime)
        mapInfo.RegainCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_RegainFbCnt % mapID)
        infoList.append(mapInfo)
    if not infoList:
        return
    regainData = ChPyNetSendPack.tagMCFBCntRegainRemainTime()
    regainData.Clear()
    regainData.InfoList = infoList
    regainData.Cnt = len(regainData.InfoList)
    NetPackCommon.SendFakePack(curPlayer, regainData)
    return
@@ -1680,20 +1789,30 @@
        itemAddCntKey = ChConfig.Def_Player_Dict_ItemAddFbCnt % mapID
        itemAddCnt = curPlayer.NomalDictGetProperty(itemAddCntKey)
        PlayerControl.NomalDictSetProperty(curPlayer, itemAddCntKey, 0)
        GameWorld.DebugLog("    重置:mapID=%s,dayTimes=%s,buyCnt=%s,recoverCnt=%s,itemAddCnt=%s,maxCnt=%s,enterCnt=%s"
                           % (mapID, dayTimes, buyCnt, recoverCnt, itemAddCnt, maxCnt, enterCnt))
        # 按时间CD恢复次数类型的副本特殊处理,重置时间点不会重置,需要保持当前剩余次数不变, 如: 封魔坛
        if mapID in [ChConfig.Def_FBMapID_SealDemon]:
            newEnterCnt = max(0, dayTimes - (maxCnt - enterCnt))
            PlayerControl.NomalDictSetProperty(curPlayer, enterCntKey, newEnterCnt)
            GameWorld.DebugLog("        特殊副本已进入次数更新: newEnterCnt=%s" % newEnterCnt)
        # 时间恢复次数
        regainFBCntKey = ChConfig.Def_Player_Dict_RegainFbCnt % mapID
        regainFBCnt = curPlayer.NomalDictGetProperty(regainFBCntKey)
        PlayerControl.NomalDictSetProperty(curPlayer, regainFBCntKey, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, 0)
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, 0)
        GameWorld.DebugLog("    重置:mapID=%s,dayTimes=%s,buyCnt=%s,recoverCnt=%s,itemAddCnt=%s,regainFBCnt=%s,maxCnt=%s,enterCnt=%s"
                           % (mapID, dayTimes, buyCnt, recoverCnt, itemAddCnt, regainFBCnt, maxCnt, enterCnt))
        if mapID == ChConfig.Def_FBMapID_ZhuXianBoss:
            if GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_ZhuXianBoss):
                curCnt = min(maxCnt - enterCnt + IpyGameDataPY.GetFuncCfg('ZhuXianBossCntCfg'), IpyGameDataPY.GetFuncCfg('ZhuXianBossCntCfg', 2))
                if curCnt > dayTimes:
                    PlayerControl.NomalDictSetProperty(curPlayer, itemAddCntKey, curCnt - dayTimes)
                elif curCnt < dayTimes:
                    PlayerControl.NomalDictSetProperty(curPlayer, enterCntKey, dayTimes - curCnt)
            
        mapIDInfo.append(mapID)
        
    if mapIDInfo:
        Sync_FBPlayerFBInfoData(curPlayer, mapIDInfo)
        Sync_FBPlayerFBBuyCount(curPlayer, mapIDInfo)
        NotifyFBCntRegainInfo(curPlayer, mapIDInfo)
    
    return
@@ -1753,6 +1872,9 @@
    if mapID == ChConfig.Def_FBMapID_SealDemon and maxDayTimes and maxCnt - enterCnt >= maxDayTimes:
        GameWorld.DebugLog('当前次数已满,无需购买。。')
        return
    if mapID == ChConfig.Def_FBMapID_ZhuXianBoss and maxCnt - enterCnt >= IpyGameDataPY.GetFuncCfg('ZhuXianBossCntCfg', 2):
        return
    if hasBuyCnt >= canBuyCnt:
        GameWorld.DebugLog("购买次数已经用完mapID=%s"%mapID)
        return
@@ -1772,16 +1894,7 @@
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_BuyFbCntDay % mapID, hasBuyCnt + 1)
    Sync_FBPlayerFBBuyCount(curPlayer, [mapID])
    PlayerControl.NotifyCode(curPlayer, 'FBEnterTimeBuy', [mapID])
    lastRegainTime= curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
    if lastRegainTime:
        maxCnt = GetEnterFBMaxCnt(curPlayer, mapID)
        if maxCnt - enterCnt == maxDayTimes:
            curTime = int(time.time())
            needTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID)
            if not needTime:
                needTime = IpyGameDataPY.GetFuncCfg('FBCntRegainInterval')
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID, needTime - (curTime-lastRegainTime))
            NotifyFBCntRegainInfo(curPlayer)
    OnFBCountChangeEffectRecoverCount(curPlayer, mapID)
    return
def DoFuncOpen_RunDaily(curPlayer): return EventReport.WriteFuncCMEAcceptable(curPlayer, ShareDefine.GameFuncID_RunDaily)
@@ -1899,7 +2012,7 @@
#  @param tick 当前时间
#  @param isMaxlv 是否直接满级
#  @return None
def FbEncourageBuff(curPlayer, key, encourageType, tick, isMaxlv=False):
def FbEncourageBuff(curPlayer, key, encourageType, tick, ownerID=0):
    #GameWorld.Log("FbEncourageBuff moneyType=%s" % (moneyType))
    curMapID = curPlayer.GetMapID()
    curMapID = GetRecordMapID(curMapID)
@@ -1908,10 +2021,10 @@
        return
    maxCnt = ipyData.GetInspireMaxLV()
    gameFB = GameWorld.GetGameFB()
    curPlayerID = curPlayer.GetID()
    encourageLV = gameFB.GetPlayerGameFBDictByKey(curPlayerID, key)
    ownerID = ownerID or curPlayer.GetID()
    encourageLV = gameFB.GetPlayerGameFBDictByKey(ownerID, key)
    encourageCntKey = 'FbEncourageCnt_%s' % encourageType
    encourageCnt = gameFB.GetPlayerGameFBDictByKey(curPlayerID, encourageCntKey)
    encourageCnt = gameFB.GetPlayerGameFBDictByKey(ownerID, encourageCntKey)
    maxLV = IpyGameDataPY.GetFuncEvalCfg('FBEncourageBuff', 2, {}).get(curMapID, 0)
    if encourageLV >= maxLV:
        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_93643")
@@ -1946,29 +2059,47 @@
        return
    
    buffType = SkillCommon.GetBuffType(skillBuff)
    BuffSkill.DoAddBuff(curPlayer, buffType, skillBuff, tick)
    gameFB.SetPlayerGameFBDict(curPlayerID, key, encourageLV+1)
    gameFB.SetPlayerGameFBDict(curPlayerID, encourageCntKey, encourageCnt+1)
    gameFB.SetPlayerGameFBDict(ownerID, key, encourageLV+1)
    gameFB.SetPlayerGameFBDict(ownerID, encourageCntKey, encourageCnt+1)
    #GameWorld.Log("FbEncourageBuff encourage nextLV=%s success" % encourageLV)
    addHurtNum = IpyGameDataPY.GetFuncEvalCfg('FBEncourageBuff', 3, {}).get(curMapID, 0)
    PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_628920", [(encourageLV+1)*addHurtNum])
    SendFBEncourageInfo(curPlayer, encourageLV+1)
    #成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FBEncourage, 1, [curMapID])
    EventShell.EventRespons_FBEncourage(curPlayer, curMapID)
    return
    if curMapID == ChConfig.Def_FBMapID_AllFamilyBoss:
        #给副本里所有盟成员提示
        playerManager = GameWorld.GetMapCopyPlayerManager()
        for index in xrange(playerManager.GetPlayerCount()):
            player = playerManager.GetPlayerByIndex(index)
            if not player:
                continue
            if player.GetFamilyID() != ownerID:
                continue
            BuffSkill.DoAddBuff(player, buffType, skillBuff, tick)
            PlayerControl.NotifyCode(player, "AllianceBossText2", [curPlayer.GetName(), encourageLV+1])
            SendFBEncourageInfo(player, encourageLV+1, ownerID)
            if player.GetID() == curPlayer.GetID():
                PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FBEncourage, 1, [curMapID])
                EventShell.EventRespons_FBEncourage(curPlayer, curMapID)
    else:
        BuffSkill.DoAddBuff(curPlayer, buffType, skillBuff, tick)
        PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_628920", [(encourageLV+1)*addHurtNum])
        SendFBEncourageInfo(curPlayer, encourageLV+1, ownerID)
        #成就
        PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FBEncourage, 1, [curMapID])
        EventShell.EventRespons_FBEncourage(curPlayer, curMapID)
    return True
## 添加副本鼓舞buff,一般用于玩家掉线后,在规定时间内重新上线回到副本时重新上buff
#  @param curPlayer 玩家
#  @param key 副本玩家字典key
#  @param tick 当前时间
#  @return None
def AddFbEncourageBuff(curPlayer, key, tick):
def AddFbEncourageBuff(curPlayer, key, tick, ownerID=0):
    curPlayerID = curPlayer.GetID()
    GameWorld.Log("AddFbEncourageBuff() curPlayerID=%s" % curPlayerID)
    ownerID = ownerID or curPlayer.GetID()
    gameFB = GameWorld.GetGameFB()
    encourageLV = gameFB.GetPlayerGameFBDictByKey(curPlayerID, key)
    encourageLV = gameFB.GetPlayerGameFBDictByKey(ownerID, key)
    if not encourageLV:
        return
    mapID = GameWorld.GetMap().GetMapID()
@@ -1983,7 +2114,7 @@
    buffType = SkillCommon.GetBuffType(skillBuff)
    BuffSkill.DoAddBuff(curPlayer, buffType, skillBuff, tick)
    
    SendFBEncourageInfo(curPlayer, encourageLV)
    SendFBEncourageInfo(curPlayer, encourageLV, ownerID)
    return
## 清除鼓舞buff
@@ -2003,7 +2134,7 @@
## 发送副本鼓舞信息
#  @param curPlayer 玩家
#  @return None
def SendFBEncourageInfo(curPlayer, lv):
def SendFBEncourageInfo(curPlayer, lv, ownerID=0):
    #//A3 0A 副本鼓舞信息通知 #tagMCFBEncourageInfo
    curMapID = curPlayer.GetMapID()
    curMapID = GetRecordMapID(curMapID)
@@ -2015,12 +2146,12 @@
    encourageInfo.InfoList = []
    encourageCntKey = 'FbEncourageCnt_%s'
    gameFB = GameWorld.GetGameFB()
    curPlayerID = curPlayer.GetID()
    ownerID = ownerID or curPlayer.GetID()
    for ipyData in ipyDataList:
        inspireType = ipyData.GetInspireType()
        packData = ChPyNetSendPack.tagMCFBEncourageCnt()
        packData.MoneyType = inspireType
        packData.EncourageCnt = gameFB.GetPlayerGameFBDictByKey(curPlayerID, encourageCntKey % inspireType)
        packData.EncourageCnt = gameFB.GetPlayerGameFBDictByKey(ownerID, encourageCntKey % inspireType)
        encourageInfo.InfoList.append(packData)
    encourageInfo.Cnt = len(encourageInfo.InfoList)
    NetPackCommon.SendFakePack(curPlayer, encourageInfo)
@@ -2374,4 +2505,11 @@
        fbHelpFunc(curPlayer, tick)
    return
def GetCrossDynamicLineMapZoneID():
    ## 获取跨服动态线路地图本线路跨服分区
    return GameWorld.GetGameWorld().GetPropertyID() / 10000
def GetCrossDynamicLineMapFuncLineID():
    ## 获取跨服动态线路地图本线路功能线路ID
    return GameWorld.GetGameWorld().GetPropertyID() % 10000 / 10