ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerFB.py
@@ -23,31 +23,16 @@
#------------------------------------------------------------------------------ 
#"""Version = 2016-12-02 11:00"""
#------------------------------------------------------------------------------ 
import ReadChConfig
import IPY_GameWorld
import PlayerControl
import GameWorld
import FBCommon
import ChConfig
import FBLogic
import ChPyNetSendPack
import NetPackCommon
import PlayerSuccess
import ItemCommon
import IpyGameDataPY
import ShareDefine
import GameFuncComm
import SkillShell
import PyGameData
import PetControl
import NPCCommon
import GameObj
import time
import math
#---------------------------------------------------------------------
def OnLogin(curPlayer):
    NotifyBuyFBBuffInfo(curPlayer)
    return
## 玩家副本行为封包 A5 08
@@ -62,180 +47,6 @@
    FBLogic.DoFBAction(curPlayer, actionType, actionInfo, tick)
    return
## A2 10 清除副本CD#tagCMClearFBCD
#  @param playerIndex 玩家索引
#  @param clientData 客户端封包
#  @param tick 时间
#  @return None
def OnClearFBCD(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    mapID = clientData.MapID # mapID
    GameWorld.DebugLog("OnClearFBCD mapID=%s" % mapID)
    if not mapID:
        return
    enterCDTick = FBCommon.GetFBEnterCD(curPlayer, mapID)
    if enterCDTick <= 0:
        GameWorld.DebugLog("    CD时间已过,不需要清除, cdTick=%s" % enterCDTick)
        return
    clearEnterCDDict = IpyGameDataPY.GetFuncEvalCfg('FBEnterCD', 2)
    if mapID not in clearEnterCDDict:
        return
    costMoney = clearEnterCDDict[mapID]
    costMoneyList = PlayerControl.HaveMoneyEx(curPlayer, ShareDefine.TYPE_Price_Gold_Paper_Money, costMoney)
    if not costMoneyList:
        return
    second = enterCDTick # 参数秒
    # 扣除消耗
    infoDict = {"MapID":mapID, "CDSecond":second}
    for moneyType, moneyCnt in costMoneyList:
        if not PlayerControl.PayMoney(curPlayer, moneyType, moneyCnt, ChConfig.Def_Cost_ClearFBCD, infoDict):
            return
    GameWorld.DebugLog("   mapID=%s 清除副本CD second=%s,costMoneyList=%s"
                         % (mapID, second, costMoneyList), curPlayer.GetPlayerID())
    FBCommon.SetFBPDictValue(curPlayer, ChConfig.Def_PDict_LastEnterFBTick % mapID, 0)
    FBCommon.SyncFBEnterTick(curPlayer)
    return
#---封包开始扫荡-------------------------------------
(
PCDFB_MapIDList, # 副本地图ID列表
PCDFB_NeedTime, # 扫荡时间, 秒
PCDFB_FinishTimeGold, # 立即完成消耗钻石公式
) = range(3)
## 判断是否当前公共CD副本扫荡中
def IsCurPubCDFBSweeping(curPlayer, mapID):
    sweepCfg = GetPubCDFBSweepCfg(curPlayer, mapID)
    if not sweepCfg:
        return False
    groupNum = sweepCfg[0]
    return curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_MapID % groupNum) == mapID
## 获取公共CD副本扫荡配置信息
def GetPubCDFBSweepCfg(curPlayer, mapID):
    PubCDFBSweepDict = ReadChConfig.GetEvalChConfig("PubCDFBSweep")
    for groupNum, sweepInfo in PubCDFBSweepDict.items():
        mapIDGroup = sweepInfo[0]
        if mapID not in mapIDGroup:
            continue
        return groupNum, sweepInfo
    return
## 开始公共CD副本扫荡
def __DoStartPubCDFBSweep(curPlayer, mapID, lineID, cnt, isFinish, dataEx, groupNum, sweepInfo):
    curSweepMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_MapID % groupNum)
    if curSweepMapID > 0:
        GameWorld.DebugLog("公共CD副本扫荡中, 无法扫荡!groupNum=%s,curSweepMapID=%s"
                           % (groupNum, curSweepMapID), curPlayer.GetPlayerID())
        return
    if not FBLogic.OnStartPubCDFBSweep(curPlayer, mapID, lineID, cnt, dataEx):
        return
    curTime = int(time.time())
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_MapID % groupNum, mapID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_LineID % groupNum, lineID)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_Cnt % groupNum, cnt)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_DataEx % groupNum, dataEx)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_Time % groupNum, curTime)
    GameWorld.DebugLog("公共CD副本开始扫荡 mapID=%s,lineID=%s,cnt=%s,dataEx=%s,groupNum=%s,curTime=%s"
                       % (mapID, lineID, cnt, dataEx, groupNum, curTime), curPlayer.GetPlayerID())
    Sync_PubFBSweepData(curPlayer, groupNum)
    return
