hxp
2022-02-21 0c27822ef5e6c67782ed143a4ff03ecfbdfda1fb
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossBattlefield.py
@@ -4,12 +4,12 @@
#
##@package GameWorldLogic.FBProcess.GameLogic_CrossBattlefield
#
# @todo:跨服战场
# @todo:跨服战场/古神战场
# @author hxp
# @date 2022-01-06
# @version 1.0
#
# 详细描述: 跨服战场
# 详细描述: 跨服战场/古神战场
#
#-------------------------------------------------------------------------------
#"""Version = 2022-01-06 20:30"""
@@ -23,16 +23,23 @@
import IpyGameDataPY
import PlayerActivity
import GameWorldProcess
import NPCCustomRefresh
import PlayerControl
import ShareDefine
import SkillCommon
import SkillShell
import BuffSkill
import ChConfig
import AICommon
import GameObj
import GameMap
import ChNPC
import operator
import random
import time
import copy
import math
#当前副本地图的状态
(
@@ -49,218 +56,400 @@
Time_Leave, # 副本离开时间 2
) = range(3)
# 大奖任务类型
SuperTaskList = (
SuperTaskType_Kill, # 击杀 1
SuperTaskType_Score, # 积分 2
) = range(1, 1 + 2)
FightRefreshInterval = 5000 # 战斗阶段刷新处理间隔,毫秒
GameFBData_BattleWorld = "BattleWorld"
GameFBData_FactionInfo = "FactionInfo"
GameFBData_PlayerInfo = "PlayerInfo"
# 事件编号
AllEventNumList = (
EventNum_Aura, # 事件 - 积分光环
EventNum_Boss, # 事件 - Boss
EventNum_Wall, # 事件 - 积分墙
) = range(1, 1 + 3)
# 得分类型
(
ScoreType_Default, # 默认
ScoreType_KillPlayer, # 击杀玩家     1
ScoreType_CollectCrystal, # 占领资源建筑     2
ScoreType_CollectFactionBuff, # 采集阵营buff    3
ScoreType_GuardKillPlayer, # 守卫击杀玩家     4
ScoreType_HurtBoss, # 对boss造成伤害     5
ScoreType_Aura, # 积分光环     6
) = range(7)
## 战场公共世界管理类
class BattleWorld():
    
    def __init__(self):
        self.callOpenPlayerInfo = {} # 本场次购买召集的玩家信息 {playerID:faction, ...}
        self.superItemInfo = [] # 大奖信息 [物品ID,个数,是否拍品]
        self.superItemPlayerID = 0 # 大奖中奖者玩家ID
        self.superItemPlayerName = "" # 大奖中奖者玩家名
        self.superTaskType = 0 # 大奖任务类型
        self.crystalFactionInfo = {} # 水晶资源所属阵营信息 {npcID:所属阵营, ...}
        self.crystalAwardTick = {} # 水晶资源定时奖励tick {npcID:tick, ...}
        self.personBuffCount = 0 # 战场存在的个人buff个数
        self.personBuffCalcTick = 0 # 开始计算个人buff补充个数tick
        self.factionBuffNPCInfo = [] # 战场存在的阵营buffNPC信息,默认只能存在一个 [npcID, posX, posY]
        self.factionBuffCalcTick = 0 # 开始计算阵营buff补充个数tick
        self.factionBuffIDOrderList = [] # 阵营buff顺序刷新列表
        self.eventInfoList = [] # 本场次要刷新的事件列表 [[刷新时间秒, 事件编号], ...]
        self.eventNum = 0 # 当前进行中的事件编号
        self.eventNPCID = 0 # 当前进行中的事件NPCID
        self.eventNPCPos = [] # 当前进行中的事件NPC坐标
        self.eventStartTick = 0 # 事件开始tick
        self.eventEndTick = 0 # 事件结束时tick,某些事件有,不一定有值
        self.eventNPCHP = 0 # 事件NPC当前剩余血量
        self.lastEventEndTick = 0 # 上个事件结束tick
        self.lastWallCollOKTick = 0 # 上次积分墙采集OK时tick
        self.RandSuperTask()
        self.__randEventList()
        return
    def getWorldHelpInfo(self, tick):
        worldInfo = {"superItemInfo":self.superItemInfo, "crystalFactionInfo":self.crystalFactionInfo,
                     "factionBuffNPCInfo":self.factionBuffNPCInfo, "eventNPCID":self.eventNPCID, "eventNPCPos":self.eventNPCPos}
        if self.eventEndTick:
            worldInfo["eventEndTick"] = max(0, self.eventEndTick - tick) # 事件结束剩余时间,单位毫秒
        if self.eventNPCHP:
            worldInfo["eventNPCHP"] = self.eventNPCHP
        return {"worldInfo":worldInfo}
    
    def RandSuperTask(self):
        # 随机生成大奖任务
        fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
        superItemWeightList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper", 1)
        superItemInfo = GameWorld.GetResultByWeightList(superItemWeightList)
        self.superItemInfo = superItemInfo if superItemInfo else []
        self.superTaskType = random.choice(SuperTaskList)
        GameWorld.Log("随机战场大奖: superTaskType=%s,superItemInfo=%s" % (self.superTaskType, self.superItemInfo), fbPropertyID)
        self.superItemInfo = GameWorld.GetResultByWeightList(superItemWeightList, [])
        GameWorld.Log("随机战场大奖: superItemInfo=%s" % str(self.superItemInfo), fbPropertyID)
        return
    
## 战斗实体基类
class BattleBase(object):
    BattleType_Player = "Player"
    BattleType_Faction = "Faction"
    def __init__(self, ID):
        self.fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
        self.battleType = ""
        self.ID = ID
        self.name = ""
        self.score = 0 # 积分
        self.scoreSortTime = 0 # 积分变更排序time值,用于同积分时,先到排名靠前
        self.superTaskValue = 0 # 大奖任务当前进度
        self.superTaskValueMax = 0 # 大奖任务完成需要的进度值
        self.superTaskFinishCount = 0 # 大奖任务完成次数
        self.killCount = 0 # 击杀数
        self.continueKillCount = 0 # 连杀数
        self.beKilledCount = 0 # 被击杀数
        return
    def addScore(self, worldObj, addValue):
        self.score += addValue
        calcTime = 3471264000 #GameWorld.ChangeTimeStrToNum("2080-01-01 00:00:00")
        self.scoreSortTime = max(0, calcTime - int(time.time()))
        GameWorld.DebugLog("    增加积分: battleType=%s,ID=%s,addValue=%s,updScore=%s" % (self.battleType, self.ID, addValue, self.score), self.fbPropertyID)
        self.addSuperTaskValue(worldObj, SuperTaskType_Score, addValue)
        return
    def addKillCount(self, worldObj, addCount):
        self.killCount += addCount
        self.continueKillCount += addCount # 同步增加连杀
        self.addSuperTaskValue(worldObj, SuperTaskType_Kill, addCount)
        return
    def addBeKilledCount(self, addCount):
        self.beKilledCount += addCount
        self.continueKillCount = 0 # 被击杀时,连杀重置
        return
    def setSuperTaskValueMax(self, worldObj):
        if worldObj == None:
            worldObj = GetBattleWorld()
        taskType = worldObj.superTaskType
        if taskType == SuperTaskType_Kill:
            superTaskValueMaxList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper2", 1)
        elif taskType == SuperTaskType_Score:
            superTaskValueMaxList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper2", 2)
        else:
    def __randEventList(self):
        # 随机本场次事件顺序列表
        if self.eventInfoList:
            return
        
        if self.battleType == self.BattleType_Player:
            curValueMaxList = superTaskValueMaxList[0]
        elif self.battleType == self.BattleType_Faction:
            curValueMaxList = superTaskValueMaxList[1]
        else:
            return
        commEventTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldEvent", 2)
        commEventNumList = [] # 常规事件 - 不包含boss的所有事件
        commEventNumList += AllEventNumList
        commEventNumList.remove(EventNum_Boss)
        
        if not curValueMaxList:
        if len(commEventTimeList) != len(commEventNumList):
            GameWorld.ErrLog("战场常规事件刷新时间个数配置错误! commEventTimeList=%s,commEventNumList=%s"
                             % (commEventTimeList, commEventNumList))
            return
        random.shuffle(commEventNumList)
        
        if self.superTaskFinishCount >= len(curValueMaxList):
            valueMax = curValueMaxList[-1]
        else:
            valueMax = curValueMaxList[self.superTaskFinishCount]
        self.superTaskValueMax = valueMax
        GameWorld.Log("    更新大奖任务进度完成所需值! battleType=%s,ID=%s,taskType=%s,superTaskFinishCount=%s,superTaskValueMax=%s"
                      % (self.battleType, self.ID, taskType, self.superTaskFinishCount, self.superTaskValueMax), self.fbPropertyID)
        return
    def addSuperTaskValue(self, worldObj, taskType, addValue):
        if taskType != worldObj.superTaskType:
            #GameWorld.DebugLog("    非战场大奖任务类型,不处理! taskType=%s != superTaskType(%s)" % (taskType, worldObj.superTaskType), self.fbPropertyID)
            return
        if len(worldObj.superItemInfo) != 3:
            GameWorld.ErrLog("大奖任务物品异常,不处理! taskType=%s,superItemInfo=%s" % (taskType, worldObj.superItemInfo), self.fbPropertyID)
            return
        if worldObj.superItemPlayerID:
            GameWorld.DebugLog("    大奖已经产出,不再处理! superItemPlayerID=%s" % worldObj.superItemPlayerID, self.fbPropertyID)
            return
        for i, eventNum in enumerate(commEventNumList):
            self.eventInfoList.append([commEventTimeList[i], eventNum])
            
        if not self.superTaskValueMax:
            self.setSuperTaskValueMax(worldObj)
        if not self.superTaskValueMax:
            return
        eventBossStartTime = IpyGameDataPY.GetFuncCfg("CrossBattlefieldEvent", 3)
        isOnlyCallHaveBoss = IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 5)
        
        self.superTaskValue += addValue
        if self.superTaskValue < self.superTaskValueMax:
            GameWorld.DebugLog("    更新大奖进度! battleType=%s,ID=%s,taskType=%s,addValue=%s,superTaskValue=%s < %s"
                               % (self.battleType, self.ID, taskType, addValue, self.superTaskValue, self.superTaskValueMax), self.fbPropertyID)
            return
        self.superTaskValue -= self.superTaskValueMax
        self.superTaskFinishCount += 1
        GameWorld.Log("    完成大奖任务! battleType=%s,ID=%s,taskType=%s,superTaskFinishCount=%s"
                      % (self.battleType, self.ID, taskType, self.superTaskFinishCount), self.fbPropertyID)
        self.setSuperTaskValueMax(worldObj)
        if isOnlyCallHaveBoss:
            zoneID = FBCommon.GetCrossDynamicLineMapZoneID()
            hmNum = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossBattlefield)
            hmCallTeamInfo = PyGameData.g_crossBattlefieldCallTeamInfo.get(zoneID, {})
            callTeamInfo = hmCallTeamInfo.get(hmNum, {})
            if callTeamInfo:
                self.eventInfoList.append([eventBossStartTime, EventNum_Boss])
        else:
            self.eventInfoList.append([eventBossStartTime, EventNum_Boss])
        
        superRate = self.getSuperItemRate()
        tick = GameWorld.GetGameWorld().GetTick()
        if not GameWorld.CanHappen(superRate):
            GameWorld.Log("        大奖没有中奖! battleType=%s,ID=%s,taskType=%s,superRate=%s"
                          % (self.battleType, self.ID, taskType, superRate), self.fbPropertyID)
            FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshFactionPlayer)
            return
        self.eventInfoList.sort()
        
        superItemPlayerID = self.getSuperItemPlayerID()
        GameWorld.Log("        大奖中奖! battleType=%s,ID=%s,taskType=%s,superRate=%s,superItemPlayerID=%s"
                      % (self.battleType, self.ID, taskType, superRate, superItemPlayerID), self.fbPropertyID)
        if not superItemPlayerID:
            return
        worldObj.superItemPlayerID = superItemPlayerID
        itemID, itemCount = worldObj.superItemInfo[0], worldObj.superItemInfo[1]
        battleObj = GetBattlePlayerObj(superItemPlayerID)
        worldObj.superItemPlayerName = battleObj.name
        PlayerControl.FBNotify("CrossBattlefieldSuperItemPlayer", [battleObj.faction, battleObj.name, itemID, itemCount])
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshFactionPlayer)
        fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
        GameWorld.Log("随机战场事件刷新时间及编号列表: eventInfoList=%s" % self.eventInfoList, fbPropertyID)
        return
    
    def getSuperItemRate(self): return 0
    def getSuperItemPlayerID(self): return 0
    def setEventEnd(self, tick):
        GameWorld.Log("战场随机事件结束! eventNum=%s" % (self.eventNum), GameWorld.GetGameWorld().GetPropertyID())
        self.eventNum = 0
        self.eventNPCID = 0
        self.eventNPCPos = []
        self.eventNPCHP = 0
        self.eventEndTick = 0
        self.lastEventEndTick = tick # 上个事件结束tick
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
        return
    
