ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossDemonKing.py
@@ -4,89 +4,130 @@
#
##@package GameWorldLogic.FBProcess.GameLogic_CrossDemonKing
#
# @todo:跨服妖王
# @todo:本服、跨服妖王
# @author hxp
# @date 2019-04-11
# @date 2019-04-13
# @version 1.0
#
# 详细描述: 跨服妖王
# 详细描述: 本服、跨服妖王
#
#-------------------------------------------------------------------------------
#"""Version = 2019-04-11 14:30"""
#"""Version = 2019-04-13 11:00"""
#-------------------------------------------------------------------------------
import FBCommon
import GameWorld
import ItemCommon
import IPY_GameWorld
import IpyGameDataPY
import ChConfig
import PyGameData
import NPCCommon
import ItemCommon
import PlayerFairyDomain
import CrossRealmPlayer
import GameWorldProcess
import PlayerControl
import ShareDefine
import PlayerSuccess
import PlayerActLogin
import PyGameData
import ChConfig
import ChItem
FBDict_StartTick = 'FBDict_StartTick%s' #开始时间
FBDict_Speed = 'FBDict_Speed%s' #掉血速度 /s
FBDict_RemainHP = 'FBDict_RemainHP%s' #剩余时间
FBDict_IsOver = 'FBDict_IsOver' #是否已结算, 结算时的tick
FBDict_IsReduceing = 'FBDict_IsReduceing%s' #是否掉血中
FBDict_BossTotalHP = 'FBDict_BossTotalHP%s' #BOSS血量,需要的总时间
FBDict_LastHurtTick = 'FBDict_LastHurtTick'  #上次伤害时间
g_heroHurtDict = {} #{playerID:hurt}
g_ownerInfo = {} # 归属者信息 {funcLineID:[ownerID, ownerName], }
## 是否需要做进入副本通用检查条件逻辑,默认需要检查
def OnNeedCheckCanEnterFBComm(curPlayer, mapID, lineID):
    curState = PlayerFairyDomain.GetFairyDomainFBEventState(curPlayer, mapID, lineID)
    return curState != PlayerFairyDomain.FDEventState_Visiting
## 是否能够通过活动查询进入
def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
    return True
    curState = PlayerFairyDomain.GetFairyDomainFBEventState(curPlayer, mapID, lineID)
    return curState in [PlayerFairyDomain.FDEventState_CanVisit, PlayerFairyDomain.FDEventState_Visiting]
## 查询是否可以进入地图
def OnChangeMapAsk(ask, tick):
    return IPY_GameWorld.cmeAccept
## 进入跨服副本注册数据前逻辑
## @return: 是否可以注册前往跨服副本,次函数中可以写一些扣除消耗逻辑等
def OnRegEnterCrossFB(curPlayer, mapID, lineID):
    curState = PlayerFairyDomain.GetFairyDomainFBEventState(curPlayer, mapID, lineID)
    if curState == PlayerFairyDomain.FDEventState_CanVisit:
        return PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visiting)
    if curState == PlayerFairyDomain.FDEventState_Visiting:
        return True
    return False
## 开启副本
def OnOpenFB(tick):
    lineID = GetCurFBFuncLineID()
    killTime = 60
    GameWorld.GetGameWorld().SetGameWorldDict(FBDict_BossTotalHP % lineID, killTime * 1000)
    return
def GetCurFBLineBOSSID(mapID=-1, lineID=-1):
    #该分线刷的BOSSID
    if mapID == -1:
        mapID = ChConfig.Def_FBMapID_CrossDemonKing if GameWorld.IsCrossServer() else ChConfig.Def_FBMapID_DemonKing
    if lineID == -1:
        lineID = GetCurFBFuncLineID()
    if mapID == -1 or lineID == -1:
        return 0
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition("FairyDomain", {"MapID":mapID, "LineID":lineID})
    if not ipyData:
        return 0
    bossID = ipyData.GetBossID()
    return bossID