## 完成公共CD副本扫荡
def __DoFinishPubCDFB(curPlayer, mapID, isFinish, groupNum, sweepInfo):
    playerID = curPlayer.GetPlayerID()
    curSweepMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_MapID % groupNum)
    if curSweepMapID <= 0 or curSweepMapID != mapID:
        GameWorld.DebugLog("未扫荡 或 不是当前正在扫荡的公共CD副本, 无法完成!curSweepMapID=%s,mapID=%s"
                           % (curSweepMapID, mapID), playerID)
        return
    sweepTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_Time % groupNum)
    lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_LineID % groupNum)
    sweepCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_Cnt % groupNum)
    dataEx = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_DataEx % groupNum)
    sweepNeedTime = sweepInfo[PCDFB_NeedTime] # 单次耗时
    finishCostGoldFormat = sweepInfo[PCDFB_FinishTimeGold]
    needTotalTime = sweepNeedTime * sweepCnt
    curTime = int(time.time())
    passTime = max(0, curTime - sweepTime)
    second = max(0, needTotalTime - passTime)
    # 正常完成
    if isFinish == 2 and second > 0:
        GameWorld.DebugLog("扫荡时间未到,无法完成,剩余%s秒, mapID=%s" % (second, mapID), playerID)
        return
    addDataDict = {"curTime":curTime, "startSweepTime":sweepTime, "sweepCnt":sweepCnt,
                   "needTotalTime":needTotalTime, "passTime":passTime, "remainSecond":second,
                   "costGold":0, "mapID":mapID, "lineID":lineID, "dataEx":dataEx, ChConfig.Def_Cost_Reason_SonKey:mapID}
    # 钻石立即完成
    if isFinish == 1:
        costGold = eval(finishCostGoldFormat)
        if costGold > 0:
            addDataDict["costGold"] = costGold
            if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, costGold,
                                          ChConfig.Def_Cost_FinishFBSweep, addDataDict):
                return
    GameWorld.DebugLog("公共CD副本扫荡完成: %s" % str(addDataDict), playerID)
    # 给奖励
    FBLogic.OnGivePubCDFBSweepPrize(curPlayer, mapID, lineID, sweepCnt, dataEx)
    # 重置扫荡数据
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_MapID % groupNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_LineID % groupNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_Cnt % groupNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_DataEx % groupNum, 0)
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_PubCDFBS_Time % groupNum, 0)
    Sync_PubFBSweepData(curPlayer, groupNum)
    return
## 同步公共CD副本扫荡信息
def Sync_PubFBSweepData(curPlayer, groupNum=-1):
    PubCDFBSweepDict = ReadChConfig.GetEvalChConfig("PubCDFBSweep")
    allGroupNumList = PubCDFBSweepDict.keys()
    if groupNum == -1:
        groupNumList = allGroupNumList
    else:
        if groupNum not in allGroupNumList:
            return
        groupNumList = [groupNum]
    pubSweepData = ChPyNetSendPack.tagMCPubFBSweepData()
    pubSweepData.Clear()
    pubSweepData.SweepDatList = []
    for gNum in groupNumList:
        sweepInfo = ChPyNetSendPack.tagMCPubFBSweep()
        sweepInfo.Clear()
        sweepInfo.PubNum = gNum
        sweepInfo.FBMapID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_MapID % gNum)
        sweepInfo.LineID = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_LineID % gNum)
        sweepInfo.SweepTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_Time % gNum)
        sweepInfo.SweepCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_PubCDFBS_Cnt % gNum)
        pubSweepData.SweepDatList.append(sweepInfo)
    pubSweepData.Cnt = len(pubSweepData.SweepDatList)
    NetPackCommon.SendFakePack(curPlayer, pubSweepData)
    return