## 战场阵营类
class BattleFaction(BattleBase):
class BattleFaction():
    
    def __init__(self, faction):
        super(BattleFaction, self).__init__(faction)
        self.fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
        self.faction = faction
        self.battleType = self.BattleType_Faction
        self.score = 0 # 积分
        self.scoreSortTime = 0 # 积分变更排序time值,用于同积分时,先到排名靠前
        self.factionPlayerDict = {} # {playerID:BattlePlayer, ...}
        self.battlePlayerSortList = [] # 阵营积分排名玩家列表 [BattlePlayer, ...]
        self.scoreKingIDList = [] # 前x名积分王ID列表 [playerID, ...] ,只算在线的,所以不一定是积分排名前x名
        
        self.onlineFightPowerTotal = 0 # 在线人数总战力
        self.onlinePlayerIDList = [] # 在线玩家ID列表 [playerID, ...]
        self.setSuperTaskValueMax(None)
        self.homePlayerIDList = [] # 在营地家里的玩家ID列表 [playerID, ...]
        self.factionBuffInfo = [] # 阵营当前获得的阵营buff信息 [buff技能ID, 结束时间戳]
        self.crystalScorePlusRate = 0 # 建筑获取资源速度提升万分率
        self.crystalScorePlusEndTick = 0 # 建筑获取资源速度提升结束tick
        self.hurtBossValue = 0 # 阵营对boss的总伤害
        self.hurtBossPlayerDict = {} # 阵营玩家对boss的伤害 {playerID:hurtValue, ...}
        self.superItemProgress = 0 # 阵营大奖开奖进度魂
        self.superItemPlayerID = 0 # 阵营大奖中奖者玩家ID
        self.superItemPlayerName = "" # 阵营大奖中奖者玩家名
        self.robotObjIDList = [] # 本阵营当前机器人实例ID列表
        return
    
    def getSuperItemRate(self):
        single = IpyGameDataPY.GetFuncCfg("CrossBattlefieldAwardSuper", 3)
        return single * len(self.onlinePlayerIDList)
    def getSuperItemPlayerID(self):
        if not self.onlinePlayerIDList:
            return 0
        return random.choice(self.onlinePlayerIDList)
    def getFactionHelpInfo(self):
        if self.factionBuffInfo and time.time() >= self.factionBuffInfo[1]:
            self.factionBuffInfo = []
        factionInfo = {"faction":self.faction, "score":self.score, "superItemPlayerName":self.superItemPlayerName,
                       "superItemProgress":self.superItemProgress, "factionBuffInfo":self.factionBuffInfo}
        if self.hurtBossValue:
            factionInfo["hurtBossValue"] = self.hurtBossValue
        return {"factionInfo_%s" % self.faction:factionInfo}
    
    def addScore(self, worldObj, addValue):
        super(BattleFaction, self).addScore(worldObj, addValue)
    def addSuperItemProgress(self, addProgress):
        if self.superItemPlayerID:
            # 阵营大奖已开奖,不再增加阵营大奖进度,但是依然会增加个人大奖贡献
            return
        self.superItemProgress = max(0, self.superItemProgress + addProgress)
        GameWorld.DebugLog("    增加阵营大奖进度: faction=%s,addProgress=%s,superItemProgress=%s"
                           % (self.faction, addProgress, self.superItemProgress), self.fbPropertyID)
        
        battleOverScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldFB", 2)
        if self.superItemProgress < IpyGameDataPY.GetFuncCfg("CrossBattlefieldAwardSuper", 2):
            return
        worldObj = GetBattleWorld()
        if not worldObj.superItemInfo:
            return
        # 本阵营大奖开奖,仅限在线玩家
        weightList = []
        for playerID, battleObj in self.factionPlayerDict.items():
            if playerID not in self.onlinePlayerIDList:
                continue
            if not battleObj.superItemContribution:
                continue
            weightList.append([battleObj.superItemContribution, playerID])
        superItemPlayerID = GameWorld.GetResultByWeightList(weightList)
        if not superItemPlayerID:
            return
        battleObj = GetBattlePlayerObj(superItemPlayerID)
        self.superItemPlayerID = superItemPlayerID
        self.superItemPlayerName = battleObj.name
        battleObj.superItemContribution = 0 # 重置贡献
        battleObj.superItemAwardCnt += 1
        itemID, itemCount = worldObj.superItemInfo[0], worldObj.superItemInfo[1]
        GameWorld.Log("阵营大奖开奖: faction=%s,weightList=%s,superItemPlayerID=%s,itemID=%s,itemCount=%s"
                      % (self.faction, weightList, superItemPlayerID, itemID, itemCount), self.fbPropertyID)
        PlayerControl.FBNotify("CrossBattlefieldSuperItemPlayer", [battleObj.faction, battleObj.name, itemID, itemCount])
        tick = GameWorld.GetGameWorld().GetTick()
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
        return
    def __checkPerScoreAddSuperItemProgress(self, befScore):
        perScoreInfo = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper2", 4)
        if not perScoreInfo or len(perScoreInfo) != 2:
            return
        superScorePer, addProgress = perScoreInfo
        if not superScorePer or not addProgress:
            return
        befTimes = befScore / superScorePer
        aftTimes = self.score / superScorePer
        if aftTimes <= 0 or aftTimes == befTimes:
            return
        GameWorld.DebugLog("    阵营每%s积分增加在线阵营玩家大奖贡献! addProgress=%s" % (superScorePer, addProgress), self.fbPropertyID)
        for playerID, battleObj in self.factionPlayerDict.items():
            if playerID in self.onlinePlayerIDList:
                battleObj.addSuperItemContribution(addProgress)
        return
    def addFactionScore(self, addValue, isCheckVictory=True):
        ## 增加阵营积分
        # @return: 是否结算胜负,某些情况下不能在加分后直接验证是否获胜,由于某些功能可能同时增加双方阵营积分,所以需等都加完后才处理结算
        if not addValue:
            return
        befScore = self.score
        self.score = max(0, self.score + addValue)
        calcTime = 3471264000 #GameWorld.ChangeTimeStrToNum("2080-01-01 00:00:00")
        self.scoreSortTime = max(0, calcTime - int(time.time()))
        GameWorld.DebugLog("    增加阵营积分: faction=%s,addValue=%s,updScore=%s" % (self.faction, addValue, self.score), self.fbPropertyID)
        self.__checkPerScoreAddSuperItemProgress(befScore)
        if not isCheckVictory:
            return
        return self.checkIsVictory()
    def checkIsVictory(self):
        battleOverScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreBase", 1)
        if self.score < battleOverScore:
            return
        
        GameWorld.Log("阵营积分达到获胜积分,获胜! faction=%s,updScore=%s" % (self.faction, self.score), self.fbPropertyID)
        GameWorld.Log("阵营积分达到获胜积分,获胜! faction=%s,score=%s" % (self.faction, self.score), self.fbPropertyID)
        tick = GameWorld.GetGameWorld().GetTick()
        DoOver(self.faction, tick)
        return True
def checkBattleOver(tick):
    ## 检查结算,根据双方最终积分判断获胜方
    jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
    eFactionObj = GetBattleFactionObj(ShareDefine.CampType_Evil)
    battleOverScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreBase", 1)
    if jFactionObj.score < battleOverScore and eFactionObj.score < battleOverScore:
        # 都未获胜
        return
    
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    winFactionObj = jFactionObj
    # 一般情况双方积分不一样,取排序后的最高分即为获胜阵营
    if jFactionObj.score != eFactionObj.score:
        sortList = [[jFactionObj.score, jFactionObj], [eFactionObj.score, eFactionObj]]
        sortList.sort(reverse=True)
        _, winFactionObj = sortList[0]
        winFaction = winFactionObj.faction
        GameWorld.Log("双方阵营积分不同,高分一方获胜! winFaction=%s,jScore=%s,eScore=%s"
                      % (winFaction, jFactionObj.score, eFactionObj.score), fbPropertyID)
    # 积分相同的情况,随机一方获胜
    else:
        winFaction = random.choice([ShareDefine.CampType_Justice, ShareDefine.CampType_Evil])
        winFactionObj = GetBattleFactionObj(winFaction)
        winFactionObj.score += 100 # 随机获胜方额外增加积分
        GameWorld.Log("双方阵营积分相同,随机一方获胜! winFaction=%s,jScore=%s,eScore=%s"
                      % (winFaction, jFactionObj.score, eFactionObj.score), fbPropertyID)
    return winFactionObj.checkIsVictory()
## 战场玩家类
class BattlePlayer(BattleBase):
class BattlePlayer():
    
    def __init__(self, playerID):
        super(BattlePlayer, self).__init__(playerID)
        self.battleType = self.BattleType_Player
        self.playerID = playerID
        self.name = ""
        self.faction = 0
        self.factionObj = None
        self.accID = ""
        self.job = 1
        self.realmLV = 0
        self.fightPower = 0
        self.highScoreToday = 0 # 本日最高积分
        self.highScoreWeekTotal = 0 # 本周每日最高分累计
        self.enterCountWeek = 0 # 本周累计进入次数
        self.onlineCalcTick = 0 # 在线统计tick
        self.onlineTimes = 0 # 活动累计在线时长,毫秒
        self.setSuperTaskValueMax(None)
        self.restoreHPTick = 0 # 营地回血tick
        self.itemRebornCount = 0 # 使用特殊道具原地复活次数
        self.score = 0 # 积分
        self.scoreSortTime = 0 # 积分变更排序time值,用于同积分时,先到排名靠前
        self.killCount = 0 # 击杀数
        self.continueKillCount = 0 # 连杀数
        self.ckillCntInfo = {} # 成就连杀数次数 {连杀数:次数, ...}
        self.killPlayerAddScoreTimes = 0 # 击杀玩家获得积分倍值
        self.killPlayerScoreAwardEndTick = 0 # 击杀玩家多倍积分福利结束tick
        self.killBossCnt = 0 # 本阵营归属击败boss
        self.killScoreKing = 0 # 本场次是否有击败积分王,单场仅计算一次
        self.killGuardCnt = 0 # 击杀守卫次数
        self.auraScore = 0 # 在光环中累计获得积分
        self.superItemAwardCnt = 0 # 获得大奖次数
        self.factionBuffCollCnt = 0 # 采集阵营buff次数
        self.personBuffCollCnt = 0 # 个人buff次数
        self.crystalCollCnt = 0 # 采集水晶资源次数
        self.wallCollCnt = 0 # 采集积分墙次数
        self.superItemContribution = 0 # 大奖进度贡献值,也是大奖获奖权重
        return
    
    def getSuperItemRate(self): return IpyGameDataPY.GetFuncCfg("CrossBattlefieldAwardSuper", 2)
    def getSuperItemPlayerID(self): return self.ID
    def getFactionObj(self):
        if not self.factionObj and self.faction:
            self.factionObj = GetBattleFactionObj(self.faction)
        return self.factionObj
    def getPlayerHelpInfo(self, exInfo=None):
        helpInfo = {"score":self.score, "superItemContribution":self.superItemContribution, "itemRebornCount":self.itemRebornCount,
                    "killCount":self.killCount, "continueKillCount":self.continueKillCount}
        if exInfo:
            helpInfo.update(exInfo)
        return {"playerInfo":helpInfo}
    def addPlayerScore(self, curPlayer, addValue, scoreType=ScoreType_Default, scoreTimes=1, isCheckVictory=True):
        addValue *= scoreTimes
        befScore = self.score
        self.score = max(0, self.score + addValue)
        calcTime = 3471264000 #GameWorld.ChangeTimeStrToNum("2080-01-01 00:00:00")
        self.scoreSortTime = max(0, calcTime - int(time.time()))
        GameWorld.DebugLog("    增加玩家积分: playerID=%s,scoreType=%s,addValue=%s,倍值=%s,updScore=%s"
                           % (self.playerID, scoreType, addValue, scoreTimes, self.score), self.playerID)
        if scoreType == ScoreType_Aura and addValue > 0:
            self.auraScore += addValue
        if curPlayer:
            FBCommon.Notify_FBHelp(curPlayer, self.getPlayerHelpInfo({"addScore":[addValue, scoreType, scoreTimes]}))
        superScorePer = IpyGameDataPY.GetFuncCfg("CrossBattlefieldAwardSuper2", 1)
        if superScorePer:
            befTimes = befScore / superScorePer
            aftTimes = self.score / superScorePer
            if aftTimes > 0 and aftTimes != befTimes:
                addIndex = aftTimes - 1
                addProgressList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper2", 3)
                addProgress = addProgressList[addIndex] if len(addProgressList) > addIndex else addProgressList[-1]
                GameWorld.DebugLog("    玩家每%s积分增加大奖贡献! addProgress=%s,superItemContribution=%s"
                                   % (superScorePer, addProgress, self.superItemContribution), self.playerID)
                self.addSuperItemContribution(addProgress)
        # 个人增加积分同步增加所属阵营积分
        factionObj = self.getFactionObj()
        if factionObj:
            factionObj.addFactionScore(addValue, isCheckVictory)
        return
    def addKillCount(self, addCount):
        befContKillCount = self.continueKillCount
        self.killCount = max(0, self.killCount + addCount)
        self.continueKillCount = max(0, self.continueKillCount + addCount) # 同步增加连杀
        superContKillPer = IpyGameDataPY.GetFuncCfg("CrossBattlefieldAwardSuper2", 2)
        if superContKillPer:
            befTimes = befContKillCount / superContKillPer
            aftTimes = self.continueKillCount / superContKillPer
            if aftTimes > 0 and aftTimes != befTimes:
                addIndex = aftTimes - 1
                addProgressList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldAwardSuper2", 3)
                addProgress = addProgressList[addIndex] if len(addProgressList) > addIndex else addProgressList[-1]
                GameWorld.DebugLog("    玩家每%s连杀增加大奖贡献! addProgress=%s,superItemContribution=%s"
                                   % (superContKillPer, addProgress, self.superItemContribution), self.playerID)
                self.addSuperItemContribution(addProgress)
        # 连杀数成就计数
        ckillCntList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldSuccess", 1)
        for ckillCnt in ckillCntList:
            # 需整除才计数1
            if self.continueKillCount and self.continueKillCount % ckillCnt == 0:
                self.ckillCntInfo[ckillCnt] = self.ckillCntInfo.get(ckillCnt, 0) + 1
        return
    def addSuperItemContribution(self, addProgress):
        self.superItemContribution = max(0, self.superItemContribution + addProgress)
        GameWorld.DebugLog("    更新玩家大奖贡献: playerID=%s,addProgress=%s,superItemContribution=%s" % (self.playerID, addProgress, self.superItemContribution), self.playerID)
        factionObj = self.getFactionObj()
        if factionObj:
            factionObj.addSuperItemProgress(addProgress)
        return
    