def GetCurFBFuncLineID():
    ## 获取本线路功能线路ID
    if GameWorld.IsCrossServer():
        return FBCommon.GetCrossDynamicLineMapFuncLineID()
    return GameWorld.GetGameWorld().GetPropertyID() - 1
def GetCurFBLineZoneID():
    ## 获取本线路所属跨服分区
    if GameWorld.IsCrossServer():
        return FBCommon.GetCrossDynamicLineMapZoneID()
    return 0
## 进副本
def DoEnterFB(curPlayer, tick):
    playerID = curPlayer.GetPlayerID()
    zoneID = GetCurFBLineZoneID()
    funcLineID = GetCurFBFuncLineID()
    GameWorld.DebugLog("DoEnterFB zoneID=%s,funcLineID=%s" % (zoneID, funcLineID), playerID)
    bossID = GetCurFBLineBOSSID(lineID=funcLineID)
    GameWorld.Log("DoEnterFB zoneID=%s,funcLineID=%s,bossID=%s" % (zoneID, funcLineID, bossID), playerID)
    PyGameData.g_fbPickUpItemDict.pop(playerID, 0)
    return
## 副本总逻辑计时器
def OnProcess(tick):
    gameFB = GameWorld.GetGameFB()
    overTick = gameFB.GetGameFBDictByKey(FBDict_IsOver)
    if overTick and tick - overTick >= ChConfig.Def_FBPickupItemTime:
        GameWorld.Log("强制踢出玩家关闭副本: overTick=%s,tick=%s" % (overTick, tick))
        FBCommon.DoLogic_FBKickAllPlayer()
        return
    return
## 关闭副本
def OnCloseFB(tick):
#    gameWorld = GameWorld.GetGameWorld()
#    lineID = gameWorld.GetPropertyID() - 1
#    gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, 0)
#    gameWorld.SetGameWorldDict(FBDict_Speed % lineID, 0)
#    gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, 0)
#
#    gameWorld.SetPropertyID(0)
    funcLineID = GetCurFBFuncLineID()
    g_ownerInfo.pop(funcLineID, None)
    GameWorld.GetGameWorld().SetPropertyID(0)
    return
## 玩家退出副本
def DoExitFB(curPlayer, tick):
    UpdateHPReduceSpeed(tick, True)
    gameFB = GameWorld.GetGameFB()
    overTick = gameFB.GetGameFBDictByKey(FBDict_IsOver)
    gameWorld = GameWorld.GetGameWorld()
    #最后一人退出副本则关闭地图
    if overTick and gameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:
        GameWorldProcess.CloseFB(tick)
    return
##玩家主动离开副本.
def DoPlayerLeaveFB(curPlayer, tick):
#    FBCommon.SetHadDelTicket(curPlayer, 0)
#    #主动退出的去掉排行榜信息
#    lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
#    playerHurtDict = PyGameData.g_ZhuXianBossPlayerHurtDict.get(lineID, {})
#    playerHurtDict.pop(curPlayer.GetPlayerID(), 0)
#    PyGameData.g_ZhuXianBossPlayerHurtDict[lineID] = playerHurtDict
#    if not playerHurtDict: #榜上没人,停止掉血
#        StopReduceHP(lineID, tick)
    gameWorld = GameWorld.GetGameWorld()
    #最后一人退出副本则关闭地图
    if gameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:
        GameWorldProcess.CloseFB(tick)
    return
## 是否副本复活
@@ -95,148 +136,73 @@
## 获得副本帮助信息
def DoFBHelp(curPlayer, tick):
    if GameWorld.GetGameFB().GetGameFBDictByKey(FBDict_IsOver):
    return
def DoFB_Npc_KillNPC(attacker, curNPC, tick):
    __FBNPCOnKilled(curNPC, tick)
    return
def DoFB_Player_KillNPC(curPlayer, curNPC, tick):
    __FBNPCOnKilled(curNPC, tick)
    return
