From 0c27822ef5e6c67782ed143a4ff03ecfbdfda1fb Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期一, 23 五月 2022 16:52:58 +0800
Subject: [PATCH] 9415 【BT】【后端】古神战场(副本内功能完整版本)

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossBattlefield.py | 1773 ++++++++++++++++++++++++++++++++++++++++++++++++----------
 1 files changed, 1,462 insertions(+), 311 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossBattlefield.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossBattlefield.py
index 5db11ee..830fe33 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GameWorldLogic/FBProcess/GameLogic_CrossBattlefield.py
+++ b/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
-

--
Gitblit v1.8.0