def GetBattleWorld():
    worldObj = FBCommon.GetGameFBData(GameFBData_BattleWorld)
@@ -288,27 +477,80 @@
        playerObj = BattlePlayer(playerID)
        playerInfoDict[playerID] = playerObj
    return playerObj
def GetBFStepTime(): return IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFB", 1) # 阶段时间
def GetCrystalNPCIDList(): # 水晶资源NPCID列表
    crystalNPCIDPosDict = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldCrystal", 1, {})
    return crystalNPCIDPosDict.keys()
def GetGuardNPCIDList(): return IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldGuard", 1) # 守卫NPCID列表
def GetPersonBuffIDList(): return IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldPersonBuff", 1) # 个人buffID列表
def GetFactionBuffIDList(): return IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFactionBuff", 1) # 阵营buffID列表
def GetRobotNPCIDList(): return IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldRobot", 1) # 机器人NPCID列表
def OnOpenFB(tick):
    #fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    FBCommon.SetGameFBData(GameFBData_BattleWorld, None)
    FBCommon.SetGameFBData(GameFBData_FactionInfo, {})
    FBCommon.SetGameFBData(GameFBData_PlayerInfo, {})
    
    GetBattleWorld()
    worldObj = GetBattleWorld()
    GetBattleFactionObj(ShareDefine.CampType_Justice)
    GetBattleFactionObj(ShareDefine.CampType_Evil)
    
    FBCommon.SetFBStep(FB_Step_Prepare, tick)
    zoneID = FBCommon.GetCrossDynamicLineMapZoneID()
    hmNum = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossBattlefield)
    hmCallTeamInfo = PyGameData.g_crossBattlefieldCallTeamInfo.get(zoneID, {})
    callTeamInfo = hmCallTeamInfo.get(hmNum, {})
    for playerID, callTeam in callTeamInfo.items():
        worldObj.callOpenPlayerInfo[playerID] = callTeam["factionID"]
    GameWorld.Log("开启战场副本: hmNum=%s,callOpenPlayerInfo=%s" % (hmNum, worldObj.callOpenPlayerInfo), fbPropertyID)
    # 刷水晶
    crystalNPCIDPosDict = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldCrystal", 1, {})
    for npcID, posInfo in crystalNPCIDPosDict.items():
        NPCCommon.SummonMapNpc(npcID, posInfo[0], posInfo[1])
    # 刷守卫
    rebornGurad()
    return
def rebornGurad():
    # 复活守卫
    isOnlyCallHaveGuard = IpyGameDataPY.GetFuncCfg("CrossBattlefieldGuard", 5)
    guardFactionList = []
    if isOnlyCallHaveGuard:
        zoneID = FBCommon.GetCrossDynamicLineMapZoneID()
        hmNum = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossBattlefield)
        hmCallTeamInfo = PyGameData.g_crossBattlefieldCallTeamInfo.get(zoneID, {})
        callTeamInfo = hmCallTeamInfo.get(hmNum, {})
        for playerID, callTeam in callTeamInfo.items():
            guardFactionList.append([callTeam["factionID"], playerID])
    else:
        guardFactionList = [[ShareDefine.CampType_Justice, 0], [ShareDefine.CampType_Evil, 0]]
    rebornNPCIDList = []
    guardNPCIDList = GetGuardNPCIDList()
    guardNPCPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldGuard", 2)
    for faction, playerID in guardFactionList:
        if not faction or faction > len(guardNPCIDList) or faction > len(guardNPCPosList):
            continue
        npcID = guardNPCIDList[faction - 1]
        if GameWorld.FindNPCByNPCID(npcID):
            GameWorld.DebugLog("守卫已存在,不重复复活! npcID=%s" % npcID)
            continue
        posInfo = guardNPCPosList[faction - 1]
        NPCCommon.SummonMapNpc(npcID, posInfo[0], posInfo[1], playerID=playerID)
        rebornNPCIDList.append(npcID)
    return rebornNPCIDList
def OnCloseFB(tick):
    GameWorld.GetGameWorld().SetPropertyID(0)
    FBCommon.SetGameFBData(GameFBData_BattleWorld, None)
    FBCommon.SetGameFBData(GameFBData_FactionInfo, None)
    FBCommon.SetGameFBData(GameFBData_PlayerInfo, None)
    FBCommon.ClearFBNPC()
    return