## 执行副本杀怪逻辑
def __FBNPCOnKilled(curNPC, tick):
    bossID = curNPC.GetNPCID()
    funcLineID = GetCurFBFuncLineID()
    if bossID != GetCurFBLineBOSSID(lineID=funcLineID):
        return
    
    lineID = GetCurFBFuncLineID()
    curSpeed = GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_Speed % lineID)
    isReduceing = GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_IsReduceing % lineID)
    remainHP = GetBossRemainHP(lineID, tick)
    totalHP = __GetBossTotalHP(lineID)
    hpReduceSpeed = curSpeed * 10000 / totalHP if totalHP else 0
    remainHPPer = min(1000000, remainHP * 1000000 / totalHP) if totalHP else 0
    fbHelpDict = {FBCommon.Help_lineID:lineID, 'hpReduceSpeed':hpReduceSpeed, 'remainHPPer':remainHPPer, 'isReduceing':isReduceing}
    GameWorld.DebugLog("DoFBHelp: %s" % fbHelpDict, curPlayer.GetPlayerID())
    FBCommon.Notify_FBHelp(curPlayer, fbHelpDict)
    return
## 玩家对NPC造成伤害
def DoFB_Player_HurtNPC(curPlayer, curNPC, hurtHP):
    return
    lineID = GetCurFBFuncLineID()
    #有人上榜开始掉血
    StartReduceHP(lineID, GameWorld.GetGameWorld().GetTick())
    GameWorld.GetGameFB().SetGameFBDict(FBDict_LastHurtTick, GameWorld.GetGameWorld().GetTick())
    return
##---副本总逻辑计时器---
# @param tick:时间戳
# @return 无意义
# @remarks 副本总逻辑计时器
def OnProcess(tick):
    return
    zoneID = GetCurFBLineZoneID()
    gameFB = GameWorld.GetGameFB()
    overTick = gameFB.GetGameFBDictByKey(FBDict_IsOver)
    # 结算20秒后强制关闭副本, 防止玩家不捡东西导致不结算,强关后地板上的东西会邮件发放给玩家
    if overTick and tick - overTick >= ChConfig.Def_FBPickupItemTime:
        GameWorld.Log("强制踢出玩家关闭副本: overTick=%s,tick=%s" % (overTick, tick))
        FBCommon.DoLogic_FBKickAllPlayer()
    gameFB.SetGameFBDict(FBDict_IsOver, tick)
    ownerType = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerType)
    ownerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastDropOwnerID) if ownerType == ChConfig.Def_NPCHurtTypePlayer else 0
    isCrossServer = GameWorld.IsCrossServer()
    mapID = ChConfig.Def_FBMapID_CrossDemonKing if isCrossServer else ChConfig.Def_FBMapID_DemonKing
    GameWorld.Log("击杀妖王: zoneID=%s,mapID=%s,funcLineID=%s,ownerID=%s,bossID=%s" % (zoneID, mapID, funcLineID, ownerID, bossID))
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition("FairyDomain", {"MapID":mapID, "LineID":funcLineID})
    if not ipyData:
        return
    lineID = GetCurFBFuncLineID()
    if lineID < 0:
        return
    gameWorld = GameWorld.GetGameWorld()
    startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)
    if not startTick or overTick:
        return
    lastHurtTick = gameFB.GetGameFBDictByKey(FBDict_LastHurtTick)
    if lastHurtTick and tick - lastHurtTick >= 2000:
        StopReduceHP(lineID, tick)
        GameWorld.GetGameFB().SetGameFBDict(FBDict_LastHurtTick, 0)
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 5000)
    __CheckBossHP(tick)
    return
def __DoLogicZhuXianBossOver(isPass, tick, dropPosX, dropPosY):
    #结算