#//A5 05 玩家开始副本扫荡 #tagCMBeginFBWipeOut
#
#struct    tagCMBeginFBWipeOut
@@ -244,378 +55,48 @@
#    DWORD        MapID;
#    WORD        LineID;
#    BYTE        Cnt;    // 扫荡次数
#    BYTE        IsFinish;    // 是否立即完成; 0-否;1-花钱立即完成;2-客户端自行倒计时间到后发送2代表领取扫荡完成奖励
#    DWORD        DataEx;    //附带信息
#    BYTE        IsLittleHelper;    // 是否小助手扫荡
#};
def OnPlayerFBWipeOut(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    
    #if not GameWorld.CheckPlayerTick(curPlayer, ChConfig.TYPE_Player_Tick_BeginFBWipeOut, tick):
    #    GameWorld.DebugLog("玩家副本扫荡请求CD中...", curPlayer.GetPlayerID())
    #    return
    mapID = clientData.MapID
    lineID = clientData.LineID
    cnt = clientData.Cnt
    #isFinish = clientData.IsFinish
    isFinish = 1 # 暂时默认1,之后有需要扫荡等待的再说
    dataEx = clientData.DataEx
    isLittleHelper = clientData.IsLittleHelper
    if isLittleHelper:
        if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_LittleHelper):
            GameWorld.DebugLog("玩家没有小助手功能权限!", curPlayer.GetPlayerID())
            return
    
    if cnt <= 0:
        return
    
    fbIpyData = FBCommon.GetFBIpyData(mapID)
    if FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID()) == FBCommon.GetRecordMapID(mapID):
        if fbIpyData and fbIpyData.GetDayTimes():#没有限制进入次数的不限制在目标地图扫荡
            GameWorld.DebugLog("玩家在扫荡目标地图中,无法扫荡!mapID=%s" % mapID)
            return
    fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID, False)
    if not fbIpyData or not fbLineIpyData:
        GameWorld.DebugLog("不存在该副本或线路无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
        return
    
    fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID)
    if not fbLineIpyData:
        GameWorld.DebugLog("找不到该副本线路,无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
    if not FBCommon.IsFBPass(curPlayer, mapID, lineID):
        GameWorld.DebugLog("未过关无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
        return
    
    if FBCommon.CheckCanEnterFBComm(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, cnt) != ShareDefine.EntFBAskRet_OK:
        return
    costMoneyList = []
    sweepCostindexList = []
    sweepCostCnt = 0
    itemPack = curPlayer.GetItemManager().GetPack(IPY_GameWorld.rptItem)
    if fbLineIpyData:
        #扫荡等级判断
        sweepLVLimit = fbLineIpyData.GetSweepLVLimit()
        if sweepLVLimit and curPlayer.GetLV() < sweepLVLimit:
            GameWorld.DebugLog('玩家副本扫荡,等级不足!mapID=%s, lineID=%s, playerLV=%s, sweepLVLimit=%s'
                               % (mapID, lineID, curPlayer.GetLV(), sweepLVLimit), curPlayer.GetPlayerID())
            return
        #扫荡道具判断,小助手不消耗扫荡道具
        sweepItemID = fbLineIpyData.GetSweepItemID()
        if sweepItemID and not isLittleHelper:
            sweepItemCnt = fbLineIpyData.GetSweepCostCnt()
            sweepCostCnt = sweepItemCnt * cnt
            #isEnough, sweepCostindexList = ItemCommon.GetItem_FromPack_ByID(sweepItemID, itemPack, sweepCostCnt)
            isEnough, sweepCostindexList, hasBind, lackCnt = ItemCommon.GetItem_FromPack_ByID_ExEx(sweepItemID, itemPack, sweepCostCnt)
            if not isEnough:
                itemPrice = ItemCommon.GetShopItemPrice(sweepItemID, IPY_GameWorld.TYPE_Price_Gold_Money)
                if itemPrice:
                    costMoney = itemPrice * lackCnt
                    costMoneyList = PlayerControl.HaveMoneyEx(curPlayer, ShareDefine.TYPE_Price_Gold_Paper_Money, costMoney)
                if not costMoneyList:
                    GameWorld.DebugLog("扫荡消耗道具不足, mapID=%s,lineID=%s,sweepItemID=%s,sweepCostCnt=%s"
                                   % (mapID, lineID, sweepItemID, sweepCostCnt), curPlayer.GetPlayerID())
                    return
    #公共CD扫荡模式暂屏蔽,有需要再修改
    #===============================================================================================
    # groupNum = -1
    # sweepInfo = None
    # PubCDFBSweepDict = ReadChConfig.GetEvalChConfig("PubCDFBSweep")
    # for gNum, sInfo in PubCDFBSweepDict.items():
    #    if mapID in sInfo[PCDFB_MapIDList]:
    #        groupNum = gNum
    #        sweepInfo = sInfo
    #        break
    #
    # # 公共CD副本扫荡
    # if groupNum >= 0:
    #    if not isFinish:
    #        __DoStartPubCDFBSweep(curPlayer, mapID, lineID, cnt, isFinish, dataEx, groupNum, sweepInfo)
    #    else:
    #        __DoFinishPubCDFB(curPlayer, mapID, isFinish, groupNum, sweepInfo)
    #    return
    #===============================================================================================
    
    # 副本是否可扫荡, 这里只判断副本自身的特殊条件, 公共条件上面已经判断
    if not FBLogic.OnPlayerFBSweepAsk(curPlayer, mapID, lineID, cnt, isFinish, dataEx):
    if not FBLogic.OnPlayerFBSweepAsk(curPlayer, mapID, lineID, cnt, dataEx):
        GameWorld.DebugLog("该副本当前无法扫荡!mapID=%s, lineID=%s" % (mapID, lineID))
        return
    
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_FBSweep, 1, [mapID])
    #扣除扫荡道具
    if sweepCostindexList and sweepCostCnt:
        ItemCommon.ReduceItem(curPlayer, itemPack, sweepCostindexList, sweepCostCnt, False, 'FBSweepCostItem')
    if costMoneyList:
        infoDict = {"MapID":mapID, "LineID":lineID, 'SweepCount':cnt}
        for moneyType, moneyNum in costMoneyList:
            if not PlayerControl.PayMoney(curPlayer, moneyType, moneyNum, ChConfig.Def_Cost_FBSweep, infoDict):
                return False, hasBind
    #PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FeastRedPack_FBSweep, 1, [mapID])
    
    #需先扣除门票, 再增加次数, 否则可能导致扣除的数量错误
    FBCommon.DelFBEnterTicket(curPlayer, mapID, lineID, cnt)
    #FBCommon.DelFBEnterTicket(curPlayer, mapID, lineID, cnt)
    #增加副本进入次数
    if fbIpyData and fbIpyData.GetDayTimes():
        FBCommon.AddEnterFBCount(curPlayer, mapID, cnt)
        
    #扫荡结果给奖励等
    FBLogic.OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, isFinish, dataEx)
    return