def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
@@ -334,7 +576,7 @@
##副本玩家进入点, 玩家分散在半径3格范围
def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):
    return random.choice(IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldPos", 1))
    return random.choice(IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFB", 2))
def DoEnterFB(curPlayer, tick):    
    gameFB = GameWorld.GetGameFB()
@@ -367,31 +609,26 @@
    elif fbStep == FB_Step_Fighting:
        notify_tick = GetBFStepTime()[Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
        curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)
        isToSafePos = not battleObj.faction
        allotPlayerFaction(playerID, fightPower, curPlayer, isToSafePos, tick)
        allotPlayerFaction(playerID, fightPower, curPlayer, fbStep, tick)
        
    return
##获得副本帮助信息, 用于通知阵营比分条
def DoFBHelp(curPlayer, tick):
    #gameWorld = GameWorld.GetGameWorld()
    gameWorld = GameWorld.GetGameWorld()
    playerID = curPlayer.GetPlayerID()
    lineID = gameWorld.GetLineID()
    
    worldObj = GetBattleWorld()
    battleObj = GetBattlePlayerObj(playerID)
    playerInfo = {"score":battleObj.score, "superTaskValue":battleObj.superTaskValue,
                  "superTaskValueMax":battleObj.superTaskValueMax, "superTaskFinishCount":battleObj.superTaskFinishCount}
    
    factionInfo = {}
    helpDict = {}
    helpDict.update(battleObj.getPlayerHelpInfo())
    helpDict.update(worldObj.getWorldHelpInfo(tick))
    for faction in [ShareDefine.CampType_Justice, ShareDefine.CampType_Evil]:
        factionObj = GetBattleFactionObj(faction)
        factionInfo[str(faction)] = {"score":factionObj.score, "superTaskValue":factionObj.superTaskValue,
                                     "superTaskValueMax":factionObj.superTaskValueMax, "superTaskFinishCount":factionObj.superTaskFinishCount}
    worldInfo = {"superTaskType":worldObj.superTaskType, "superItemPlayerName":worldObj.superItemPlayerName, "superItemInfo":worldObj.superItemInfo}
    helpDict = {"playerInfo":playerInfo, "factionInfo":factionInfo, "worldInfo":worldInfo}
        helpDict.update(factionObj.getFactionHelpInfo())
    helpDict[FBCommon.Help_robotJob] = PyGameData.g_fbRobotJobDict.get(lineID, {})
    #GameWorld.DebugLog("DoFBHelp %s" % helpDict, playerID)
    FBCommon.Notify_FBHelp(curPlayer, helpDict)
    return
@@ -439,7 +676,7 @@
    
    # 副本准备
    if fbStep == FB_Step_Prepare:
        __DoLogic_FB_Prepare(tick)
        __DoLogic_FB_Prepare(fbStep, tick)
        
    # 副本进行中
    elif fbStep == FB_Step_Fighting:
@@ -447,11 +684,11 @@
        
    # 副本结束
    elif fbStep == FB_Step_LeaveTime:
        __DoLogic_FB_Over(tick)
        __DoLogic_FB_Leave(tick)
        
    return
def __DoLogic_FB_Prepare(tick):
def __DoLogic_FB_Prepare(fbStep, tick):
    
    remaindTick = GetBFStepTime()[Time_Prepare] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    if remaindTick > 0:
@@ -483,11 +720,8 @@
#        playerInfoList.append({"playerID":playerID, "fightPower":fightPower, "curPlayer":None})
#    ##--------- 山寨分配测试代码 --------------
    
    # 按战力排序
    # 当超过副本下限人数时,往人数低的阵营划分; 否则 往战力低的阵营划分
    playerInfoList.sort(key=operator.itemgetter("fightPower"), reverse=True)
    isToSafePos = True
    # 按战力从低到高升序排序
    playerInfoList.sort(key=operator.itemgetter("fightPower"))
    
    # 先分配召集队伍
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
@@ -507,7 +741,7 @@
            playerID = playerInfo["playerID"]
            fightPower = playerInfo["fightPower"]
            curPlayer = playerInfo["curPlayer"]
            allotPlayerFaction(playerID, fightPower, curPlayer, isToSafePos, tick)
            allotPlayerFaction(playerID, fightPower, curPlayer, fbStep, tick)
            
    for playerInfo in playerInfoList:
        playerID = playerInfo["playerID"]
@@ -515,11 +749,12 @@
        curPlayer = playerInfo["curPlayer"]
        if playerID in callPlayerIDList:
            continue
        allotPlayerFaction(playerID, fightPower, curPlayer, isToSafePos, tick)
        allotPlayerFaction(playerID, fightPower, curPlayer, fbStep, tick)
        
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def allotPlayerFaction(playerID, fightPower, curPlayer, isToSafePos, tick):
def allotPlayerFaction(playerID, fightPower, curPlayer, allotStep, tick):
    ## 分配玩家阵营
    
    zoneID = FBCommon.GetCrossDynamicLineMapZoneID()
@@ -536,26 +771,28 @@
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    battleObj = GetBattlePlayerObj(playerID)
    faction = battleObj.faction
    isAllot = not faction # 是否分配,无阵营时为 True
    if callFaction:
        faction = callFaction # 召集阵营为固定阵营
        
    if not faction:
        jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
        eFactionObj = GetBattleFactionObj(ShareDefine.CampType_Evil)
        onlinePlayerTotal = len(jFactionObj.onlinePlayerIDList) + len(eFactionObj.onlinePlayerIDList)
        fbPlayerCountSet = IpyGameDataPY.GetFuncCfg("CrossBattlefieldFB", 3) # 副本下限人数设定
        # 当超过副本下限人数时,往人数低的阵营划分; 否则 往战力低的阵营划分
        if onlinePlayerTotal > fbPlayerCountSet:
            faction = ShareDefine.CampType_Justice if len(jFactionObj.onlinePlayerIDList) <= len(eFactionObj.onlinePlayerIDList) else ShareDefine.CampType_Evil
        jPlayerCount = len(jFactionObj.factionPlayerDict)
        ePlayerCount = len(eFactionObj.factionPlayerDict)
        # 人数相同时随机,否则往人数少的分配
        if jPlayerCount == ePlayerCount:
            faction = random.choice([ShareDefine.CampType_Justice, ShareDefine.CampType_Evil])
        elif jPlayerCount < ePlayerCount:
            faction = ShareDefine.CampType_Justice
        else:
            faction = ShareDefine.CampType_Justice if jFactionObj.onlineFightPowerTotal <= eFactionObj.onlineFightPowerTotal else ShareDefine.CampType_Evil
            faction = ShareDefine.CampType_Evil
            
    battleObj.faction = faction
    battleObj.onlineCalcTick = tick
    
    factionObj = GetBattleFactionObj(faction)
    battleObj.factionObj = factionObj
    
    if playerID not in factionObj.factionPlayerDict:
        factionObj.factionPlayerDict[playerID] = battleObj
@@ -565,38 +802,120 @@
    if playerID not in factionObj.onlinePlayerIDList:
        factionObj.onlinePlayerIDList.append(playerID)
        
    GameWorld.Log("    分配阵营: callFaction=%s,faction=%s,playerID=%s,fightPower=%s,onlineFightPowerTotal=%s,onlinePlayerIDList=%s,isToSafePos=%s"
                  % (callFaction, faction, playerID, fightPower, factionObj.onlineFightPowerTotal, factionObj.onlinePlayerIDList, isToSafePos), fbPropertyID)
    GameWorld.Log("    分配阵营: allotStep=%s,callFaction=%s,faction=%s,playerID=%s,fightPower=%s,onlineFightPowerTotal=%s,onlinePlayerIDList=%s,isAllot=%s"
                  % (allotStep, callFaction, faction, playerID, fightPower, factionObj.onlineFightPowerTotal, factionObj.onlinePlayerIDList, isAllot), fbPropertyID)
    
    # 分配阶段是准备阶段的
    if allotStep == FB_Step_Prepare:
        initScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreBase", 2)
        battleObj.addPlayerScore(curPlayer, initScore)
    if curPlayer:
        curPlayer.SetFaction(faction)
        if isToSafePos:
            __RandFactionSafeArea(curPlayer)
        if isAllot:
            __RandFactionRebornArea(curPlayer)
            
    return
## 重置副本复活玩家坐标点
def OnResetFBRebornPlacePos(curPlayer, rebornPlace, tick):
    __RandFactionSafeArea(curPlayer)
def OnCanFBReborn(curPlayer, rebornType):
    playerID = curPlayer.GetPlayerID()
    if rebornType == ChConfig.rebornType_Health:
        GameWorld.ErrLog("不允许消耗货币原地健康复活! ", playerID)
        return False
    if rebornType == ChConfig.rebornType_UseItem:
        battleObj = GetBattlePlayerObj(playerID)
        if battleObj.itemRebornCount >= IpyGameDataPY.GetFuncCfg("CrossBattlefieldReborn", 2):
            PlayerControl.NotifyCode(curPlayer, "CrossBattlefieldItemRebornLimit")
            return False
    return True
## 玩家复活后处理
def OnPlayerRebornOver(curPlayer, rebornType):
    playerID = curPlayer.GetPlayerID()
    battleObj = GetBattlePlayerObj(playerID)
    if rebornType == ChConfig.rebornType_UseItem:
        battleObj.itemRebornCount += 1
        GameWorld.DebugLog("更新使用道具复活次数! itemRebornCount=%s, 且不中断连杀=%s"
                           % (battleObj.itemRebornCount, battleObj.continueKillCount), playerID)
    else:
        GameWorld.DebugLog("非原地复活,中断连杀!  %s" % battleObj.continueKillCount, playerID)
        battleObj.continueKillCount = 0 # 非原地复活的中断连杀数
    return
def __RandFactionSafeArea(curPlayer):
    faction = curPlayer.GetFaction()
    factionSafeAreaRandPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldPos", 2)
    if faction and faction <= len(factionSafeAreaRandPosList):
        safePosX, safePosY, radius = random.choice(factionSafeAreaRandPosList[faction - 1])
        posPoint = GameMap.GetEmptyPlaceInArea(safePosX, safePosY, radius)
        posX, posY = posPoint.GetPosX(), posPoint.GetPosY()
def OnPlayerReborn():
    ## 是否副本复活
    return True
## 重置副本复活玩家坐标点
def OnResetFBRebornPlacePos(curPlayer, rebornPlace, tick):
    __RandFactionRebornArea(curPlayer)
    return
def __RandFactionRebornArea(curPlayer):
    ## 随机阵营复活点: 营地 + 已占领的资源点  随机
    faction = curPlayer.GetFaction()
    posInfo = getRandFactionRebornPos(faction)
    if posInfo:
        posX, posY = posInfo
    else:
        posX, posY = curPlayer.GetPosX(), curPlayer.GetPosY()
    curPlayer.ResetPos(posX, posY)
    return
def getRandFactionRebornPos(faction):
    rebornPosList = []
    factionSafeAreaRandPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFB", 3)
    if faction and faction <= len(factionSafeAreaRandPosList):
        safePosX, safePosY, _ = factionSafeAreaRandPosList[faction - 1]
        rebornPosList.append([safePosX, safePosY, 3])
    crystalNPCIDPosDict = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldCrystal", 1, {})
    worldObj = GetBattleWorld()
    for npcID, ownerFaction in worldObj.crystalFactionInfo.items():
        if ownerFaction != faction:
            continue
        if npcID not in crystalNPCIDPosDict:
            continue
        posInfo = crystalNPCIDPosDict[npcID]
        rebornPosList.append([posInfo[0], posInfo[1], 3])
    if not rebornPosList:
        return
    randPosX, randPosY, radius = random.choice(rebornPosList)
    posPoint = GameMap.GetEmptyPlaceInArea(randPosX, randPosY, radius)
    return posPoint.GetPosX(), posPoint.GetPosY()
def GetFBRobotRandomMovePos(curNPC):
    ## 获取副本中机器人随机移动坐标点
    randPosList = []
    crystalNPCIDPosDict = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldCrystal", 1, {})
    for posX, posY in crystalNPCIDPosDict.values():
        randPosList.append([posX, posY])
    factionBuffPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFactionBuff", 2)
    for posList in factionBuffPosList:
        for posX, posY in posList:
            randPosList.append([posX, posY])
    return random.choice(randPosList)
def __DoLogic_FB_Fighting(tick):
    
    remaindTick = GetBFStepTime()[Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    passTick = tick - GameWorld.GetGameFB().GetFBStepTick()
    remaindTick = GetBFStepTime()[Time_Fight] * 1000 - passTick
    if remaindTick > 0:
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 5000, refreshFactionPlayer)
        passSeconds = passTick / 1000
        __refreshFactionHome(tick)
        __RefreshPersonBuff(tick, passSeconds)
        __RefreshFactionBuff(tick, passSeconds)
        __RefreshBattlefieldEvent(tick, passSeconds)
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, FightRefreshInterval, refreshCrossBattlefield)
        return
    
    jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
@@ -611,111 +930,531 @@
    DoOver(winnerFaction, tick)
    return
def __DoLogic_FB_Over(tick):
def __refreshFactionHome(tick):
    # 刷新阵营营地相关,如回血等
    restoreHPPerBySecond = IpyGameDataPY.GetFuncCfg("CrossBattlefieldFB", 4) # 每秒回血百分比
    factionSafeAreaRandPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFB", 3) # 营地坐标
    copyMapMgr = GameWorld.GetMapCopyPlayerManager()
    for faction in [ShareDefine.CampType_Justice, ShareDefine.CampType_Evil]:
        factionObj = GetBattleFactionObj(faction)
        if not factionObj.homePlayerIDList:
            continue
        for playerID in factionObj.homePlayerIDList[::-1]:
            curPlayer = copyMapMgr.FindPlayerByID(playerID)
            if not curPlayer:
                continue
            batObj = GetBattlePlayerObj(playerID)
            safePosX, safePosY, safeRadius = factionSafeAreaRandPosList[faction - 1]
            if GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), safePosX, safePosY) > safeRadius:
                factionObj.homePlayerIDList.remove(playerID)
                batObj.restoreHPTick = 0
                continue
            # 营地回血
            restoreSeconds = (tick - batObj.restoreHPTick) / 1000.0 if batObj.restoreHPTick else 1 # 首次保底1秒
            if restoreSeconds < 1:
                continue
            maxHP = GameObj.GetMaxHP(curPlayer)
            if GameObj.GetHP(curPlayer) < maxHP:
                restoreHP = int(maxHP * restoreHPPerBySecond / 100.0 * round(restoreSeconds, 1))
                #GameWorld.DebugLog("restoreHPPerBySecond=%s,restoreSeconds=%s,maxHP=%s,restoreHP=%s"
                #                   % (restoreHPPerBySecond, restoreSeconds, maxHP, restoreHP), playerID)
                SkillCommon.SkillAddHP(curPlayer, 0, restoreHP)
            batObj.restoreHPTick = tick
    return
def __RefreshPersonBuff(tick, passSeconds):
    ## 刷新个人buff
    startRefreshSeconds, refreshCD = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldPersonBuff", 3)
    if passSeconds < startRefreshSeconds:
        return
    buffCountMax = IpyGameDataPY.GetFuncCfg("CrossBattlefieldPersonBuff", 4)
    worldObj = GetBattleWorld()
    if worldObj.personBuffCount >= buffCountMax:
        return
    if (tick - worldObj.personBuffCalcTick) < (refreshCD * 1000):
        return
    buffIDList = GetPersonBuffIDList()
    if not buffIDList:
        return
    posList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldPersonBuff", 2)
    posInfo = __GetRandPos(posList)
    if not posInfo:
        return
    randBuffNPCID = random.choice(buffIDList)
    if not NPCCommon.SummonMapNpc(randBuffNPCID, posInfo[0], posInfo[1]):
        return
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    worldObj.personBuffCount = worldObj.personBuffCount + 1
    if worldObj.personBuffCount >= buffCountMax:
        worldObj.personBuffCalcTick = 0
    else:
        worldObj.personBuffCalcTick = tick
    GameWorld.DebugLog("刷新个人buff: randBuffNPCID=%s,personBuffCount=%s" % (randBuffNPCID, worldObj.personBuffCount), fbPropertyID)
    return
def __RefreshFactionBuff(tick, passSeconds):
    ## 刷新阵营buff
    startRefreshSeconds, refreshCD = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFactionBuff", 3)
    if passSeconds < startRefreshSeconds:
        return
    worldObj = GetBattleWorld()
    if worldObj.factionBuffNPCInfo:
        return
    if (tick - worldObj.factionBuffCalcTick) < (refreshCD * 1000):
        return
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    if not worldObj.factionBuffIDOrderList:
        buffIDList = GetFactionBuffIDList()
        if not buffIDList:
            return
        worldObj.factionBuffIDOrderList = copy.deepcopy(buffIDList)
        random.shuffle(worldObj.factionBuffIDOrderList) # 每轮重新打乱顺序
        GameWorld.DebugLog("战场阵营buff顺序列表: %s" % worldObj.factionBuffIDOrderList, fbPropertyID)
    if not worldObj.factionBuffIDOrderList:
        return
    jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
    eFactionObj = GetBattleFactionObj(ShareDefine.CampType_Evil)
    # 使用对方阵营的积分作为本阵营权重, 分数越低的阵营随机到靠近自己阵营的位置的权重越高,权重至少10
    nearFactionWeightList = [[max(10, jFactionObj.score), ShareDefine.CampType_Evil],
                             [max(10, eFactionObj.score), ShareDefine.CampType_Justice]]
    nearFaction = GameWorld.GetResultByWeightList(nearFactionWeightList, ShareDefine.CampType_Evil)
    allPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFactionBuff", 2)
    if nearFaction > len(allPosList):
        return
    posList = allPosList[nearFaction - 1]
    posInfo = __GetRandPos(posList)
    if not posInfo:
        return
    posX, posY = posInfo[0], posInfo[1]
    randBuffNPCID = worldObj.factionBuffIDOrderList.pop(0)
    if not NPCCommon.SummonMapNpc(randBuffNPCID, posX, posY):
        return
    worldObj.factionBuffNPCInfo = [randBuffNPCID, posX, posY]
    GameWorld.DebugLog("刷新阵营buff: randBuffNPCID=%s,nearFaction=%s,nearFactionWeightList=%s"
                       % (randBuffNPCID, nearFaction, nearFactionWeightList), fbPropertyID)
    PlayerControl.FBNotify("CrossBattlefieldBuff_%s" % randBuffNPCID, [randBuffNPCID])
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def __GetRandPos(posList):
    if not posList:
        return
    random.shuffle(posList)
    gameMap = GameWorld.GetMap()
    for posX, posY in posList:
        if gameMap.CanMove(posX, posY) != True:
            continue
        #检查有没有玩家在这一点上
        mapObj = gameMap.GetPosObj(posX, posY)
        if not mapObj:
            continue
        if mapObj.GetObjCount() != 0:
            #有玩家在此点上
            #GameWorld.DebugLog("有实例在此坐标上: posX=%s, posY=%s, GetObjCount=%s"
            #                   % (posX, posY, mapObj.GetObjCount()), GameWorld.GetGameWorld().GetPropertyID())
            continue
        return posX, posY
    return