#    gameFB = GameWorld.GetGameFB()
#    mapID = GameWorld.GetMap().GetMapID()
#    lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
#    leaveTick = FBCommon.GetFBLineStepTime(mapID, lineID) * 1000
#    playerHurtList = __GetSortHurtList(lineID)
#    if not playerHurtList:
#        GameWorld.Log(' __DoLogicZhuXianBossOver, 伤害榜上没有人!!lineID=%s' % lineID)
#        return
#    firsthurtInfo = playerHurtList[0]
#    firstPlayerID = firsthurtInfo[0]
#    firstPlayerFamilyID = firsthurtInfo[1][2]
#    playerManager = GameWorld.GetMapCopyPlayerManager()#GameWorld.GetPlayerManager()
#    firstPlayer = playerManager.FindPlayerByID(firstPlayerID)
#    if firstPlayer:
#        gameFB.SetPlayerGameFBDict(firstPlayerID, FBPlayerDict_Rank, 1)
#        if not dropPosX or not dropPosY:
#            dropPosX, dropPosY = firstPlayer.GetPosX(), firstPlayer.GetPosY()
#        prizeItemList = GiveZhuXianBossAward(firstPlayer, lineID, dropItemMapInfo=[dropPosX, dropPosY, True, True])
#        if not prizeItemList:
#            # 没有掉落时直接通知结算,防止卡副本
#            firstPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)
#            overDict = {FBCommon.Over_rank:1, FBCommon.Over_itemInfo:prizeItemList}
#            FBCommon.NotifyFBOver(firstPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, lineID, isPass, overDict)
#        else:
#            firstPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)
#    else:
#        leaveServerTick = PlayerControl.GetPlayerLeaveServerTick(firstPlayerID)
#        if leaveServerTick and tick - leaveServerTick < ChConfig.Def_PlayerOfflineProtectTime:
#            #离线超过3分钟的不给奖励
#            msgStr = str([ShareDefine.Def_UniversalGameRecType_ZhuXianBossRecord, [firstPlayerID, lineID], [], 0, 0])
#            GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'AddUniversalGameRec', msgStr, len(msgStr))
#
#    helpItemList = FBCommon.GetFBLineReward(mapID, lineID)
#    if helpItemList: #同盟协助奖励
#        jsonItemList = FBCommon.GetJsonItemList(helpItemList)
#        for index in range(0 , playerManager.GetPlayerCount()):
#            curPlayer = playerManager.GetPlayerByIndex(index)
#            curPlayerID = curPlayer.GetPlayerID()
#            if not curPlayerID:
#                continue
#            if curPlayerID == firstPlayerID:
#                continue
#            curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)
#            remainCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_ZhuXianBossHelpCnt)
#            if curPlayer.GetFamilyID() == firstPlayerFamilyID and remainCnt:
#                PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_ZhuXianBossHelpCnt, remainCnt - 1)
#                ItemControler.GivePlayerItemOrMail(curPlayer, helpItemList, 'ZXBossHelperReward')
#                overDict = {FBCommon.Over_rank:0, FBCommon.Over_itemInfo:jsonItemList}
#                FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, lineID, isPass, overDict)
#            else:
#                overDict = {FBCommon.Over_rank:0}
#                FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, lineID, 0, overDict)
    return