#// A5 1B 购买挑战副本精力 #tagCMBuyFBEnergy
#
#struct    tagCMBuyFBEnergy
#{
#    tagHead         Head;
#};
def OnPlayerBuyFBEnergy(playerIndex, clientData, tick):
    #curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    return
## 玩家副本功能时间处理
def DoPlayerFBTimeProcess(curPlayer, tick):
    checkInterval = ChConfig.TYPE_Player_Tick_Time[ChConfig.TYPE_Player_Tick_FBTimeProcess]
    if tick - curPlayer.GetTickByType(ChConfig.TYPE_Player_Tick_FBTimeProcess) < checkInterval:
        return
    curPlayer.SetTickByType(ChConfig.TYPE_Player_Tick_FBTimeProcess, tick)
    # 领主霸业玩家功能时间处理
    FBCommon.RegainFBCntProcess(curPlayer)
    return
#// B1 02 领取多倍副本奖励 #tagCMGetMultiFBPrize
#
#struct    tagCMGetMultiFBPrize
#{
#    tagHead         Head;
#    DWORD        MapID;
#    WORD        LineID;
#    WORD        Percent;    // 额外奖励百分比奖励等级
#};
def OnPlayerGetMultiFBPrize(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    mapID = clientData.MapID
    lineID = clientData.LineID
    prizeExLV = clientData.Percent
    FBLogic.OnGetMultiFBPrize(curPlayer, mapID, lineID, prizeExLV)
    return
#//A5 60 重置副本挑战次数 #tagCMResetFBJoinCnt
#
#struct tagCMResetFBJoinCnt
#{
#    tagHead        Head;
#};
def OnPlayerResetFBJoinCnt(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    return
#// B1 01 客户端副本发送结束 #tagCMClientEndFB
#
#struct    tagCMClientEndFB
#{
#    tagHead         Head;
#    DWORD        MapID;
#    WORD        LineID;
#    DWORD        Data;    //副本数据
#};
def OnClientEndFB(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    mapID = clientData.MapID
    lineID = clientData.LineID
    data1 = clientData.Data1
    data2 = clientData.Data2
    dataList = [data1, data2]
    FBLogic.OnClientEndFB(curPlayer, mapID, lineID, dataList)
    GameWorld.DebugLog('    客户端副本发送结束mapID=%s,lineID=%s,dataList=%s'%(mapID,lineID,dataList))
    return
#// B1 04 客户端发送开始副本 #tagCMClientStartFB
#
#struct    tagCMClientStartFB
#{
#    tagHead         Head;
#};
def OnClientStartFB(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    FBLogic.OnClientStartFB(curPlayer, tick)
    return
#// A2 31 前端开始自定义场景 #tagCMClientStartCustomScene
#
#struct    tagCMClientStartCustomScene
#{
#    tagHead        Head;
#    DWORD        MapID;
#    WORD        FuncLineID;
#};
def OnClientStartCustomScene(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    mapID = clientData.MapID
    funcLineID = clientData.FuncLineID
    DoEnterCustomScene(curPlayer, mapID, funcLineID, tick)
    return
#// A2 33 前端退出自定义场景 #tagCMClientExitCustomScene
#
#struct    tagCMClientExitCustomScene
#{
#    tagHead        Head;
#};
def OnClientExitCustomScene(index, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
    DoExitCustomScene(curPlayer)
    return
def DoEnterCustomScene(curPlayer, mapID, lineID, tick):
    ## 进入自定义场景状态
    playerID = curPlayer.GetPlayerID()
    GameWorld.Log("玩家请求进入自定义场景!mapID=%s,lineID=%s" % (mapID, lineID), playerID)
    if curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ClientCustomScene):
        curMapID = PlayerControl.GetCustomMapID(curPlayer)
        curLineID = PlayerControl.GetCustomLineID(curPlayer)
        if mapID == curMapID and lineID == curLineID:
            GameWorld.Log("    玩家当前已经在自定义场景中!无需重新请求!", playerID)
            result = 1
        else:
            GameWorld.Log("    玩家当前在不同的自定义场景中!不允许进入!curMapID=%s,curLineID=%s"
                          % (curMapID, curLineID), playerID)
            result = 0
        StartCustomSceneResult(curPlayer, mapID, lineID, result)
        return result
    #进入副本通用检查
    if mapID:
        fbIpyData = FBCommon.GetFBIpyData(mapID)
        fbLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID)
        if PlayerControl.CheckMoveToFB(curPlayer, mapID, lineID, fbIpyData, fbLineIpyData, tick) != ShareDefine.EntFBAskRet_OK:
            StartCustomSceneResult(curPlayer, mapID, lineID, 0)
            return 0
    PlayerControl.SetPlayerSightLevel(curPlayer, curPlayer.GetID())
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 1) # 由于前端不一定有发mapID,所以这里额外记录这个状态,不能直接用mapID判断
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneStepTick, tick)
    PlayerControl.SetCustomMap(curPlayer, mapID, lineID)
    NPCCommon.ClearPriWoodPile(curPlayer)
    GameWorld.Log("玩家开始自定义场景!mapID=%s,lineID=%s" % (mapID, lineID), playerID)
    if mapID:
        PetControl.DoLogic_PetLoadMapOK(curPlayer)
        FBLogic.OnEnterCustomScene(curPlayer, mapID, lineID)
    #默认回满血
    if GameObj.GetHP(curPlayer) < GameObj.GetMaxHP(curPlayer):
        GameObj.SetHPFull(curPlayer)
    #通知进入状态
    StartCustomSceneResult(curPlayer, mapID, lineID, 1)
    return 1
def StartCustomSceneResult(curPlayer, mapID, lineID, result):
    if result != 1:
        DoExitCustomScene(curPlayer)
    resultPack = ChPyNetSendPack.tagMCStartCustomSceneResult()
    resultPack.MapID = mapID
    resultPack.FuncLineID = lineID
    resultPack.Result = result
    NetPackCommon.SendFakePack(curPlayer, resultPack)
    return
def DoExitCustomScene(curPlayer):
    ## 退出自定义场景状态
    PlayerControl.SetPlayerSightLevel(curPlayer, 0)
    mapID = PlayerControl.GetCustomMapID(curPlayer)
    lineID = PlayerControl.GetCustomLineID(curPlayer)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomScene, 0)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneStepTick, 0)
    curPlayer.SetDict(ChConfig.Def_PlayerKey_ClientCustomSceneGrade, 0)
    PlayerControl.SetCustomMap(curPlayer, 0, 0)
    if mapID and FBCommon.GetCustomMapStep(curPlayer, mapID, lineID) != ChConfig.CustomMapStep_Over:
        FBCommon.SetCustomMapStep(curPlayer, mapID, lineID, ChConfig.CustomMapStep_Over)
    NPCCommon.ClearPriWoodPile(curPlayer)
    #默认回满血
    if GameObj.GetHP(curPlayer) > 0 and curPlayer.GetPlayerAction() != IPY_GameWorld.paDie and GameObj.GetHP(curPlayer) < GameObj.GetMaxHP(curPlayer):
        GameObj.SetHPFull(curPlayer)
    GameWorld.Log("玩家退出自定义场景!", curPlayer.GetPlayerID())
    return