def __RefreshBattlefieldEvent(tick, passSeconds):
    ## 刷新战场随机事件
    worldObj = GetBattleWorld()
    if worldObj.eventStartTick > worldObj.lastEventEndTick:
        #GameWorld.DebugLog("当前事件进行中未结束!")
        if worldObj.eventNum == EventNum_Aura:
            if tick <= worldObj.eventEndTick:
                return
            auraNPCID = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreAura", 1)
            auraNPC = GameWorld.FindNPCByNPCID(auraNPCID)
            if auraNPC:
                NPCCommon.SetDeadEx(auraNPC)
            worldObj.setEventEnd(tick)
        return
    if not worldObj.eventInfoList:
        return
    nextEventTime, nextEventNum = worldObj.eventInfoList[0] # 默认取第一个就行,副本开始时已随机好
    if passSeconds < nextEventTime:
        # 事件时间未到
        return
    eventRefresCD = IpyGameDataPY.GetFuncCfg("CrossBattlefieldEvent", 4) * 1000
    if worldObj.lastEventEndTick and eventRefresCD and (tick - worldObj.lastEventEndTick) < eventRefresCD:
        GameWorld.DebugLog("事件刷新CD中!")
        return
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
    eFactionObj = GetBattleFactionObj(ShareDefine.CampType_Evil)
    nearFaction = 0
    if nextEventNum == EventNum_Boss:
        callFactioList = worldObj.callOpenPlayerInfo.values()
        callFactioList = worldObj.callOpenPlayerInfo.values()
        if len(callFactioList) == 1:
            nearFaction = callFactioList[0]
            GameWorld.Log("战场boss事件,仅一方召集,固定刷新在靠近该阵营的位置: nearFaction=%s, callOpenPlayerInfo=%s"
                          % (nearFaction, worldObj.callOpenPlayerInfo), fbPropertyID)
        else:
            GameWorld.Log("战场boss事件,走常规逻辑判断靠近阵营位置! callOpenPlayerInfo=%s" % worldObj.callOpenPlayerInfo, fbPropertyID)
    # 使用对方阵营的积分作为本阵营权重, 分数越低的阵营随机到靠近自己阵营的位置的权重越高,权重至少10
    if nearFaction:
        # 已经决定了事件靠近的阵营,不用再处理
        pass
    elif jFactionObj.score < eFactionObj.score:
        nearFaction = ShareDefine.CampType_Justice
    elif jFactionObj.score > eFactionObj.score:
        nearFaction = ShareDefine.CampType_Evil
    else:
        nearFaction = random.choice([ShareDefine.CampType_Justice, ShareDefine.CampType_Evil])
    if nextEventNum == EventNum_Aura:
        refreshNPCID = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreAura", 1)
    elif nextEventNum == EventNum_Boss:
        refreshNPCID = IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 1)
    elif nextEventNum == EventNum_Wall:
        refreshNPCID = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 1)
    else:
        return
    refreshMark = 0
    if refreshNPCID:
        eventRefreshMarkList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldEvent", 1)
        if nearFaction > len(eventRefreshMarkList):
            return
        refreshMark = eventRefreshMarkList[nearFaction - 1]
    worldObj.eventInfoList.pop(0)
    eventNum = nextEventNum
    GameWorld.Log("开始战场事件: eventNum=%s,refreshNPCID=%s,nearFaction=%s,refreshMark=%s"
                  % (eventNum, refreshNPCID, nearFaction, refreshMark), fbPropertyID)
    worldObj.eventNum = eventNum
    worldObj.eventNPCID = refreshNPCID
    worldObj.eventStartTick = tick
    if eventNum == EventNum_Aura:
        worldObj.eventEndTick = tick + IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreAura", 2) * 1000
    else:
        worldObj.eventEndTick = 0
    if refreshNPCID and refreshMark:
        NPCCustomRefresh.SetNPCRefresh(refreshMark, [refreshNPCID])
    # 帮助信息放在NPC刷出来后通知,因为需要坐标信息
    return
def DoFBRebornNPC(curNPC, tick):
    ##副本有NPC召出
    npcID = curNPC.GetNPCID()
    worldObj = GetBattleWorld()
    if npcID == worldObj.eventNPCID:
        fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
        eventNum = worldObj.eventNum
        worldObj.eventNPCHP = GameObj.GetHP(curNPC)
        worldObj.eventNPCPos = [curNPC.GetPosX(), curNPC.GetPosY()]
        GameWorld.Log("战场事件NPC刷新: eventNum=%s,npcID=%s,eventNPCPos=%s,eventNPCHP=%s"
                      % (worldObj.eventNum, npcID, worldObj.eventNPCPos, worldObj.eventNPCHP), fbPropertyID)
        if eventNum == EventNum_Aura:
            PlayerControl.FBNotify("CrossBattlefieldEventAura", [npcID])
        elif eventNum == EventNum_Boss:
            factionScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 3)
            PlayerControl.FBNotify("CrossBattlefieldEventBoss", [npcID, factionScore])
        elif eventNum == EventNum_Wall:
            wallScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 3)
            PlayerControl.FBNotify("CrossBattlefieldEventWall", [npcID, wallScore, worldObj.eventNPCHP])
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def DoBeAttackOver(attacker, defender, curSkill, tick):
    atkObjType = attacker.GetGameObjType()
    defObjType = defender.GetGameObjType()
    if atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotPlayer:
        curNPC, curPlayer = attacker, defender
        npcID = curNPC.GetNPCID()
        if npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreAura", 1):
            __DoAuraNPCAddPlayerScore(curNPC, curPlayer)
    return
def __DoAuraNPCAddPlayerScore(curNPC, curPlayer):
    ## 积分光环给玩家增加积分
    #npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    auraScoreRange = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreAura", 3)
    if len(auraScoreRange) != 2:
        return
    addValue = random.randint(auraScoreRange[0], auraScoreRange[1])
    #GameWorld.DebugLog("积分光环给玩家加积分: addValue=%s,auraScoreRange=%s" % (addValue, auraScoreRange), playerID)
    battleObj = GetBattlePlayerObj(playerID)
    battleObj.addPlayerScore(curPlayer, addValue, ScoreType_Aura)
    return
def __DoLogic_FB_Leave(tick):
    remaindTick = GetBFStepTime()[Time_Leave] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    if remaindTick > 0:
        return
    
    FBCommon.DoLogic_FBKickAllPlayer()
    GameWorldProcess.CloseFB(tick)
    FBCommon.SetFBStep(FB_Step_Over, tick)
    return
##处理副本中杀死玩家逻辑
def DoFBOnKill_Player(curPlayer, defender, tick):
    playerID = curPlayer.GetPlayerID()
    tagPlayerID = defender.GetPlayerID()
    faction = curPlayer.GetFaction()
    tagFaction = defender.GetFaction()
    curBattleObj = GetBattlePlayerObj(playerID)
    tagBattleObj = GetBattlePlayerObj(tagPlayerID)
    if not faction or not tagFaction:
        GameWorld.ErrLog("击杀玩家没有阵营! playerID=%s,faction=%s,tagPlayerID=%s,tagFaction=%s"
                         % (playerID, faction, tagPlayerID, tagFaction), playerID)
        return
    worldObj = GetBattleWorld()
    curFactionObj = GetBattleFactionObj(faction)
    tagFactionObj = GetBattleFactionObj(tagFaction)
    GameWorld.DebugLog("击杀玩家! playerID=%s,faction=%s,tagPlayerID=%s,tagFaction=%s"
                       % (playerID, faction, tagPlayerID, tagFaction), playerID)
    # 1. 处理玩家
    killPlayerScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldKill", 1)
    addPlayerScore = 0
    addPlayerScore += killPlayerScore
    #addPlayerScore += ... # 其他加分
    curBattleObj.addScore(worldObj, addPlayerScore)
    curBattleObj.addKillCount(worldObj, 1)
    tagBattleObj.addBeKilledCount(1)
    # 2. 处理阵营
    addFactionScore = 0
    addFactionScore += addPlayerScore # 阵营积分同步增加玩家得分
    # 击杀积分王,阵营积分额外增加
    for index, kingID in enumerate(tagFactionObj.scoreKingIDList):
        if kingID == tagPlayerID:
            killScoreKingScoreList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreKing", 3)
            if index < len(killScoreKingScoreList):
                kingScore = killScoreKingScoreList[index]
                addFactionScore += kingScore
                GameWorld.DebugLog("    对方是积分王,阵营额外获得积分:  index=%s,kingScore=%s" % (index, kingScore), playerID)
            killScoreKingNotifyList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreKing", 4)
            if index < len(killScoreKingNotifyList):
                msgMark = killScoreKingNotifyList[index]
                defMapID = defender.GetMapID()
                defPosX = defender.GetPosX()
                defPosY = defender.GetPosY()
                PlayerControl.FBNotify(msgMark, [faction, curPlayer.GetPlayerName(), tagFaction, defender.GetPlayerName(), defMapID, defPosX, defPosY])
            break
    #addFactionScore += ... # 其他加分
    curFactionObj.addScore(worldObj, addFactionScore)
    curFactionObj.addKillCount(worldObj, 1)
    tagFactionObj.addBeKilledCount(1)
    onBattleObjKillOtherBattleObj(curPlayer, defender, tick)
    return True
def refreshFactionPlayer(tick):
    ## 刷新阵营玩家相关
def onBattleObjKillOtherBattleObj(atkObj, defObj, tick):
    ## 战斗实例 击杀 其他阵营战斗实例,战斗实例包含(真实玩家、战斗机器人)
    if not atkObj or not defObj:
        return
    
    atkID = atkObj.GetID()
    defID = defObj.GetID()
    atkObjType = atkObj.GetGameObjType()
    defObjType = defObj.GetGameObjType()
    if atkObjType == defObjType and atkID == defID:
        return
    if atkObjType == IPY_GameWorld.gotPlayer:
        atkName = atkObj.GetName()
        atkFaction = atkObj.GetFaction()
    elif atkObjType == IPY_GameWorld.gotNPC:
        atkFaction = NPCCommon.GetFaction(atkObj)
        atkName = atkObj.GetName()
        atkName = atkName.decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())
    else:
        return
    if defObjType == IPY_GameWorld.gotPlayer:
        defFaction = defObj.GetFaction()
    elif defObjType == IPY_GameWorld.gotNPC:
        defFaction = NPCCommon.GetFaction(defObj)
    else:
        return
    if not atkFaction or not defFaction or atkFaction == defFaction:
        return
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    baseKillScore = 0 # 基础击杀分
    fbFightSeconds = (tick - GameWorld.GetGameFB().GetFBStepTick()) / 1000
    killPlayerScoreTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreBase", 3)
    for fbFightTimes, killScore in killPlayerScoreTimeList:
        if fbFightSeconds <= (fbFightTimes * 60):
            baseKillScore = killScore
            GameWorld.DebugLog("基础击杀分: baseKillScore=%s, %s分钟内" % (baseKillScore, fbFightTimes), fbPropertyID)
            break
    worldObj = GetBattleWorld()
    # 1. 处理玩家个人积分
    if atkObjType == IPY_GameWorld.gotPlayer:
        playerID = atkID
        playerScore = 0
        playerScore += baseKillScore
        GameWorld.DebugLog("玩家击杀对手! playerID=%s,atkFaction=%s,defObjType=%s,defID=%s"
                           % (playerID, atkFaction, defObjType, defID), fbPropertyID)
        if playerID in worldObj.callOpenPlayerInfo:
            callPlayerKillScoreEx = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreBase", 4)
            playerScore += callPlayerKillScoreEx
            GameWorld.DebugLog("    召集人额外击杀分: callPlayerKillScoreEx=%s" % callPlayerKillScoreEx, fbPropertyID)
        atkBattleObj = GetBattlePlayerObj(playerID)
        scoreTimes = 1 # 积分倍值
        if atkBattleObj.killPlayerAddScoreTimes and tick <= atkBattleObj.killPlayerScoreAwardEndTick:
            scoreTimes = atkBattleObj.killPlayerAddScoreTimes
        else:
            atkBattleObj.killPlayerAddScoreTimes = 0
            atkBattleObj.killPlayerScoreAwardEndTick = 0
        atkBattleObj.addKillCount(1)
        atkBattleObj.addPlayerScore(atkObj, playerScore, ScoreType_KillPlayer, scoreTimes)
    else:
        GameWorld.DebugLog("机器人击杀对手! atkID=%s,atkFaction=%s,defObjType=%s,defID=%s"
                           % (atkID, atkFaction, defObjType, defID), fbPropertyID)
        # 机器人不计算个人积分
    # 2. 处理阵营积分
    factionScore = 0
    atkFactionObj = GetBattleFactionObj(atkFaction)
    defFactionObj = GetBattleFactionObj(defFaction)
    if atkObjType == IPY_GameWorld.gotNPC:
        factionScore += baseKillScore # 机器人没有个人分,所以击杀基础分直接算到阵营上
    # 击杀积分王,阵营积分额外增加
    if defObjType == IPY_GameWorld.gotPlayer:
        for index, kingID in enumerate(defFactionObj.scoreKingIDList):
            if kingID == defID:
                killScoreKingScoreList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreKing", 3)
                kingScore = killScoreKingScoreList[index] if index < len(killScoreKingScoreList) else 0
                factionScore += kingScore
                GameWorld.DebugLog("    对方是积分王,阵营额外获得积分:  index=%s,kingScore=%s" % (index, kingScore), fbPropertyID)
                killScoreKingNotifyList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreKing", 4)
                if index < len(killScoreKingNotifyList):
                    msgMark = killScoreKingNotifyList[index]
                    defMapID = GameWorld.GetMap().GetMapID()
                    defPosX = defObj.GetPosX()
                    defPosY = defObj.GetPosY()
                    PlayerControl.FBNotify(msgMark, [atkFaction, atkName, defFaction, defObj.GetPlayerName(), kingScore, defMapID, defPosX, defPosY])
                # 玩家击败积分王
                if atkObjType == IPY_GameWorld.gotPlayer and index == 0:
                    atkBattleObj.killScoreKing = 1
                break
    else:
        pass
    #factionScore += ... # 其他加分
    atkFactionObj.addFactionScore(factionScore)
    return