def GiveZhuXianBossAward(curPlayer, lineID, isMail=False, dropItemMapInfo=[]):
    ##给归属者奖励
    addCnt = 1
    equipList = []
    prizeItemDict = {}
    bossID = GetCurFBLineBOSSID(lineID)
    jsonItemList, totalExp, totalMoney = NPCCommon.GiveKillNPCDropPrize(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, {bossID:addCnt},
                                                                        mailTypeKey="ZXBossBelongerReward", isMail=isMail,
                                                                        dropItemMapInfo=dropItemMapInfo)
    for jsonItem in jsonItemList:
        if 'UserData' in jsonItem:
            equipList.append(jsonItem)
    eventID = ipyData.GetID()
    ownerName = ""
    dropPosX, dropPosY = curNPC.GetPosX(), curNPC.GetPosY()
    serverGroupIDList = []
    msgInfo = {}
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        if not curPlayer:
            continue
        playerID = curPlayer.GetPlayerID()
        isOwner = playerID == ownerID
        if isOwner:
            ownerName = curPlayer.GetPlayerName()
        giveItemList = __GetDemonKingPrizeItemList(curPlayer, mapID, funcLineID, eventID, isOwner)
        GameWorld.Log("玩家奖励: %s" % giveItemList, playerID)
        ChItem.DoMapDropItem(curPlayer, giveItemList, bossID, dropPosX, dropPosY, isOnlySelfSee=True, isDropDisperse=True)
        #curPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)
        if not isCrossServer:
            PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, funcLineID, PlayerFairyDomain.FDEventState_Visited)
        else:
            itemID, itemCnt = jsonItem['ItemID'], jsonItem.get('Count', 1)
            prizeItemDict[itemID] = prizeItemDict.get(itemID, 0) + itemCnt
            serverGroupID = PlayerControl.GetPlayerServerGroupID(curPlayer)
            if serverGroupID not in serverGroupIDList:
                serverGroupIDList.append(serverGroupID)
            msgInfo[playerID] = [serverGroupID, mapID, funcLineID]
    g_ownerInfo[funcLineID] = [ownerID, ownerName]
    
    GameWorld.DebugLog("诛仙boss结算奖励: lineID=%s,bossID=%s,totalExp=%s,totalMoney=%s,jsonItemList=%s"
                       % (lineID, bossID, totalExp, totalMoney, jsonItemList), curPlayer.GetPlayerID())
    prizeItemList = equipList + FBCommon.GetJsonItemList(prizeItemDict.items())
    #PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_ZhuXianBoss, addCnt)
    if msgInfo:
        GameWorld.SendMsgToClientServer(ShareDefine.CrossServerMsg_FBEnd, msgInfo, serverGroupIDList)
    return
    #击杀特定NPC成就
    PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, addCnt, [bossID])
    FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, addCnt)
    # 每日活动
    #PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_ZhuXianBoss, addCnt)
    PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_ZhuXianBOSS, addCnt)
    return prizeItemList
## 结束跨服副本
def OnEndCrossFB(curPlayer, mapID, lineID, exData):
    PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visited)
    return
def OnPickUpItem(curPlayer, curItem, tick):
    mapItemType = curItem.GetType()
@@ -246,12 +212,12 @@
    isEquip = ItemCommon.CheckItemIsEquip(curItem)
    jsonItem = ItemCommon.GetJsonItem(curItem)
    if playerID in PyGameData.g_fbPickUpItemDict:
        if isEquip:
        if isEquip or jsonItem.get("IsAuctionItem"):
            PyGameData.g_fbPickUpItemDict[playerID].append(jsonItem)
        else:
            isIn = False
            for itemInfo in PyGameData.g_fbPickUpItemDict[playerID]:
                if itemInfo["ItemID"] == jsonItem["ItemID"] and itemInfo.get("IsBind") == jsonItem.get("IsBind"):
                if itemInfo["ItemID"] == jsonItem["ItemID"] and itemInfo.get("IsAuctionItem") == jsonItem.get("IsAuctionItem"):
                    itemInfo["Count"] = itemInfo.get("Count", 1) + jsonItem.get("Count", 1)
                    isIn = True
                    break
@@ -276,142 +242,66 @@
        return
    
    isPass = 1
    lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
    leaveTick = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_ZhuXianBoss, lineID) * 1000
    gameFB = GameWorld.GetGameFB()
    rank = 1###gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_Rank)
    jsonItemList = PyGameData.g_fbPickUpItemDict.get(playerID, [])
    mapID = ChConfig.Def_FBMapID_CrossDemonKing if GameWorld.IsCrossServer() else ChConfig.Def_FBMapID_DemonKing
    funcLineID = GetCurFBFuncLineID()
    leaveTick = FBCommon.GetFBLineStepTime(mapID, funcLineID) * 1000
    ownerID, ownerName = g_ownerInfo.pop(funcLineID, [0, ""])
    jsonItemList = PyGameData.g_fbPickUpItemDict.pop(playerID, [])
    overDict = {FBCommon.Over_ownerID:ownerID, FBCommon.Over_ownerName:ownerName, FBCommon.Over_itemInfo:jsonItemList}
    FBCommon.NotifyFBOver(curPlayer, mapID, funcLineID, isPass, overDict)
    curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)
    overDict = {FBCommon.Over_rank:rank, FBCommon.Over_itemInfo:jsonItemList}
    FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_ZhuXianBoss, lineID, isPass, overDict)
    return
