ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/FBCommon.py
@@ -90,6 +90,7 @@
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' #进入时等级
@@ -1472,7 +1473,7 @@
## ---------------------------------- TD ---------------------------------------
def GetEnterFBMaxCnt(curPlayer, mapID):
    ## 获取副本最大可进入次数: 基本次数 + VIP额外次数 + 购买次数 + 找回次数
    ## 获取副本最大可进入次数: 基本次数 + 时间已恢复次数 + VIP额外次数 + 购买次数 + 找回次数 + 使用道具增加次数
    fbIpyData = GetFBIpyData(mapID)
    maxTimes = fbIpyData.GetDayTimes()
    MWPrivilegeID = fbIpyData.GetExtraTimesMWPriID()
@@ -1483,14 +1484,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
@@ -1500,8 +1507,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):
@@ -1509,13 +1516,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 玩家实例
@@ -1553,92 +1560,124 @@
        PlayerActivity.OnEnterFBActivity(curPlayer, fbID, updCnt, addCount)
        PlayerSuccess.AddEnterFBSuccess(curPlayer, fbID, addCount)
        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)
    curTime = int(time.time())
    lastRegainTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID)
    if not lastRegainTime:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, curTime)
        return
    recoverInterval = IpyGameDataPY.GetFuncCfg('FBCntRegainInterval')
    needTime = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainTotalTime % mapID)
    if not needTime:
        needTime = recoverInterval
    passTime = curTime - lastRegainTime
    if passTime < needTime:
        return
    recoverCnt = 1 + (passTime-needTime) / recoverInterval # 恢复次数
    if recoverCnt > maxCanAdd:
        #记录超出的次数,用于资源找回
        beyondTimes = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FbCntRegainOverTime % mapID)
        updBeyondTimes = recoverCnt - maxCanAdd + beyondTimes
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainOverTime % mapID, updBeyondTimes)
        if not maxCanAdd:
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, curTime)
        GameWorld.DebugLog('    封魔坛恢复次数 记录超出的次数addOverCnt=%s, updBeyondTimes=%s'%(recoverCnt-maxCanAdd, updBeyondTimes))
def OnFBCountChangeEffectRecoverCount(curPlayer, mapID):
    ## 副本相关次数变更,包含增加、扣除等影响副本按时间恢复次数相关逻辑处理
    
    if not maxCanAdd:
    recoverIntervalDict = IpyGameDataPY.GetFuncEvalCfg('FBCntRegainInterval', 1)
    if str(mapID) not in recoverIntervalDict:
        return
    recoverCnt = min(maxCanAdd, recoverCnt)
    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:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainStartTime % mapID, curTime)
    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
@@ -1737,16 +1776,17 @@
        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)
            PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FbCntRegainOverTime % mapID, 0)
            GameWorld.DebugLog("        特殊副本已进入次数更新: newEnterCnt=%s" % newEnterCnt)
        elif mapID == ChConfig.Def_FBMapID_ZhuXianBoss:
        # 时间恢复次数
        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:
@@ -1759,6 +1799,7 @@
    if mapIDInfo:
        Sync_FBPlayerFBInfoData(curPlayer, mapIDInfo)
        Sync_FBPlayerFBBuyCount(curPlayer, mapIDInfo)
        NotifyFBCntRegainInfo(curPlayer, mapIDInfo)
    
    return
@@ -1840,16 +1881,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)