def DoFB_NPCDead(curNPC):
    gameFB = GameWorld.GetGameFB()
    if gameFB.GetFBStep() != FB_Step_Fighting:
        return
    faction = NPCCommon.GetFaction(curNPC)
    if not faction:
        return
    if curNPC.GetType() == ChConfig.ntRobot:
        objID = curNPC.GetID()
        factionObj = GetBattleFactionObj(faction)
        if objID in factionObj.robotObjIDList:
            factionObj.robotObjIDList.remove(objID)
            GameWorld.DebugLog("机器人被击杀,阵营机器人ID移除: faction=%s,objID=%s,robotObjIDList=%s"
                               % (faction, objID, factionObj.robotObjIDList), GameWorld.GetGameWorld().GetPropertyID())
    return
def refreshCrossBattlefield(tick, checkVictory=True):
    ## 刷新战场相关
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    # 定时占领资源积分奖励
    awardScorePerSecond = IpyGameDataPY.GetFuncCfg("CrossBattlefieldCrystal", 3)
    worldObj = GetBattleWorld()
    for npcID, ownerFaction in worldObj.crystalFactionInfo.items():
        lastAwardTick = worldObj.crystalAwardTick.get(npcID, tick)
        awardSeconds = (tick - lastAwardTick) / 1000.0
        awardFactionScore = int(awardScorePerSecond * round(awardSeconds))
        worldObj.crystalAwardTick[npcID] = tick
        if awardFactionScore <= 0:
            continue
        factionObj = GetBattleFactionObj(ownerFaction)
        if factionObj.crystalScorePlusRate and tick <= factionObj.crystalScorePlusEndTick:
            awardFactionScore = int(awardFactionScore * (1 + int(factionObj.crystalScorePlusRate / 10000.0)))
        else:
            factionObj.crystalScorePlusRate = 0
            factionObj.crystalScorePlusEndTick = 0
        GameWorld.DebugLog("定时资源积分: npcID=%s,ownerFaction=%s,awardSeconds=%s,awardFactionScore=%s"
                           % (npcID, ownerFaction, awardSeconds, awardFactionScore), fbPropertyID)
        factionObj.addFactionScore(awardFactionScore, False)
    # 参与玩家处理
    scoreKingScoreMin = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreKing", 1)
    scoreKingBuffIDList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldScoreKing", 2)
    scoreKingCount = len(scoreKingBuffIDList)
    
    factionSafeAreaRandPosList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldFB", 3) # 营地坐标
    robotNPCIDList = IpyGameDataPY.GetFuncEvalCfg("CrossBattlefieldRobot", 1)
    battleObjBaseCount = IpyGameDataPY.GetFuncCfg("CrossBattlefieldRobot", 2) # 阵营保底战斗人员数,在线+机器人
    copyMapMgr = GameWorld.GetMapCopyPlayerManager()
    copyPlayerCount = copyMapMgr.GetPlayerCount()
    for faction in [ShareDefine.CampType_Justice, ShareDefine.CampType_Evil]:
        factionObj = GetBattleFactionObj(faction)
        
        # 机器人,有真实玩家时才处理刷出机器人
        if copyPlayerCount and len(factionObj.onlinePlayerIDList) + len(factionObj.robotObjIDList) < battleObjBaseCount and faction <= len(robotNPCIDList):
            robotNPCID = robotNPCIDList[faction - 1]
            posInfo = getRandFactionRebornPos(faction)
            if posInfo:
                robotNPC = NPCCommon.SummonMapNpc(robotNPCID, posInfo[0], posInfo[1])
                if robotNPC:
                    robotNPC.SetIsNeedProcess(True)
                    robotID = robotNPC.GetID()
                    if robotID not in factionObj.robotObjIDList:
                        factionObj.robotObjIDList.append(robotID)
                        GameWorld.DebugLog("新增阵营机器人: faction=%s,robotNPCID=%s,robotID=%s,posInfo=%s,robotObjIDList=%s"
                                           % (faction, robotNPCID, robotID, posInfo, factionObj.robotObjIDList), fbPropertyID)
        befKingIDList = factionObj.scoreKingIDList
        
        factionObj.battlePlayerSortList = factionObj.factionPlayerDict.values()
        factionObj.battlePlayerSortList.sort(key=operator.attrgetter("score", "scoreSortTime"), reverse=True)
        
        safePosX, safePosY, safeRadius = factionSafeAreaRandPosList[faction - 1]
        aftKingIDList = []
        aftKingObjList = []
        for batObj in factionObj.battlePlayerSortList:
            playerID = batObj.ID
            playerID = batObj.playerID
            curPlayer = copyMapMgr.FindPlayerByID(playerID)
            if not curPlayer:
                continue
            
            # 累计参与战斗时长
            if batObj.onlineCalcTick:
                batObj.onlineTimes += max(0, tick - batObj.onlineCalcTick)
                batObj.onlineCalcTick = tick
                
            if batObj.score < scoreKingScoreMin:
                continue
            if len(aftKingIDList) < scoreKingCount:
            # 回营地
            if GameWorld.GetDist(curPlayer.GetPosX(), curPlayer.GetPosY(), safePosX, safePosY) <= safeRadius:
                if playerID not in factionObj.homePlayerIDList:
                    factionObj.homePlayerIDList.append(playerID)
            # 有资格的积分王列表
            if batObj.score >= scoreKingScoreMin and len(aftKingIDList) < scoreKingCount:
                aftKingIDList.append(playerID)
                aftKingObjList.append([curPlayer, batObj])
                
        if befKingIDList == aftKingIDList:
            #GameWorld.DebugLog("    阵营积分王不变: faction=%s,befKingIDList=%s,aftKingIDList=%s" % (faction, befKingIDList, aftKingIDList))
            #GameWorld.DebugLog("    阵营积分王不变: faction=%s,befKingIDList=%s,aftKingIDList=%s" % (faction, befKingIDList, aftKingIDList), fbPropertyID)
            continue
        
        GameWorld.DebugLog("    阵营积分王变更: faction=%s,befKingIDList=%s,aftKingIDList=%s" % (faction, befKingIDList, aftKingIDList))
        GameWorld.DebugLog("    阵营积分王变更: faction=%s,befKingIDList=%s,aftKingIDList=%s" % (faction, befKingIDList, aftKingIDList), fbPropertyID)
        
        # 更新buff
        for index, objInfo in enumerate(aftKingObjList):
@@ -728,27 +1467,34 @@
            if playerID in befKingIDList:
                befIndex = befKingIDList.index(playerID)
                if index == befIndex:
                    GameWorld.DebugLog("        积分王名次不变,不需要变更buff! index=%s" % index, playerID)
                    GameWorld.DebugLog("        积分王名次不变,不需要变更buff! index=%s,playerID=%s" % (index, playerID), fbPropertyID)
                    continue
                delBuffID = scoreKingBuffIDList[befIndex] if befIndex < len(scoreKingBuffIDList) else 0
                if delBuffID:
                    GameWorld.DebugLog("        积分王名次变更! 删除旧buff! befIndex=%s,delBuffID=%s" % (befIndex, delBuffID), playerID)
                    GameWorld.DebugLog("        积分王名次变更! 删除旧buff! befIndex=%s,delBuffID=%s,playerID=%s" % (befIndex, delBuffID, playerID), fbPropertyID)
                    BuffSkill.DelBuffBySkillID(curPlayer, delBuffID, tick)
                    
            if addBuffID:
                GameWorld.DebugLog("        积分王名次变更! 添加新buff! index=%s,addBuffID=%s" % (index, addBuffID), playerID)
                GameWorld.DebugLog("        积分王名次变更! 添加新buff! index=%s,addBuffID=%s,playerID=%s" % (index, addBuffID, playerID), fbPropertyID)
                SkillCommon.AddBuffBySkillType_NoRefurbish(curPlayer, addBuffID, tick)
                
        for befIndex, playerID in enumerate(befKingIDList):
            if playerID in aftKingIDList:
                continue
            curPlayer = copyMapMgr.FindPlayerByID(playerID)
            if not curPlayer:
                continue
            delBuffID = scoreKingBuffIDList[befIndex] if befIndex < len(scoreKingBuffIDList) else 0
            if delBuffID:
                GameWorld.DebugLog("        积分王被挤掉! 删除旧buff! befIndex=%s,delBuffID=%s" % (befIndex, delBuffID), playerID)
                GameWorld.DebugLog("        积分王被挤掉! 删除旧buff! befIndex=%s,delBuffID=%s,playerID=%s" % (befIndex, delBuffID, playerID), fbPropertyID)
                BuffSkill.DelBuffBySkillID(curPlayer, delBuffID, tick)
                
        factionObj.scoreKingIDList = aftKingIDList
    if not checkVictory:
        return
    checkBattleOver(tick)
    return
def DoOver(winnerFaction, tick):
@@ -757,7 +1503,8 @@
    funcLineID = FBCommon.GetCrossDynamicLineMapFuncLineID()
    GameWorld.Log("跨服战场结算! zoneID=%s,funcLineID=%s,winnerFaction=%s" % (zoneID, funcLineID, winnerFaction), fbPropertyID)
    
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshFactionPlayer) # 结算前强刷一次
    refreshCrossBattlefield(tick, False) # 结算前强刷一次
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)
    
    #awardOnlineTimes = IpyGameDataPY.GetFuncCfg("CrossBattlefieldAward", 1) # 结算奖励需参与活动时长,秒钟
    
@@ -766,28 +1513,28 @@
    leaveTime = GetBFStepTime()[Time_Leave] * 1000
    copyMapMgr = GameWorld.GetMapCopyPlayerManager()
    
    superItemPlayerID = worldObj.superItemPlayerID
    superItemPlayerName = worldObj.superItemPlayerName
    # 没人中奖则随机给其中一位在线的玩家
    if not superItemPlayerID:
        onlinePlayerIDList = []
        for index in xrange(copyMapMgr.GetPlayerCount()):
            curPlayer = copyMapMgr.GetPlayerByIndex(index)
            playerID = curPlayer.GetPlayerID()
            if not playerID:
                continue
            onlinePlayerIDList.append(playerID)
        if onlinePlayerIDList:
            superItemPlayerID = random.choice(onlinePlayerIDList)
            superPlayerObj = GetBattlePlayerObj(superItemPlayerID)
            superItemPlayerName = superPlayerObj.name
            worldObj.superItemPlayerID = superItemPlayerID
            worldObj.superItemPlayerName = superItemPlayerName
            GameWorld.Log("没人中大奖,则随机其中一位在线玩家! superItemPlayerID=%s,onlinePlayerIDList=%s"
                          % (superItemPlayerID, onlinePlayerIDList), fbPropertyID)
    GameWorld.Log("大奖获奖信息: superItemInfo=%s,superItemPlayerID=%s" % (worldObj.superItemInfo, superItemPlayerID), fbPropertyID)
    superItemPlayerIDList = []
    superWeight = []
    for index in xrange(copyMapMgr.GetPlayerCount()):
        curPlayer = copyMapMgr.GetPlayerByIndex(index)
        playerID = curPlayer.GetPlayerID()
        if not playerID:
            continue
        battleObj = GetBattlePlayerObj(playerID)
        if not battleObj.superItemContribution:
            continue
        superWeight.append([battleObj.superItemContribution, playerID])
    # 这是最终结算额外再开一次的大奖,仅限结算时在线的所有玩家
    finalSuperItemPlayerName = ""
    finalSuperItemPlayerID = GameWorld.GetResultByWeightList(superWeight, 0)
    GameWorld.Log("最终结算额外随机大奖在线玩家! superItemInfo=%s,finalSuperItemPlayerID=%s,superWeight=%s"
                  % (worldObj.superItemInfo, finalSuperItemPlayerID, superWeight), fbPropertyID)
    if finalSuperItemPlayerID:
        superPlayerObj = GetBattlePlayerObj(finalSuperItemPlayerID)
        superPlayerObj.superItemAwardCnt += 1
        finalSuperItemPlayerName = superPlayerObj.name
        superItemPlayerIDList.append(finalSuperItemPlayerID)
    hmNum = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_DailyActionState % ShareDefine.DailyActionID_CrossBattlefield)
    hmCallTeamInfo = PyGameData.g_crossBattlefieldCallTeamInfo.get(zoneID, {})
    callTeamInfo = hmCallTeamInfo.get(hmNum, {})