def __CheckBossHP(tick):
    gameFB = GameWorld.GetGameFB()
    isOver = gameFB.GetGameFBDictByKey(FBDict_IsOver)
    lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
    if not isOver and GetBossRemainHP(lineID, tick) == 0:
        bossID = GetCurFBLineBOSSID(lineID)
        curBoss = GameWorld.FindNPCByNPCID(bossID)
        dropPosX, dropPosY = 0, 0
        if curBoss:
            dropPosX, dropPosY = curBoss.GetPosX(), curBoss.GetPosY()
        #结束 设置BOSS死亡
        FBCommon.ClearFBNPC()
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
        GameWorld.DebugLog('结束 设置BOSS死亡 lineID=%s' % lineID)
        ###playerHurtList = __GetSortHurtList(lineID)
        playerHurtList = []
        if playerHurtList:
            killerName, hurtValue = playerHurtList[0][1][:2]
            NPCCommon.GameServer_KillGameWorldBoss(bossID, killerName, hurtValue)
        NPCCommon.GameServe_GameWorldBossState(bossID, 0)
        ###__DoLogicZhuXianBossOver(1, tick, dropPosX, dropPosY)
        gameFB.SetGameFBDict(FBDict_IsOver, tick)
## 客户端进入自定义场景
def OnEnterCustomScene(curPlayer, mapID, lineID):
    PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visiting)
    return
def UpdateHPReduceSpeed(tick, isExit=False):
    gameWorld = GameWorld.GetGameWorld()
    playerCnt = gameWorld.GetMapCopyPlayerManager().GetPlayerCount()
    playerCnt = playerCnt - 1 if isExit else playerCnt
    if playerCnt <= 0:
        return
    lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
    if lineID < 0:
        return
    curSpeed = int(min(1 + 0.08 * (playerCnt - 1), 1.8) * 1000)
    gameWorld.SetGameWorldDict(FBDict_Speed % lineID, curSpeed)
    if not gameWorld.GetGameWorldDictByKey(FBDict_IsReduceing % lineID):
        return
    startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)
    remainHP = gameWorld.GetGameWorldDictByKey(FBDict_RemainHP % lineID)
    lastSpeed = gameWorld.GetGameWorldDictByKey(FBDict_Speed % lineID)
    if not startTick:
        startTick = tick
        lastSpeed = curSpeed
        remainHP = __GetBossTotalHP(lineID)
    remainHP = max(0, int((remainHP - (tick - startTick) / 1000.0 * lastSpeed)))
    gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, tick)
    gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, remainHP)
    GameWorld.DebugLog('    curSpeed=%s, remainHP=%s, passTime=%s, lastSpeed=%s' % (curSpeed, remainHP, tick - startTick, lastSpeed))
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
    return
def StopReduceHP(lineID, tick):
    ##暂停BOSS血量减少
    gameWorld = GameWorld.GetGameWorld()
    if not gameWorld.GetGameWorldDictByKey(FBDict_IsReduceing % lineID):
        return
    remainHP = GetBossRemainHP(lineID, tick)
    if not remainHP:
        return
    gameWorld.SetGameWorldDict(FBDict_IsReduceing % lineID, 0)
    gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, remainHP)
    return
def StartReduceHP(lineID, tick):
    ##开始BOSS掉血
    gameWorld = GameWorld.GetGameWorld()
    if gameWorld.GetGameWorldDictByKey(FBDict_IsReduceing % lineID):
        return
    gameWorld.SetGameWorldDict(FBDict_IsReduceing % lineID, 1)
    startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)
    if not startTick:
        gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, __GetBossTotalHP(lineID))
    gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, tick)
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
    return