#// B1 0A 副本购买buff #tagCMFBBuyBuff
#struct    tagCMFBBuyBuff
#{
#    tagHead         Head;
#    DWORD        MapID;
#    WORD        MoneyCnt;
#};
def OnFBBuyBuff(playerIndex, clientData, tick):
    curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)
    playerID = curPlayer.GetPlayerID()
    mapID = clientData.MapID
    moneyCnt = clientData.MoneyCnt
    ipyData = IpyGameDataPY.GetIpyGameData('FBBuyBuff', mapID, moneyCnt)
    if not ipyData:
        return
    addBuffID = ipyData.GetBuffID()
    curSkill = GameWorld.GetGameData().GetSkillBySkillID(addBuffID)
    if not curSkill:
        return
    crossMapID = PlayerControl.GetCrossMapID(curPlayer)
    if crossMapID and mapID !=crossMapID:
        return
    if not crossMapID and mapID != GameWorld.GetMap().GetMapID():
        return
    curTime = int(time.time())
    #判断CD
    timeKey = (mapID, moneyCnt)
    lastTime = PyGameData.g_fbBuyBuffTimeDict.get(playerID, {}).get(timeKey, 0)
    if lastTime and curTime - lastTime < ipyData.GetBuffCD():
        GameWorld.DebugLog('副本购买buff CD未到 ')
        return
    #扣钱
    infoDict =  {"MapID":mapID, "addBuffID":addBuffID}
    if not PlayerControl.PayMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Money, moneyCnt, ChConfig.Def_Cost_FBBuyBuff, infoDict):
        return
    if playerID not in PyGameData.g_fbBuyBuffTimeDict:
        PyGameData.g_fbBuyBuffTimeDict[playerID] = {}
    PyGameData.g_fbBuyBuffTimeDict[playerID][timeKey] = curTime
    NotifyBuyFBBuffInfo(curPlayer)
    if crossMapID:
        msgDict = {"PlayerID":curPlayer.GetPlayerID(), "buffID":addBuffID}
        GameWorld.SendMsgToCrossServer(ShareDefine.ClientServerMsg_AddBuff, msgDict)
        GameWorld.DebugLog("跨服中请求复活, crossMapID=%s,msgDict=%s" % (crossMapID, msgDict), playerID)
        return
    SkillShell.__DoLogic_AddBuff(curPlayer, curPlayer, curSkill, False, tick, 0, 0)
    #SkillCommon.AddBuffBySkillType(curPlayer, addBuffID, tick)
    return
def NotifyBuyFBBuffInfo(curPlayer):
    playerID = curPlayer.GetPlayerID()
    buffTimeDict = PyGameData.g_fbBuyBuffTimeDict.get(playerID, {})
    if not buffTimeDict:
        return
    packData = ChPyNetSendPack.tagMCFBBuyBuffInfo()
    packData.InfoList = []
    for timeKey, buyTime in buffTimeDict.items():
        mapID, moneyCnt = timeKey
        timeInfo = ChPyNetSendPack.tagMCFBBuyBuffTime()
        timeInfo.MapID = mapID
        timeInfo.MoneyCnt = moneyCnt
        timeInfo.BuyTime = buyTime
        packData.InfoList.append(timeInfo)
    packData.Cnt = len(packData.InfoList)
    NetPackCommon.SendFakePack(curPlayer, packData)
    FBLogic.OnPlayerFBSweepResult(curPlayer, mapID, lineID, cnt, dataEx)
    return
#// B1 08 快速一键过关副本 #tagCMFBQuickPass