@@ -800,10 +1547,13 @@
    for faction in [ShareDefine.CampType_Justice, ShareDefine.CampType_Evil]:
        factionObj = GetBattleFactionObj(faction)
        factionScore = factionObj.score
        isWinner = (faction == winnerFaction)
        isWinner = 1 if faction == winnerFaction else 0
        scoreKingIDList = factionObj.scoreKingIDList
        GameWorld.Log("结算阵营! faction=%s,factionScore=%s,isWinner=%s,playerCount=%s,onlineFightPowerTotal=%s,onlinePlayerIDList=%s,scoreKingIDList=%s"
                      % (faction, factionScore, isWinner, len(factionObj.battlePlayerSortList), factionObj.onlineFightPowerTotal, factionObj.onlinePlayerIDList, scoreKingIDList), fbPropertyID)
        factionSuperItemPlayerID = factionObj.superItemPlayerID
        GameWorld.Log("结算阵营! faction=%s,factionScore=%s,isWinner=%s,playerCount=%s,onlineFightPowerTotal=%s,onlinePlayerIDList=%s,scoreKingIDList=%s,factionSuperItemPlayerID=%s"
                      % (faction, factionScore, isWinner, len(factionObj.battlePlayerSortList), factionObj.onlineFightPowerTotal, factionObj.onlinePlayerIDList, scoreKingIDList, factionSuperItemPlayerID), fbPropertyID)
        if factionSuperItemPlayerID:
            superItemPlayerIDList.append(factionSuperItemPlayerID)
        if isWinner and scoreKingIDList:
            scoreKingID = scoreKingIDList[0]
            scoreKingObj = GetBattlePlayerObj(scoreKingID)
@@ -813,9 +1563,9 @@
        for battleObj in factionObj.battlePlayerSortList[:20]:
            rankPlayerList.append({"Name":battleObj.name, "Job":battleObj.job, "Score":battleObj.score})
            
        overDict = {"rankPlayerList":rankPlayerList, "faction":faction, "superItemPlayerName":superItemPlayerName, "scoreKingName":scoreKingName}
        overDict = {"rankPlayerList":rankPlayerList, "faction":faction, "superItemPlayerName":finalSuperItemPlayerName, "scoreKingName":scoreKingName}
        for rank, battleObj in enumerate(factionObj.battlePlayerSortList, 1):
            playerID = battleObj.ID
            playerID = battleObj.playerID
            score = battleObj.score
            job = battleObj.job
            realmLV = battleObj.realmLV
@@ -824,6 +1574,7 @@
            highScoreWeekTotal = battleObj.highScoreWeekTotal
            enterCountWeek = battleObj.enterCountWeek
            onlineTimes = battleObj.onlineTimes / 1000
            GameWorld.Log("     rank=%s,playerID=%s,score=%s,fightPower=%s,onlineTimes=%s,accID=%s" 
                          % (rank, playerID, score, battleObj.fightPower, onlineTimes, battleObj.accID), fbPropertyID)
            
@@ -832,8 +1583,18 @@
            #    GameWorld.Log("    活动时长不足,不给奖励! faction=%s,playerID=%s,isWinner=%s" % (faction, playerID, isWinner), fbPropertyID)
            #    continue
            
            isCallEnter = 1 if playerID in allCallPlayerIDList else 0 # 是否召集进入的
            playerInfo = [faction, rank, playerID, job, realmLV, name, score, highScoreToday, highScoreWeekTotal, enterCountWeek, isCallEnter]
            isCallOpen = 1 if playerID in worldObj.callOpenPlayerInfo else 0 # 是否召集进入的
            isCalled = 1 if (playerID in allCallPlayerIDList and not isCallOpen) else 0 # 是否被召集的
            killCnt, ckillCntInfo, killBossCnt, killScoreKing, killGuardCnt, auraScore, superItemAwardCnt, \
                factionBuffCollCnt, personBuffCollCnt, crystalCollCnt, wallCollCnt = \
                battleObj.killCount, battleObj.ckillCntInfo, battleObj.killBossCnt, battleObj.killScoreKing, battleObj.killGuardCnt, \
                battleObj.auraScore, battleObj.superItemAwardCnt, battleObj.factionBuffCollCnt, battleObj.personBuffCollCnt, \
                battleObj.crystalCollCnt, battleObj.wallCollCnt
            playerInfo = [playerID, job, realmLV, name,
                          isWinner, faction, rank, score, highScoreToday, highScoreWeekTotal, enterCountWeek,
                          isCallOpen, isCalled, killCnt, ckillCntInfo, killBossCnt, killScoreKing, killGuardCnt, auraScore, superItemAwardCnt,
                          factionBuffCollCnt, personBuffCollCnt, crystalCollCnt, wallCollCnt]
            battlePlayerList.append(playerInfo)
            
            player = copyMapMgr.FindPlayerByID(playerID)
@@ -849,28 +1610,391 @@
            
    # 同步GameServer 比赛结果
    superItemInfo = worldObj.superItemInfo
    msgInfo = str([fbPropertyID, zoneID, funcLineID, winnerFaction, superItemInfo, superItemPlayerID, superItemPlayerName, scoreKingID, scoreKingName, battlePlayerList])
    msgInfo = str([fbPropertyID, zoneID, funcLineID, winnerFaction, superItemInfo, finalSuperItemPlayerID, finalSuperItemPlayerName, superItemPlayerIDList, scoreKingID, scoreKingName, battlePlayerList])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CrossBattlefieldOver", msgInfo, len(msgInfo))
    
    FBCommon.SetFBStep(FB_Step_LeaveTime, tick)
    return
## 执行副本杀怪逻辑
def DoFB_Player_KillNPC(curPlayer, curNPC, tick):
    #curNPC.SetDict(ChConfig.Def_NPC_Dict_Faction, 0)
##是否可以夺旗
def OnCanCollect(curPlayer, curNPC, tick):
    gameFB = GameWorld.GetGameFB()
    fbStep = gameFB.GetFBStep()
    # 非战斗阶段不可采集
    if fbStep != FB_Step_Fighting:
        PlayerControl.NotifyCode(curPlayer, "NotFightStepCanNotCollect")
        return False
    npcID = curNPC.GetNPCID()
    GameWorld.DebugLog("OnCanCollect npcID=%s" % npcID, curPlayer.GetPlayerID())
    if npcID in GetCrystalNPCIDList():
        # 已获得战旗的战盟不可采集
        worldObj = GetBattleWorld()
        ownerFaction = worldObj.crystalFactionInfo.get(npcID)
        faction = curPlayer.GetFaction()
        if ownerFaction == faction:
            PlayerControl.NotifyCode(curPlayer, "CrossBattlefieldCollectOwnerLimit")
            return False
    # 积分墙
    elif npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 1):
        worldObj = GetBattleWorld()
        collectCD = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 2) * 1000
        passTick = tick - worldObj.lastWallCollOKTick
        #GameWorld.DebugLog("lastWallCollOKTick=%s,tick=%s,passTick=%s,collectCD=%s" % (worldObj.lastWallCollOKTick, tick, passTick, collectCD))
        if passTick <= collectCD:
            waitSeconds = int(math.ceil((collectCD - passTick) / 1000.0))
            PlayerControl.NotifyCode(curPlayer, "CrossBattlefieldWallTimeLimit", [waitSeconds])
            return False
    return True
##玩家收集成功(塔, 旗)
def OnCollectOK(curPlayer, npcID, tick):
    GameWorld.DebugLog("OnCollectOK npcID=%s" % npcID, curPlayer.GetPlayerID())
    tagObj = curPlayer.GetActionObj()
    if not tagObj:
        return
    if tagObj.GetGameObjType() != IPY_GameWorld.gotNPC:
        return
    curNPC = GameWorld.GetNPCManager().GetNPCByIndex(tagObj.GetIndex())
    AICommon.ClearPlayerPreparing(curNPC, curPlayer)
    npcID = curNPC.GetNPCID()
    # 水晶
    if npcID in GetCrystalNPCIDList():
        __OnCollectOK_Crystal(curPlayer, curNPC, tick)
    # 个人buff
    elif npcID in GetPersonBuffIDList():
        __OnCollectOK_PersonBuff(curPlayer, curNPC, tick)
    # 阵营buff
    elif npcID in GetFactionBuffIDList():
        __OnCollectOK_FactionBuff(curPlayer, curNPC, tick)
    # 积分墙
    elif npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 1):
        __OnCollectOK_EventWall(curPlayer, curNPC, tick)
    return
def __OnCollectOK_Crystal(curPlayer, curNPC, tick):
    ## 采集水晶资源建筑
    objID = curNPC.GetID()
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    battleObj = GetBattlePlayerObj(playerID)
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    if not battleObj:
        return
    faction = battleObj.faction
    worldObj = GetBattleWorld()
    lastOwnerFaction = worldObj.crystalFactionInfo.get(npcID)
    if lastOwnerFaction == faction:
        return
    # 更新归属信息
    worldObj.crystalFactionInfo[npcID] = faction
    worldObj.crystalAwardTick[npcID] = tick
    battleObj.crystalCollCnt += 1
    GameWorld.Log("玩家占领水晶: objID=%s,npcID=%s,lastOwnerFaction=%s,playerID=%s,faction=%s"
                  % (objID, npcID, lastOwnerFaction, playerID, faction), fbPropertyID)
    addScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldCrystal", 2)
    battleObj.addPlayerScore(curPlayer, addScore, ScoreType_CollectCrystal)
    # 占领广播给自己阵营、对方阵营 不同内容
    PlayerControl.FBFactionNotify(curPlayer.GetFaction(), "CrossBattlefieldOccupiedSelf", [battleObj.name],
                                  "CrossBattlefieldOccupiedOther", [battleObj.name])
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def __OnCollectOK_PersonBuff(curPlayer, curNPC, tick):
    npcID = curNPC.GetNPCID()
    worldObj = GetBattleWorld()
    if worldObj.personBuffCount > 0:
        worldObj.personBuffCount = worldObj.personBuffCount - 1
    if not worldObj.personBuffCalcTick:
        worldObj.personBuffCalcTick = tick
    # 增加buff效果
    addSkill = curNPC.GetSkillManager().GetSkillByIndex(0)
    addSkillID = addSkill.GetSkillID() if addSkill else 0
    playerID = curPlayer.GetPlayerID()
    GameWorld.DebugLog("采集个人buff: npcID=%s,addSkillID=%s,personBuffCount=%s"
                       % (npcID, addSkillID, worldObj.personBuffCount), playerID)
    battleObj = GetBattlePlayerObj(playerID)
    battleObj.personBuffCollCnt += 1
    if addSkill:
        SkillShell.__DoLogic_AddBuff(curPlayer, curPlayer, addSkill, False, tick, addForce=True)
    # 攻击翻x倍                            30908107
    # 击杀玩家积分翻x倍        30908108
    # 无敌                                        30908109
    if npcID == 30908108:
        buffSkill = GameWorld.GetGameData().GetSkillBySkillID(addSkillID)
        if buffSkill:
            buffTime = buffSkill.GetLastTime()
            battleObj.killPlayerAddScoreTimes = buffSkill.GetEffect(0).GetEffectValue(0)
            battleObj.killPlayerScoreAwardEndTick = tick + buffTime
            GameWorld.DebugLog("获得击杀玩家多倍积分福利: killPlayerAddScoreTimes=%s,buffTime=%s"
                               % (battleObj.killPlayerAddScoreTimes, buffTime), playerID)
    NPCCommon.SetDeadEx(curNPC)
    return
def __OnCollectOK_FactionBuff(curPlayer, curNPC, tick):
    npcID = curNPC.GetNPCID()
    worldObj = GetBattleWorld()
    if worldObj.factionBuffNPCInfo and npcID == worldObj.factionBuffNPCInfo[0]:
        worldObj.factionBuffNPCInfo = []
    worldObj.factionBuffCalcTick = tick
    # 增加buff效果
    addSkill = curNPC.GetSkillManager().GetSkillByIndex(0)
    addSkillID = addSkill.GetSkillID() if addSkill else 0
    if not addSkillID:
        return
    buffSkill = GameWorld.GetGameData().GetSkillBySkillID(addSkillID)
    if not buffSkill:
        return
    playerID = curPlayer.GetPlayerID()
    addScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldFactionBuff", 4)
    battleObj = GetBattlePlayerObj(playerID)
    battleObj.factionBuffCollCnt += 1
    battleObj.addPlayerScore(curPlayer, addScore, ScoreType_CollectFactionBuff)
    faction = battleObj.faction
    tagFaction = ShareDefine.CampType_Justice if faction == ShareDefine.CampType_Evil else ShareDefine.CampType_Evil
    # 黑夜降临: 敌对玩家每x秒掉血y%,持续xx秒                        30908110
    # 天道威压: 敌对玩家攻击降低x%,持续xx秒                           30908111
    # 普度众生: 我方建筑获取资源速度提升x%,持续xx秒       30908112
    # 洞天福地: 我方玩家每x秒回血y%,持续xx秒                        30908113
    gainBuffFaction = faction # 获得buff的阵营
    if npcID in [30908110, 30908111]:
        gainBuffFaction = tagFaction
    GameWorld.DebugLog("采集阵营buff: npcID=%s,addSkillID=%s,faction=%s,tagFaction=%s,gainBuffFaction=%s"
                       % (npcID, addSkillID, faction, tagFaction, gainBuffFaction), playerID)
    paramList = [faction, battleObj.name, npcID, gainBuffFaction]
    PlayerControl.FBNotify("CrossBattlefieldBuffOK_%s" % npcID, paramList)
    gainBuffFactionObj = GetBattleFactionObj(gainBuffFaction)
    doAddFactionPlayerBuff(curPlayer, gainBuffFactionObj, buffSkill, tick)
    buffTime = buffSkill.GetLastTime()
    endTime = int(time.time()) + int(buffTime / 1000)
    gainBuffFactionObj.factionBuffInfo = [addSkillID, endTime]
    if npcID == 30908112:
        gainBuffFactionObj.crystalScorePlusRate = buffSkill.GetEffect(0).GetEffectValue(0)
        gainBuffFactionObj.crystalScorePlusEndTick = tick + buffTime
    FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    NPCCommon.SetDeadEx(curNPC)
    return