def __GetBossTotalHP(lineID):return GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_BossTotalHP % lineID)
def GetBossRemainHP(lineID, tick):
    gameWorld = GameWorld.GetGameWorld()
    startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)
    lastSpeed = gameWorld.GetGameWorldDictByKey(FBDict_Speed % lineID)
    remainHP = gameWorld.GetGameWorldDictByKey(FBDict_RemainHP % lineID)
    if not gameWorld.GetGameWorldDictByKey(FBDict_IsReduceing % lineID):
        return remainHP
    if not startTick:
        startTick = tick
        remainHP = __GetBossTotalHP(lineID)
    else:
        remainHP = max(0, int((remainHP - (tick - startTick) / 1000.0 * lastSpeed)))
    return remainHP
def GetCurFBLineBOSSID(lineID= -1):
    #该分线刷的BOSSID
    if lineID == -1:
        lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
    if lineID == -1:
        return 0
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition("FairyDomain", {"MapID":ChConfig.Def_FBMapID_CrossDemonKing, "LineID":lineID})
## 客户端发送刷新自定义副本奖励
def OnRefreshCustomFBPrize(curPlayer, mapID, lineID):
    visitCount = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FairyDomainVisitCnt)
    fakeImmortalCount = IpyGameDataPY.GetFuncCfg("FakeImmortalCount", 1)
    if visitCount > fakeImmortalCount:
        GameWorld.DebugLog("当前寻访次数不能获取自定义副本奖励!visitCount=%s" % visitCount)
        return []
    if not PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visiting):
        GameWorld.DebugLog("寻访状态异常不能获取自定义副本奖励!")
        return []
    ipyData = IpyGameDataPY.GetIpyGameDataByCondition("FairyDomain", {"MapID":mapID, "LineID":lineID})
    if not ipyData:
        return 0
    bossID = ipyData.GetBossID()
    return bossID
        return []
    eventID = ipyData.GetID()
    isOwner = True
    giveItemList = __GetDemonKingPrizeItemList(curPlayer, mapID, lineID, eventID, isOwner)
    return giveItemList
def GetCurFBFuncLineID(): return GameWorld.GetGameWorld().GetPropertyID() % 1000
def GetCurFBLineZoneID(): return GameWorld.GetGameWorld().GetPropertyID() / 1000
## 给自定义副本奖励后续处理
## @return: 返回结算副本over信息字典,不含jsonItem信息
def OnGiveCustomFBPrizeOK(curPlayer, mapID, lineID):
    PlayerFairyDomain.SetFairyDomainFBEventState(curPlayer, mapID, lineID, PlayerFairyDomain.FDEventState_Visited)
    ownerID, ownerName = curPlayer.GetPlayerID(), curPlayer.GetPlayerName()
    overDict = {FBCommon.Over_ownerID:ownerID, FBCommon.Over_ownerName:ownerName}
    return overDict
##玩家死亡.
# @param curPlayer:死亡的玩家
# @param tick 时间戳
# @return 返回值无意义
# @remarks 玩家主动离开副本.
def DoPlayerDead(curPlayer):
    return
def __GetDemonKingPrizeItemList(curPlayer, mapID, lineID, eventID, isOwner):
    giveItemList = PlayerFairyDomain.GetFairyAppointAward(curPlayer, eventID)
    if giveItemList:
        return giveItemList
    # 没有定制奖励则取常规奖励
    # {物品ID:[归属者获得个数饼图[[概率, 个数], ...], 非归属者获得个数饼图[[概率, 个数], ...], 是否拍品], ...}
    giveItemList = []
    awardDict = FBCommon.GetFBLineReward(mapID, lineID)
    for itemID, itemInfo in awardDict.items():
        ownerCountRateList, notOwnerCountRateList, isAuctionItem = itemInfo
        if isOwner:
            itemCount = GameWorld.GetResultByRandomList(ownerCountRateList)
        else:
            itemCount = GameWorld.GetResultByRandomList(notOwnerCountRateList)
        if not itemCount:
            continue
        giveItemList.append([itemID, itemCount, isAuctionItem])
    return giveItemList
##处理副本中杀死玩家逻辑
def DoFBOnKill_Player(atkobj, defender, tick):
    return True