def doAddFactionPlayerBuff(curPlayer, factionObj, buffSkill, tick):
    ## 给某个阵营在线玩家添加buff
    copyMapMgr = GameWorld.GetMapCopyPlayerManager()
    for playerID in factionObj.onlinePlayerIDList:
        player = copyMapMgr.FindPlayerByID(playerID)
        if not player:
            continue
        SkillShell.__DoLogic_AddBuff(curPlayer, player, buffSkill, False, tick, addForce=True)
    return
def __OnCollectOK_EventWall(curPlayer, curNPC, tick):
    ## 采集积分墙
    npcID = curNPC.GetNPCID()
    ChNPC.OnCollectEnd(curPlayer, curNPC)
    worldObj = GetBattleWorld()
    worldObj.lastWallCollOKTick = tick
    worldObj.eventNPCHP = GameObj.GetHP(curNPC)
    playerID = curPlayer.GetPlayerID()
    faction = curPlayer.GetFaction()
    battleObj = GetBattlePlayerObj(playerID)
    battleObj.wallCollCnt += 1
    factionObj = GetBattleFactionObj(faction)
    addValue = IpyGameDataPY.GetFuncCfg("CrossBattlefieldScoreWall", 3)
    GameWorld.Log("玩家采集积分墙: npcID=%s,faction=%s,eventNPCHP=%s,tick=%s" % (npcID, faction, worldObj.eventNPCHP, tick), playerID)
    factionObj.addFactionScore(addValue)
    PlayerControl.FBNotify("CrossBattlefieldWallCollectOK", [faction, curPlayer.GetPlayerName(), npcID, addValue])
    if worldObj.eventNPCHP <= 0:
        worldObj.setEventEnd(tick)
    else:
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def DoFBOnNPCKill_Player(curNPC, curPlayer, tick):
    ## 执行副本NPC击杀玩家
    npcID = curNPC.GetNPCID()
    npcFaction = NPCCommon.GetFaction(curNPC)
    if npcFaction:
        __OnPlayerKillOtherFactionRobot(curPlayer, npcFaction, tick)
        if npcID in GetGuardNPCIDList():
            __OnGuardKillOtherPlayer(curNPC, curPlayer, tick)
        elif npcID in GetRobotNPCIDList():
            onBattleObjKillOtherBattleObj(curNPC, curPlayer, tick)
    else:
        __OnPlayerKillNeutralNPC(curPlayer, curNPC, tick)
        pass
    return
def __OnPlayerKillOtherFactionRobot(curPlayer, npcFaction, tick):
    ## 玩家击杀其他阵营机器人玩家
def DoFB_Player_KillNPC(curPlayer, curNPC, tick):
    ## 执行副本杀怪逻辑
    npcID = curNPC.GetNPCID()
    npcFaction = NPCCommon.GetFaction(curNPC)
    GameWorld.DebugLog("DoFB_Player_KillNPC %s kill %s" % (curPlayer.GetID(), npcID))
    if npcFaction:
        if npcID in GetGuardNPCIDList():
            __OnPlayerKillOtherFactionGurad(curPlayer, curNPC, tick)
        elif npcID in GetRobotNPCIDList():
            onBattleObjKillOtherBattleObj(curPlayer, curNPC, tick)
    # boss
    elif npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 1):
        __OnPlayerKillEventBoss(curPlayer, curNPC, tick)
    return
def __OnPlayerKillNeutralNPC(curPlayer, curNPC, tick):
    ## 玩家击杀中立怪物
def DoFB_Npc_KillNPC(attacker, curNPC, tick):
    if attacker.GetType() == ChConfig.ntRobot and curNPC.GetType() == ChConfig.ntRobot:
        onBattleObjKillOtherBattleObj(attacker, curNPC, tick)
    return
def __OnPlayerKillOtherFactionGurad(curPlayer, curNPC, tick):
    ## 玩家击杀其他阵营守卫
    playerID = curPlayer.GetPlayerID()
    guardFaction = NPCCommon.GetFaction(curNPC)
    tagFaction = curPlayer.GetFaction()
    if guardFaction == tagFaction:
        return
    battleObj = GetBattlePlayerObj(playerID)
    battleObj.killGuardCnt += 1
    PlayerControl.FBFactionNotify(curPlayer.GetFaction(), "CrossBattlefieldKillGuardSelf", [battleObj.name],
                                  "CrossBattlefieldKillGuardOther", [battleObj.name])
    factionObj = GetBattleFactionObj(battleObj.faction)
    killGuardScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldGuard", 3)
    factionObj.addFactionScore(killGuardScore)
    return
def __OnGuardKillOtherPlayer(curNPC, tagPlayer, tick):
    ## 守卫击杀玩家
    npcID = curNPC.GetNPCID()
    guardFaction = NPCCommon.GetFaction(curNPC)
    tagFaction = tagPlayer.GetFaction()
    tagPlayerID = tagPlayer.GetPlayerID()
    ownerPlayerID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_SummonMapNPCPlayerID)
    if not ownerPlayerID or guardFaction == tagFaction:
        return
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    copyMapMgr = GameWorld.GetMapCopyPlayerManager()
    ownerPlayer = copyMapMgr.FindPlayerByID(ownerPlayerID)
    guardKillPlayerScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldGuard", 4)
    GameWorld.DebugLog("守卫击杀玩家: npcID=%s,guardFaction=%s,ownerPlayerID=%s,tagPlayerID=%s"
                       % (npcID, guardFaction, ownerPlayerID, tagPlayerID), fbPropertyID)
    battleObj = GetBattlePlayerObj(ownerPlayerID)
    battleObj.addKillCount(1)
    battleObj.addPlayerScore(ownerPlayer, guardKillPlayerScore, ScoreType_GuardKillPlayer)
    return
def __OnPlayerKillEventBoss(curPlayer, curNPC, tick):
    ## 玩家击杀事件Boss
    npcID = curNPC.GetNPCID()
    killerPlayerID = curPlayer.GetPlayerID()
    killerFaction = curPlayer.GetFaction()
    fbPropertyID = GameWorld.GetGameWorld().GetPropertyID()
    jFactionObj = GetBattleFactionObj(ShareDefine.CampType_Justice)
    eFactionObj = GetBattleFactionObj(ShareDefine.CampType_Evil)
    GameWorld.Log("击杀天道之眼Boss: npcID=%s,killerPlayerID=%s,killerFaction=%s"
                  % (npcID, killerPlayerID, killerFaction), fbPropertyID)
    GameWorld.Log("    faction=%s,hurtBossValue=%s" % (jFactionObj.faction, jFactionObj.hurtBossValue), fbPropertyID)
    GameWorld.Log("    faction=%s,hurtBossValue=%s" % (eFactionObj.faction, eFactionObj.hurtBossValue), fbPropertyID)
    ownerFaction = None
    if jFactionObj.hurtBossValue > eFactionObj.hurtBossValue:
        ownerFaction = jFactionObj
    elif jFactionObj.hurtBossValue < eFactionObj.hurtBossValue:
        ownerFaction = eFactionObj
    else:
        # 伤害相同时,归属最后一击玩家所属阵营
        ownerFaction = jFactionObj if killerFaction == jFactionObj.faction else eFactionObj
        ownerFaction.hurtBossValue += 100 # 随机归属方额外增加伤害
        GameWorld.Log("    伤害相同,归属最后一击玩家阵营! ", fbPropertyID)
    GameWorld.Log("    Boss归属阵营: faction=%s" % ownerFaction.faction, fbPropertyID)
    ownerFactionScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 3)
    ownerFaction.addFactionScore(ownerFactionScore, False)
    hurtPlayerScore = IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 2)
    for factionObj in [jFactionObj, eFactionObj]:
        for playerID in factionObj.hurtBossPlayerDict.keys():
            battleObj = GetBattlePlayerObj(playerID)
            if factionObj.faction == ownerFaction.faction:
                battleObj.killBossCnt += 1
            battleObj.addPlayerScore(curPlayer, hurtPlayerScore, ScoreType_HurtBoss, isCheckVictory=False)
    PlayerControl.FBNotify("CrossBattlefieldBossKilled", [npcID, ownerFaction.faction, ownerFactionScore, hurtPlayerScore])
    worldObj = GetBattleWorld()
    worldObj.setEventEnd(tick)
    if not checkBattleOver(tick):
        FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0, refreshCrossBattlefield)
    return
def GetFBPlayerHurtNPCMultiValue(curPlayer, curNPC):
    ## 玩家对NPC造成伤害倍值,默认1
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    worldObj = GetBattleWorld()
    # 召集开启的玩家  对 Boss的伤害倍值
    if playerID in worldObj.callOpenPlayerInfo and npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 1):
        return IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 4)
    return 1
def DoFB_Player_HurtNPC(curPlayer, curNPC, hurtHP):
    ## 玩家对NPC造成伤害
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    # Boss
    if npcID == IpyGameDataPY.GetFuncCfg("CrossBattlefieldBoss", 1):
        worldObj = GetBattleWorld()
        worldObj.eventNPCHP = GameObj.GetHP(curNPC)
        faction = curPlayer.GetFaction()
        factionObj = GetBattleFactionObj(faction)
        # 累加伤害
        factionObj.hurtBossValue = factionObj.hurtBossValue + hurtHP
        factionObj.hurtBossPlayerDict[playerID] = factionObj.hurtBossPlayerDict.get(playerID, 0) + hurtHP
        GameWorld.DebugLog("玩家攻击boss: faction=%s,hurtHP=%s,factionHurtBossValue=%s,playerHurtBossValue=%s,npcHP=%s"
                           % (faction, hurtHP, factionObj.hurtBossValue, factionObj.hurtBossPlayerDict[playerID], GameObj.GetHP(curNPC)), playerID)
    return
## 检查是否可攻击, 主判定不可攻击的情况,其他逻辑由外层决定
@@ -878,13 +2002,40 @@
    gameFB = GameWorld.GetGameFB()
    if gameFB.GetFBStep() != FB_Step_Fighting:
        return False
    atkObjType = attacker.GetGameObjType()
    defObjType = defender.GetGameObjType()
    if atkObjType == IPY_GameWorld.gotNPC and defObjType == IPY_GameWorld.gotNPC:
        if NPCCommon.GetFaction(attacker) == NPCCommon.GetFaction(defender):
            return False
        if attacker.GetType() == ChConfig.ntRobot and defender.GetType() == ChConfig.ntRobot:
            #GameWorld.DebugLog("本副本机器人NPC可以互相攻击: atkNPCID=%s(%s),defNPCID=%s(%s)" % (attacker.GetNPCID(), attacker.GetName(), defender.GetNPCID(), defender.GetName()))
            return True
        #GameWorld.DebugLog("本副本NPC不能互相攻击: atkNPCID=%s(%s),defNPCID=%s(%s)" % (attacker.GetNPCID(), attacker.GetName(), defender.GetNPCID(), defender.GetName()))
        return False
    return True
def GetFBRobotCanAtkObjTypeIDList(curNPC):
    ## 获取副本中机器人可能可攻击的实例类型ID列表
    ## @return: [[objType, objID], ...]
    faction = NPCCommon.GetFaction(curNPC)
    if not faction:
        return []
    defFaction = ShareDefine.CampType_Justice if faction == ShareDefine.CampType_Evil else ShareDefine.CampType_Evil
    objTypeIDList = []
    defFactionObj = GetBattleFactionObj(defFaction)
    for playerID in defFactionObj.onlinePlayerIDList:
        objTypeIDList.append([IPY_GameWorld.gotPlayer, playerID])
    for robotID in defFactionObj.robotObjIDList:
        objTypeIDList.append([IPY_GameWorld.gotNPC, robotID])
    random.shuffle(objTypeIDList) # 打乱顺序
    return objTypeIDList
## 玩家攻击玩家是否有惩罚
def DoFBAttackHasPunish(atkPlayer, defPlayer):
    return False
## 是否副本复活
def OnPlayerReborn():
    return True