#!/usr/bin/python
# -*- coding: GBK -*-
#-------------------------------------------------------------------------------
#
##@package GameWorldLogic.FBProcess.GameLogic_FamilyWar
#
# @todo:ÏÉÃËÁªÈü
# @author hxp
# @date 2018-01-12
# @version 1.1
#
# @change: "2018-07-23 16:00" hxp ²É¼¯Ë®¾§Ö§³Ö°´Ë®¾§IDÅäÖòɼ¯»ý·Ö£»Ôö¼ÓÎÞÖ÷buff£»Ì켫ÁªÈü»ý·Ö¶îÍâ½±Àøµ÷ÕûΪ»ñʤ·½»ý·ÖµÚÒ»Ãû²ÅÓУ»
#
# ÏêϸÃèÊö: ÏÉÃËÁªÈü
#
#-------------------------------------------------------------------------------
#"""Version = 2018-07-23 16:00"""
#-------------------------------------------------------------------------------
import ChConfig
import NPCCommon
import GameWorld
import PyGameData
import ShareDefine
import IPY_GameWorld
import PlayerControl
import ItemControler
import ChPyNetSendPack
import GameWorldProcess
import PlayerDienstgrad
import PlayerWeekParty
import IpyGameDataPY
import PlayerFamily
import NetPackCommon
import SkillCommon
import EventReport
import ItemCommon
import BuffSkill
import AICommon
import FBCommon
import GameMap
import GameObj
import random
import copy
import math
FamilyWarRound_First = 1 # Ê×ÂÖ
FamilyWarRound_Second = 2 # ´ÎÂÖ
FamilyWar_MaxGroupID = 5 # ÁªÈü·Ö×éÊý
#µ±Ç°¸±±¾µØÍ¼µÄ״̬
(
FB_Step_Open, # µØÍ¼¿ªÆô
FB_Step_Prepare, # µØÍ¼×¼±¸
FB_Step_Fighting, # Õ½¶·ÖÐ
FB_Step_LeaveTime, # ×ÔÓÉʱ¼ä
FB_Step_Over, # ¸±±¾¹Ø±Õ
) = range(5)
(
Time_Prepare, # ¸±±¾×¼±¸Ê±¼ä 0
Time_Fight, # ¸±±¾Õ½¶·Ê±¼ä 1
Time_Leave, # ¸±±¾À뿪ʱ¼ä 2
) = range(3)
# GameFBData »º´æ
GameFBData_FamilyWarGlobal = "FamilyWarGlobal" # {key:value, ...}
GameFBData_FamilyWarFamily = "FamilyWarFamily" # {playerID:FamilyWarFamily, ...}
GameFBData_FamilyWarPlayer = "FamilyWarPlayer" # {playerID:FamilyWarPlayer, ...}
# GameFBData_FamilyWarGlobal key
Global_HelpInfo = "HelpInfo" # ¼Ç¼³£¹æ°ïÖúÐÅÏ¢£¬±ä¸üʱͬ²½
Global_HelpBuff = "HelpBuff" # ¼ÇÂ¼Ëæ»úbuff״̬ÐÅÏ¢£¬±ä¸üʱͬ²½
Global_HelpCrystal = "HelpCrystal" # ¼Ç¼ˮ¾§Õ¼ÁìÃ÷ϸÐÅÏ¢£¬±ä¸üʱͬ²½
Global_HelpCrystalAtk = "HelpCrystalAtk" # ¼Ç¼ˮ¾§¹¥»÷Ã÷ϸÐÅÏ¢£¬±ä¸üʱͬ²½
Global_BillboardBuff = "BillboardBuff" # ¼Ç¼ÅÅÐаñbuffÐÅÏ¢£¬±ä¸üʱͬ²½
# ¸±±¾Ïà¹Ø×Öµäkey
GameFBDict_IsFinalMatch = "IsFinalMatch" # ÊÇ·ñ×îÖÕ¾öÈü³¡´Î
GameFBDict_RoundNum = "RoundNum" # ÂÖ´Î
GameFBDict_GroupID = "GroupID" # ÁªÈü×é¼¶±ð
GameFBDict_WinnerFamilyID = "WinnerFamilyID" # »ñʤµÄÏÉÃËID
GameFBDict_GetFlagFamilyID = "FlagFamily_%s" # »ñµÃÕ½ÆìµÄÕ½ÃËid£¬²ÎÊýΪսÆìNPCID
GameFBDict_FamilyResPointTick = "FamResPointTick_%s" # »ñµÃÕ½ÆìÕ½ÃËˢлý·Öʱ¼ä£¬²ÎÊýΪսÆìNPCID
GameFBDict_HelpInfoTick = "HelpInfoTick" # ¸±±¾°ïÖúÐÅϢͬ²½tick
GameFBDict_RandBuffCollectTick = "RBuffCollectTick" # Ëæ»úbuff±»²Étick
GameFBDict_RandBuffRefreshTick = "RBuffRefreshTick" # Ëæ»úbuffË¢ÐÂtick
GameFBDict_RandBuffObjID = "RBuffObjID_%s" # Ëæ»úbuffµÄObjID, ²ÎÊýÎª×ø±ê±àºÅË÷Òý 0~n
## ²ÎÈüµÄÏÉÃËÀà
class FamilyWarFamily():
    
    def __init__(self, familyID):
        self.familyID = familyID
        self.faction = 0
        self.rank = 0 # ÏÉÃËÁбíÃû´Î
        self.winCount = 0 # Á¬Ê¤´ÎÊý
        self.resPoint = 0.0 # µ±Ç°×ÊÔ´µãÊý, ³É³¤°Ù·Ö±È¼ÆËãºó²»È¡Õû£¬¿ÉÄÜÊÇСÊý
        self.memCount = 0 # ÏÉÃËÔÚÕ½³¡ÖеÄÈËÊý
        
        self.randBuffAttrLV = 0 # Ëæ»úbuff¼ÓÊôÐԵȼ¶
        self.randBuffResPoint = 0 # Ëæ»úbuffÔö¼ÓµÄ¹Ì¶¨×ÊÔ´µãÊý
        self.randBuffResPointPerDict = {} # Ëæ»úbuffÔö¼ÓµÄ×ÊÔ´µã³É³¤ÐÅÏ¢ {addBuffTick:[lastTime, addPer], ...}
        return
    
    def GetBuffResPointPer(self, tick):
        totalPer = 0
        for addBuffTick, buffInfo in self.randBuffResPointPerDict.items():
            lastTime, addPer = buffInfo
            if tick - addBuffTick >= lastTime:
                self.randBuffResPointPerDict.pop(addBuffTick)
            else:
                totalPer += addPer
        return totalPer
    
    def GetResPoint(self): return self.resPoint
    def AddResPoint(self, addResPoint):
        basePoint = 500
        befDivValue = int(self.resPoint / basePoint)
        self.resPoint += addResPoint
        aftDivValue = int(self.resPoint / basePoint)
        if befDivValue != aftDivValue:
            notifyPoint = basePoint * aftDivValue
            # ¼º·½×ÊÔ´µãÒÑ´ï%s0µã
            # µÐ·½×ÊÔ´µãÒÑ´ï%s0µã
            PlayerControl.FBFactionNotify(self.faction, "FamilyMatchOwnResources", [notifyPoint], 
                                          "FamilyMatchEnimeyResources", [notifyPoint])
        return self.resPoint
    
def AddFamilyWarFamily(familyID):
    familyWarFamilyDict = FBCommon.GetGameFBData(GameFBData_FamilyWarFamily)
    if familyID in familyWarFamilyDict:
        return familyWarFamilyDict[familyID]
    warFamily = FamilyWarFamily(familyID)
    warFamily.faction = GetFamilyFaction(familyID)
    familyWarFamilyDict[familyID] = warFamily
    return warFamily
def GetFamilyWarFamily(familyID):
    familyWarFamilyDict = FBCommon.GetGameFBData(GameFBData_FamilyWarFamily)
    if familyID in familyWarFamilyDict:
        return familyWarFamilyDict[familyID]
    return AddFamilyWarFamily(familyID)
def GetWarFamilyName(familyID):
    familyVsMgr = GameWorld.GetGameFB().GetFamilyVS()
    if familyVsMgr.GetFamilyID() == familyID:
        return familyVsMgr.GetFamilyName()
    return familyVsMgr.GetVSFamilyName()
## ²ÎÈüµÄÏÉÃËÍæ¼ÒÀà
class FamilyWarPlayer():
    
    def __init__(self, familyID, faction, playerID, name, tick):
        self.familyID = familyID
        self.faction = faction
        self.playerID = playerID
        self.name = name
        self.score = 0 # »ý·Ö
        self.killPlayerCount = 0 # »÷ɱÊý
        self.collResourceCount = 0 # Õ¼Áì×ÊÔ´µãÊý
        self.collRandBuffCount = 0 # ÇÀ¶ábuffÊý
        self.fightTime = 0 # Õ½¶·Ê±³¤
        self.joinTick = tick # ¼ÓÈëÕ½³¡Ê±µÄtick
        
        self.calcFightTimeTick = 0 # ¼ÆËãÕ½¶·Ê±³¤tick
        self.collectTypeIndex = 0 # ²É¼¯NPCÀàÐÍÅäÖÃindex
        self.collectLostHPTick = 0 # ²É¼¯NPCµôѪtick
        return
    
def AddFamilyWarPlayer(familyID, faction, playerID, name, tick):
    familyWarPlayerDict = FBCommon.GetGameFBData(GameFBData_FamilyWarPlayer)
    if playerID in familyWarPlayerDict:
        return familyWarPlayerDict[playerID]
    warPlayer = FamilyWarPlayer(familyID, faction, playerID, name, tick)
    familyWarPlayerDict[playerID] = warPlayer
    return warPlayer
def GetFamilyWarPlayer(playerID):
    familyWarPlayerDict = FBCommon.GetGameFBData(GameFBData_FamilyWarPlayer)
    if playerID in familyWarPlayerDict:
        return familyWarPlayerDict[playerID]
    # Ò»°ã²»¿ÉÄܳöÏÖ²»´æÔÚµÄÇé¿ö£¬ÒÔÏ´úÂëÖ÷ҪΪÁ˱àÂëʱ°´ . ÄÜÌáʾÏÔʾÀàÖжÔÏó
    tick = GameWorld.GetGameWorld().GetTick()
    curPlayer = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(playerID)
    familyID = 0 if not curPlayer else curPlayer.GetFamilyID()
    name = "" if not curPlayer else curPlayer.GetPlayerName()
    faction = GetFamilyFaction(familyID)
    return AddFamilyWarPlayer(familyID, faction, playerID, name, tick)
def GetFamilyWarBillboardPack(gameFB, sortWarPlayer, tick, winFaction=0):
    warBillboard = ChPyNetSendPack.tagMCFamilyWarBillboard()
    warBillboard.Clear()
    warBillboard.GroupID = gameFB.GetGameFBDictByKey(GameFBDict_GroupID)
    warBillboard.WinFaction = winFaction
    warBillboard.TotalFightTime = 0 if not winFaction else (tick - gameFB.GetFBStepTick()) / 1000
    warBillboard.FBBillboardPlayer = []
    for warPlayer in sortWarPlayer:
        wPlayer = ChPyNetSendPack.tagMCFamilyWarPlayer()
        wPlayer.Clear()
        wPlayer.PlayerID = warPlayer.playerID
        wPlayer.PlayerName = warPlayer.name
        wPlayer.PlayerNameLen = len(wPlayer.PlayerName)
        wPlayer.Faction = warPlayer.faction
        wPlayer.CrystalCount = warPlayer.collResourceCount
        wPlayer.RandBuffCount = warPlayer.collRandBuffCount
        wPlayer.KillPlayerCount = warPlayer.killPlayerCount
        wPlayer.FightTime = 0 if not winFaction else warPlayer.fightTime / 1000
        wPlayer.Point = warPlayer.score
        warBillboard.FBBillboardPlayer.append(wPlayer)
    warBillboard.BillboardCount = len(warBillboard.FBBillboardPlayer)
    return warBillboard
def SortFamilyWarPlayer():
    familyWarPlayerDict = FBCommon.GetGameFBData(GameFBData_FamilyWarPlayer)
    sortWarPlayerList = familyWarPlayerDict.values()
    sortWarPlayerList.sort(cmp=CmpWarPlayer)
    return sortWarPlayerList
def CmpWarPlayer(warPlayerA, warPlayerB):
    ## ÅÅÐò¹æÔò£¬»ý·Ö > ʤÀûµÄ £¾ »÷ɱÊý¶àµÄ £¾ Õ¼Áì×ÊÔ´µã¶àµÄ£¾ ÇÀ¶áBUFF¶àµÄ £¾ Õ½¶·Ê±³¤³¤µÄ £¾ ¼ÓÈëÕ½³¡tick
    # »ý·Ö
    scoreA = warPlayerA.score
    scoreB = warPlayerB.score
    cmpRet = cmp(scoreB, scoreA) # µ¹Ðò
    #GameWorld.DebugLog("    »ý·Ö±È½Ï: scoreB=%s,scoreA=%s,cmpRet=%s" % (scoreB, scoreA, cmpRet))
    if cmpRet != 0:
        return cmpRet
    
    # »ñʤµÄ
    winnerFamilyID = GameWorld.GetGameFB().GetGameFBDictByKey(GameFBDict_WinnerFamilyID)
    isWinA = warPlayerA.familyID == winnerFamilyID
    isWinB = warPlayerB.familyID == winnerFamilyID
    cmpRet = cmp(isWinB, isWinA) # µ¹Ðò
    #GameWorld.DebugLog("    »ñʤ±È½Ï: winnerFamilyID=%s,isWinB=%s,isWinA=%s,cmpRet=%s" % (winnerFamilyID, isWinB, isWinA, cmpRet))
    if cmpRet != 0:
        return cmpRet
    
    # »÷É±Íæ¼Ò
    killPlayerCountA = warPlayerA.killPlayerCount
    killPlayerCountB = warPlayerB.killPlayerCount
    cmpRet = cmp(killPlayerCountB, killPlayerCountA) # µ¹Ðò
    #GameWorld.DebugLog("    »÷É±Íæ¼Ò: killPlayerCountB=%s,killPlayerCountA=%s,cmpRet=%s" % (killPlayerCountB, killPlayerCountA, cmpRet))
    if cmpRet != 0:
        return cmpRet
    
    # Õ¼Áì×ÊÔ´
    collResourceCountA = warPlayerA.collResourceCount
    collResourceCountB = warPlayerB.collResourceCount
    cmpRet = cmp(collResourceCountB, collResourceCountA) # µ¹Ðò
    #GameWorld.DebugLog("    Õ¼Áì×ÊÔ´: collResourceCountB=%s,collResourceCountA=%s,cmpRet=%s" % (collResourceCountB, collResourceCountA, cmpRet))
    if cmpRet != 0:
        return cmpRet
    
    # ÇÀ¶ábuff
    collRandBuffCountA = warPlayerA.collRandBuffCount
    collRandBuffCountB = warPlayerB.collRandBuffCount
    cmpRet = cmp(collRandBuffCountB, collRandBuffCountA) # µ¹Ðò
    #GameWorld.DebugLog("    ÇÀ¶ábuff: collRandBuffCountB=%s,collRandBuffCountA=%s,cmpRet=%s" % (collRandBuffCountB, collRandBuffCountA, cmpRet))
    if cmpRet != 0:
        return cmpRet
    
    # Õ½¶·Ê±³¤
    fightTimeA = warPlayerA.fightTime
    fightTimeB = warPlayerB.fightTime
    cmpRet = cmp(fightTimeB, fightTimeA) # µ¹Ðò
    #GameWorld.DebugLog("    Õ½¶·Ê±³¤: fightTimeB=%s,fightTimeA=%s,cmpRet=%s" % (fightTimeB, fightTimeA, cmpRet))
    if cmpRet != 0:
        return cmpRet
        
    # ¼ÓÈëÕ½³¡tick ÕýÐò
    joinTickA = warPlayerA.joinTick
    joinTickB = warPlayerB.joinTick
    cmpRet = cmp(joinTickA, joinTickB) # µ¹Ðò
    #GameWorld.DebugLog("    ¼ÓÈëÕ½³¡tick: joinTickA=%s,joinTickB=%s,cmpRet=%s" % (joinTickA, joinTickB, cmpRet))
    return cmpRet
## -----------------------------------------------------------------------------------------------
def GetFWarStepTime(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchPlayTime") # ½×¶Îʱ¼ä
## ÓªµØ
def GetFactionArea(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchSpawnPoint", 1) # ÓªµØ·¶Î§
def GetBarrierPointList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchSpawnPoint", 2) # ×¼±¸Çø¼äÓªµØÕϰµã
## Ë®¾§
def GetResourceRebornPosList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchResourcePoint", 1) # Ë®¾§¸´»îµãÁбí
def GetResourceNPCIDList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchResourcePoint", 2) # Ë®¾§NPCID˳ÐòÁбí
def GetResourceRebornRank(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchResourcePoint", 3) # ¸´»î¶ÔÓ¦Õ¼ÁìË®¾§±àºÅÓÅÏȼ¶
def GetResourceWinPoint(): return IpyGameDataPY.GetFuncCfg("FamilyMatchResourcePoint", 5) # »ñʤ×ÊÔ´ÉÏÏÞ
def GetResourcePointMultiple(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchResourcePoint1", 1) # ÌØÊâË®¾§×ÊÔ´µã³É³¤±¶Öµ
def GetResourcePointPerSecond(): return IpyGameDataPY.GetFuncCfg("FamilyMatchResourcePoint1", 2) # Õ¼ÁìË®¾§»ñµÃ×ÊÔ´µã/Ãë
## ²É¼¯
def GetCollectTimeList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchCollect", 1)
def GetCollectLostHPPerList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchCollect", 2)
## Ëæ»úbuff
def GetRandBuffPosList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRandomBuff", 1) # Ëæ»úbuffË¢ÐÂ×ø±êÁбí
def GetRandBuffCount(): return IpyGameDataPY.GetFuncCfg("FamilyMatchRandomBuff", 2) # ÿ´ÎË¢ÐÂËæ»úbuffÊý
def GetRandBuffNPCIDList(): return IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRandomBuff", 3) # Ëæ»úbuffNPCIDÁбí
def GetRandBuffRefreshTime(): return IpyGameDataPY.GetFuncCfg("FamilyMatchRandomBuff", 4) # Ëæ»úbuffˢмä¸ôÃë
## ¸öÈË»ý·Ö
def GetScorePerMinute(): return IpyGameDataPY.GetFuncCfg("FamilyMatchPersonalScore", 1) # ÔÚÕ½³¡ÄÚ¶ºÁôÿ·ÖÖÓ»ñµÃ»ý·Ö
def GetScoreKillPlayer(): return IpyGameDataPY.GetFuncCfg("FamilyMatchPersonalScore", 2) # ÿ´Î»÷ɱµÐ·½Íæ¼Ò»ñµÃ»ý·Ö
def GetScoreCollectRescource(): return IpyGameDataPY.GetFuncCfg("FamilyMatchPersonalScore", 3) # ³É¹¦Õ¼ÁìÒ»¸öË®¾§»ñµÃ»ý·Ö
def GetScoreCollectRandBuff(): return IpyGameDataPY.GetFuncCfg("FamilyMatchPersonalScore", 4) # ³É¹¦²É¼¯Ò»¸öBUFF»ñµÃ»ý·Ö
def GetScoreWinerAddPer(): return IpyGameDataPY.GetFuncCfg("FamilyMatchPersonalScore", 5) # ʤÀû·½½áËãʱ£¬»ý·ÖµÄ¶îÍâ°Ù·Ö±È¼Ó³É£¨N%£©
def OnFBPlayerOnDay(curPlayer):
    dailyRewardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyWarDailyReward)
    if dailyRewardState:
        PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyWarDailyReward, 0)
        championFamilyID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ChampionFamilyID)
        if curPlayer.GetFamilyID() == championFamilyID:
            Sync_ChampionFamilyDailyRewardState(curPlayer)
    return
def OnFBPlayerOnLogin(curPlayer):
    dailyRewardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyWarDailyReward)
    if dailyRewardState:
        championFamilyID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ChampionFamilyID)
        if curPlayer.GetFamilyID() == championFamilyID:
            Sync_ChampionFamilyDailyRewardState(curPlayer)
    return
def OnChampionFamilyIDChange():
    playerManager = GameWorld.GetPlayerManager()
    for index in range(0, playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        if curPlayer.GetID() == 0:
            continue
        DoCheckChampionFamilyTitle(curPlayer)
    return
def DoCheckChampionFamilyTitle(curPlayer):
    ## ¼ì²éÍõÕßÏÉÃ˳ƺÅ: 1-ÍõÕßÏÉÃ˱ä¸üʱ£»2-Íæ¼Ò¼ÓÈëÏÉÃËʱ£»3-Íæ¼ÒÍ˳öÏÉÃËʱ£»3-Íæ¼Òְλ±ä¸üʱ
    titleIDList = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchDayReward", 2)
    if not titleIDList:
        return
    leaderTitleID, memberTitleID = titleIDList
    
    delDienstgradIDList = []
    addDienstgradIDList = []
    
    familyID = curPlayer.GetFamilyID()
    championFamilyID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ChampionFamilyID)
    if not championFamilyID or familyID != championFamilyID:
        delDienstgradIDList = [leaderTitleID, memberTitleID]
    elif curPlayer.GetFamilyMemberLV() == IPY_GameWorld.fmlLeader:
        addDienstgradIDList = [leaderTitleID]
        delDienstgradIDList = [memberTitleID]
    else:
        addDienstgradIDList = [memberTitleID]
        delDienstgradIDList = [leaderTitleID]
        
    PlayerDienstgrad.PlayerDelAddDienstgrad(curPlayer, delDienstgradIDList, addDienstgradIDList)
    return
##¿ªÆô¸±±¾
# @param tick ʱ¼ä´Á
# @return ·µ»ØÖµÎÞÒâÒå
# @remarks ¿ªÆô¸±±¾
def OnOpenFB(tick):
    globalDict = {
                  Global_HelpInfo:None,
                  Global_HelpBuff:None,
                  Global_HelpCrystal:None,
                  Global_HelpCrystalAtk:None,
                  Global_BillboardBuff:None,
                  }
    FBCommon.SetGameFBData(GameFBData_FamilyWarGlobal, globalDict)
    FBCommon.SetGameFBData(GameFBData_FamilyWarFamily, {})
    FBCommon.SetGameFBData(GameFBData_FamilyWarPlayer, {})
    
    FBCommon.SetFBStep(FB_Step_Prepare, tick)
    
    gameFB = GameWorld.GetGameFB()
    familyVsMgr = gameFB.GetFamilyVS()
    familyIDA = familyVsMgr.GetFamilyID()
    familyIDB = familyVsMgr.GetVSFamilyID()
    
    warFamilyA = AddFamilyWarFamily(familyIDA)
    warFamilyB = AddFamilyWarFamily(familyIDB)
    
    for vsFamily in PyGameData.VSFamilyInfo:
        familyIDList = vsFamily[ShareDefine.VSFamilyInfo_FamilyIDList]
        if familyIDA in familyIDList and familyIDB in familyIDList:
            isFinalMatch = vsFamily[ShareDefine.VSFamilyInfo_IsFinalMatch]
            roundNum = vsFamily[ShareDefine.VSFamilyInfo_RoundNum]
            groupID = vsFamily[ShareDefine.VSFamilyInfo_GroupID]
            rankA, rankB = vsFamily[ShareDefine.VSFamilyInfo_FamilyRankList]
            winCountA, winCountB = vsFamily[ShareDefine.VSFamilyInfo_WinCountList]
            
            gameFB.SetGameFBDict(GameFBDict_IsFinalMatch, int(isFinalMatch))
            gameFB.SetGameFBDict(GameFBDict_RoundNum, roundNum)
            gameFB.SetGameFBDict(GameFBDict_GroupID, groupID)
            warFamilyA.faction = ShareDefine.CampType_Justice
            warFamilyA.rank = rankA
            warFamilyA.winCount = winCountA
            warFamilyB.faction = ShareDefine.CampType_Evil
            warFamilyB.rank = rankB
            warFamilyB.winCount = winCountB
            GameWorld.Log("OpenFBWar: isFinalMatch=%s,roundNum=%s,groupID=%s,familyIDA(%s) VS familyIDB(%s),rank=[%s,%s],winCount=[%s,%s]" 
                          % (isFinalMatch, roundNum, groupID, familyIDA, familyIDB, rankA, rankB, winCountA, winCountB))
            break
        
    return
##¹Ø±Õ¸±±¾
# @param tick ʱ¼ä´Á
# @return ÎÞÒâÒå
# @remarks 
def OnCloseFB(tick):
    FBCommon.SetGameFBData(GameFBData_FamilyWarGlobal, None)
    FBCommon.SetGameFBData(GameFBData_FamilyWarFamily, None)
    FBCommon.SetGameFBData(GameFBData_FamilyWarPlayer, None)
    return
## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë
#  @param curPlayer Íæ¼ÒʵÀý
#  @param mapID µØÍ¼ID
#  @param lineID Ïß·id
#  @param tick ʱ¼ä´Á
#  @return ²¼¶ûÖµ
def OnEnterFBEvent(curPlayer, mapID, lineID, tick):
    if not GetFamilyFaction(curPlayer.GetFamilyID()):
        PlayerControl.NotifyCode(curPlayer, "NoFamilyWarLine")
        return False
    return True
## ½øÈë´«Ë͵ã
#  @param curPlayer
#  @param mapID µØÍ¼ID
#  @param lineId ·ÖÏßID
#  @param tick
#  @return ×ø±êÁбí(X,Y)
def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):
    faction = GetFamilyFaction(curPlayer.GetFamilyID())
    if not faction:
        return
    return GetFactionArea()[GetFactionIndex(faction)]
def GetFactionIndex(faction): return max(0, faction - 1)
def GetFamilyFaction(familyID):
    # »ñÈ¡ÏÉÃËËùÊôÕóÓª£¬ÆäËûµØÍ¼Ò²ÐèÒªÓõ½£¬¹ÊÕâÀïÖ±½Ó±éÀú»º´æÖÐÊý¾Ý
    for vsFamily in PyGameData.VSFamilyInfo:
        familyIDList = vsFamily[ShareDefine.VSFamilyInfo_FamilyIDList]
        if familyID in familyIDList:
            if familyID == familyIDList[0]:
                return ShareDefine.CampType_Justice
            return ShareDefine.CampType_Evil
    return 0
##»ñµÃÍæ¼Ò´«È븱±¾ÐèҪЯ´øµÄÐÅÏ¢
# @param curPlayer Íæ¼ÒʵÀý
# @return ×Ö·û´®
# @remarks
def GetPlayerResetWorldPosFBMsg(curPlayer, lineId):
    return str(curPlayer.GetFamilyID())
## ÊÇ·ñ¿ÉÒÔ½øÈë
#  @param ask ÇëÇóÐÅÏ¢
#  @param tick
#  @return »Ø¸´ÊÇ·ñͨ¹ýÇëÇó
def OnChangeMapAsk(ask, tick):
    familyIDMsg = ask.GetMsg()
    
    if not familyIDMsg:
        GameWorld.ErrLog("ÎÞ·¨»ñµÃ´«ÈëµÄ¼Ò×åID = %s" % (familyIDMsg))
        return IPY_GameWorld.cmeNull
    
    familyID = int(familyIDMsg)
    result = GetFamilyWarGameFB(familyID)
    if result == None:
        return IPY_GameWorld.cmeCustom, "NoFamilyWarLine"
    
    gameFB, openState = result
    if openState != IPY_GameWorld.fbosOpen:
        return IPY_GameWorld.cmeCustom, "FamilyWarLineClose"
 
    #ÒѾ¿ªÆôÁË£¬²»ÈýøÈë
    if gameFB.GetFBStep() >= FB_Step_LeaveTime:
        return IPY_GameWorld.cmeCustom, "FamilyWarLineEnd"
    
    return IPY_GameWorld.cmeAccept
def GetFamilyWarGameFB(familyID):
    gameWorld = GameWorld.GetGameWorld()
    for index in range(gameWorld.GetGameWorldCount()):
        gameFB = gameWorld.GetGameFBByFbIndex(index)
        familyVsMgr = gameFB.GetFamilyVS()
        familyIDA = familyVsMgr.GetFamilyID()
        familyIDB = familyVsMgr.GetVSFamilyID()
        if familyID in [familyIDA, familyIDB]:
            return gameFB, gameWorld.GetOpenStateByFbIndex(index)
    return
##Íæ¼Ò½øÈ븱±¾
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ÎÞÒâÒå
# @remarks Íæ¼Ò½øÈ븱±¾
def DoEnterFB(curPlayer, tick):
    gameFB = GameWorld.GetGameFB()
    
    fbStep = gameFB.GetFBStep()
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    faction = GetFamilyFaction(familyID)
    if not faction or fbStep not in [FB_Step_Prepare, FB_Step_Fighting]:
        GameWorld.ErrLog("DoEnterFB PlayerLeaveFB familyID=%s,faction=%s,fbStep=%s" % (familyID, faction, fbStep), playerID)
        PlayerControl.PlayerLeaveFB(curPlayer)
        return
    if curPlayer.GetFaction() != faction:
        curPlayer.SetFaction(faction)
        
    if not FBCommon.GetHadDelTicket(curPlayer):
        FBCommon.SetHadDelTicket(curPlayer)
        FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_FamilyWar)
        PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_FamilyWar, 1)
    isFinalMatch = gameFB.GetGameFBDictByKey(GameFBDict_IsFinalMatch)
    roundNum = gameFB.GetGameFBDictByKey(GameFBDict_RoundNum)
    groupID = gameFB.GetGameFBDictByKey(GameFBDict_GroupID)
    warPlayer = AddFamilyWarPlayer(familyID, faction, playerID, curPlayer.GetPlayerName(), tick)
    
    if fbStep == FB_Step_Prepare:
        notify_tick = GetFWarStepTime()[Time_Prepare] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
        curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)
        FBCommon.SyncDynamicBarrierState(GetBarrierPointList(), 1, curPlayer) # ×¼±¸ÆÚ¼äÓж¯Ì¬Õϰµã
        
    elif fbStep == FB_Step_Fighting:
        notify_tick = GetFWarStepTime()[Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
        curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)
        warPlayer.calcFightTimeTick = tick # Õ½¶·½×¶Î½øÈë¸üдËtick
        
    familyVsMgr = gameFB.GetFamilyVS()
    familyIDA = familyVsMgr.GetFamilyID()
    familyIDB = familyVsMgr.GetVSFamilyID()
    warFamilyA = GetFamilyWarFamily(familyIDA)
    warFamilyB = GetFamilyWarFamily(familyIDB)
    
    curWarFamily = warFamilyA if familyID == familyIDA else warFamilyB
    tagWarFamily = warFamilyA if familyID != familyIDA else warFamilyB
    
    curWarFamily.memCount += 1
    GameWorld.Log("DoEnterFB ÏÉÃËÕ½³¡ÈËÊý¼Ó1, isFinalMatch=%s,roundNum=%s,groupID=%s,familyID=%s,memCount=%s,faction=%s" 
                  % (isFinalMatch, roundNum, groupID, familyID, curWarFamily.memCount, faction), playerID)
    
    enterHelpDict = {"familyWar_Enter":{"WinCount":[warFamilyA.winCount, warFamilyB.winCount], "IsFinalMatch":isFinalMatch}}
    __NotifyWarHelp_Info(tick, curPlayer, enterHelpDict)
    
    # ¸ù¾Ýµ±Ç°ÏÉÃËÕ½³¡ÈËÊý¼Ó²ÎÓëbuff
    __AddFamilyWarBuff(familyID, ChConfig.Def_SkillID_FamilyWar_JoinBuff, tick, curWarFamily.memCount)
    
    # ×îÖÕ¾öÈü³¡´Î£¬¶ÔÊÖÓÐÁ¬Ê¤´ÎÊýµÄ£¬Ôö¼ÓÁ¬Ê¤buff
    if isFinalMatch and tagWarFamily.winCount:
        __AddFamilyWarBuff(familyID, ChConfig.Def_SkillID_FamilyWar_CWinBuff, tick, tagWarFamily.winCount)
        
    EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_FamilyWar, 0, ChConfig.CME_Log_Start)
    return
def __NotifyWarHelp_Info(tick, enterPlayer=None, enterHelpDict={}):
    ''' ¸±±¾°ïÖúÐÅÏ¢
    ʵʱͬ²½
    {"familyWar_Buff":[{"PosIndex":λÖÃË÷Òý, "NPCID":buffNPCID, "Atk":1}, {"PosIndex":λÖÃË÷Òý, "NPCID":buffNPCID, "Atk":0}, ...]]}
    
    {"familyWar_Crystal":{"ÕóÓª1":[Ë®¾§NPCID, ...], "ÕóÓª2":[Ë®¾§NPCID, ...]}, "familyWar_CrystalAtk":[ÕýÔÚ±»¹¥»÷µÄË®¾§NPCIDÁбí]}
    
    ͬ²½¹æÔò£º xÃëÒ»´Î
    {"familyWar_HelpInfo":[{"ResPoint":1, MemCount":1, "BuffResPoint":buffÔö¼ÓµÄ×ÊÔ´µãÊý, "BuffResPointPer":buff×ÊÔ´µãÊý³É³¤Íò·ÖÂÊ, "BuffAttrLV":buffÊôÐԵȼ¶},
                            {"ResPoint":1, "MemCount":1, "BuffResPoint":buffÔö¼ÓµÄ×ÊÔ´µãÊý, "BuffResPointPer":buff×ÊÔ´µãÊý³É³¤Íò·ÖÂÊ, "BuffAttrLV":buffÊôÐԵȼ¶}]}
    '''
    
    helpDict = {}
    billboardPack = None
    globalDict = FBCommon.GetGameFBData(GameFBData_FamilyWarGlobal)
    gameFB = GameWorld.GetGameFB()
    lastHelpTick = gameFB.GetGameFBDictByKey(GameFBDict_HelpInfoTick)
    # ÓÐÐÂÍæ¼Ò½øÈë »ò xÃëÇ¿ÖÆÍ¬²½Ò»´Î
    if enterPlayer or tick - lastHelpTick >= 10000:
        gameFB.SetGameFBDict(GameFBDict_HelpInfoTick, tick)
        
        familyVsMgr = gameFB.GetFamilyVS()
        familyIDA = familyVsMgr.GetFamilyID()
        familyIDB = familyVsMgr.GetVSFamilyID()
        warFamilyA = GetFamilyWarFamily(familyIDA)
        warFamilyB = GetFamilyWarFamily(familyIDB)
        helpInfoList = []
        for warFamily in [warFamilyA, warFamilyB]:
            helpInfoList.append({"ResPoint":warFamily.GetResPoint(), "MemCount":warFamily.memCount, 
                                 "BuffResPoint":warFamily.randBuffResPoint, "BuffResPointPer":warFamily.GetBuffResPointPer(tick), 
                                 "BuffAttrLV":warFamily.randBuffAttrLV})
        helpInfoListHis = globalDict[Global_HelpInfo]
        if helpInfoList != helpInfoListHis:
            globalDict[Global_HelpInfo] = helpInfoList
            helpDict["familyWar_HelpInfo"] = helpInfoList
        if enterHelpDict:
            enterHelpDict["familyWar_HelpInfo"] = helpInfoList
            
        billboardPack = GetFamilyWarBillboardPack(gameFB, SortFamilyWarPlayer(), tick)
        
    # buffÐÅÏ¢
    helpBuffList = []
    for i in xrange(len(GetRandBuffPosList())):
        objID = gameFB.GetGameFBDictByKey(GameFBDict_RandBuffObjID % i)
        if not objID:
            continue
        curNPC = GameWorld.FindNPCByID(objID)
        if not curNPC:
            continue
        isInAtk = int(curNPC.GetPlayerHurtList().GetHurtCount() > 0)
        helpBuffList.append({"PosIndex":i, "NPCID":curNPC.GetNPCID(), "Atk":isInAtk})
    helpBuffListHis = globalDict[Global_HelpBuff]
    if helpBuffList != helpBuffListHis:
        globalDict[Global_HelpBuff] = helpBuffList
        helpDict["familyWar_Buff"] = helpBuffList
    if enterHelpDict:
        enterHelpDict["familyWar_Buff"] = helpBuffList
        
    # Ë®¾§×ÊÔ´
    familyIDA = gameFB.GetFamilyVS().GetFamilyID()
    flagAtkList = []
    factionFlagList = [[], []]
    for npcID in GetResourceNPCIDList():
        curNPC = GameWorld.FindNPCByNPCID(npcID)
        if not curNPC:
            continue
        familyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if familyID:
            factionIndex = 0 if familyID == familyIDA else 1
            factionFlagList[factionIndex].append(npcID)
        if curNPC.GetPlayerHurtList().GetHurtCount() > 0:
            flagAtkList.append(npcID)
    
    # Õ¼ÁìË®¾§
    helpCrystal = {ShareDefine.CampType_Justice:factionFlagList[0], ShareDefine.CampType_Evil:factionFlagList[1]} # {ÕóÓª:[Õ¼ÁìNPCID, ...], ...}
    crystalHis = globalDict[Global_HelpCrystal]
    if factionFlagList != crystalHis:
        globalDict[Global_HelpCrystal] = factionFlagList
        helpDict["familyWar_Crystal"] = helpCrystal
    if enterHelpDict:
        enterHelpDict["familyWar_Crystal"] = helpCrystal
        
    # ¹¥»÷Ë®¾§
    crystalAtkHis = globalDict[Global_HelpCrystalAtk]
    if flagAtkList != crystalAtkHis:
        globalDict[Global_HelpCrystalAtk] = flagAtkList
        helpDict["familyWar_CrystalAtk"] = flagAtkList
    if enterHelpDict:
        enterHelpDict["familyWar_CrystalAtk"] = flagAtkList
        
    isBillPackChange = False
    if billboardPack:
        billBuff = billboardPack.GetBuffer()
        lastBillBuff = globalDict[Global_BillboardBuff]
        if billBuff != lastBillBuff:
            globalDict[Global_BillboardBuff] = billBuff
            isBillPackChange = True
            GameWorld.DebugLog("isBillPackChange=%s" % isBillPackChange)
            
    if enterPlayer or isBillPackChange or helpDict:
        enterPlayerID = 0 if not enterPlayer else enterPlayer.GetPlayerID()
        playerManager = GameWorld.GetMapCopyPlayerManager()
        for index in xrange(playerManager.GetPlayerCount()):
            player = playerManager.GetPlayerByIndex(index)
            if not player:
                continue
            playerID = player.GetPlayerID()
            if not playerID:
                continue
            
            if playerID == enterPlayerID:
                FBCommon.NotifyFBHelp(player, 0, enterHelpDict)
                NetPackCommon.SendFakePack(player, billboardPack)
                continue
            
            if helpDict:
                FBCommon.NotifyFBHelp(player, 0, helpDict)
                
            if isBillPackChange:
                NetPackCommon.SendFakePack(player, billboardPack)
    return
##Íæ¼ÒÍ˳ö¸±±¾
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ÎÞÒâÒå
def DoExitFB(curPlayer, tick):
    fbStep = GameWorld.GetGameFB().GetFBStep()
    if fbStep >= FB_Step_LeaveTime:
        if GameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:
            GameWorldProcess.CloseFB(tick)
            FBCommon.SetFBStep(FB_Step_Over, tick)
        return
    
    playerID = curPlayer.GetPlayerID()
    warPlayer = GetFamilyWarPlayer(playerID)
    familyID = warPlayer.familyID # ÕâÀïÈ¡familyID·½Ê½ÌØÊâ´¦Àí£¬·ÀÖ¹Íæ¼ÒÒì³£À뿪ÏÉÃ˱»Ìß³ö¸±±¾Ê±µ¼ÖÂÔÏÉÃËÈËÊý²»»á-1
    warFamily = GetFamilyWarFamily(familyID)
    warFamily.memCount = max(0, warFamily.memCount - 1)
    GameWorld.Log("DoExitFB ÏÉÃËÕ½³¡ÈËÊý¼õ1, familyID=%s,memCount=%s" % (familyID, warFamily.memCount), playerID)
    
    # ÒòΪÊǽµbuffµÈ¼¶£¬ËùÒÔÐèÒªÏÈɾ³ý
    __AddFamilyWarBuff(familyID, ChConfig.Def_SkillID_FamilyWar_JoinBuff, tick, warFamily.memCount, True)
    return
def OnProcess(tick):
    fbStep = GameWorld.GetGameFB().GetFBStep()
    
    # ¸±±¾×¼±¸
    if fbStep == FB_Step_Prepare:
        __DoLogic_FB_Prepare(tick)
          
    # ¸±±¾½øÐÐÖÐ
    elif fbStep == FB_Step_Fighting:
        __DoLogic_FB_Fighting(tick)
        
    # ¸±±¾½áÊø
    elif fbStep == FB_Step_LeaveTime:
        __DoLogic_FB_Over(tick)
        
    return
def __DoLogic_FB_Prepare(tick):
    
    remaindTick = GetFWarStepTime()[Time_Prepare] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    if remaindTick > 0:
        return
    barrierPointList = GetBarrierPointList()
    #¹Ø±Õ¶¯Ì¬Õϰµã
    FBCommon.SyncDynamicBarrierState(barrierPointList, 0)
    
    FBCommon.SetFBStep(FB_Step_Fighting, tick)
    
    factionAreaInfo = GetFactionArea()
    maxDistList = []
    for i, pointList in enumerate(barrierPointList):
        centrePosX, centrePosY = factionAreaInfo[i][:2]
        dist1 = GameWorld.GetDist(centrePosX, centrePosY, pointList[0], pointList[1])
        dist2 = GameWorld.GetDist(centrePosX, centrePosY, pointList[2], pointList[3])
        maxDistList.append(max(dist1, dist2))
        
    fightTime = GetFWarStepTime()[Time_Fight] * 1000
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        playerID = curPlayer.GetPlayerID()
        if not playerID:
            continue
        curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, fightTime, True)
        
        warPlayer = GetFamilyWarPlayer(playerID)
        warPlayer.calcFightTimeTick = tick
        
        faction = curPlayer.GetFaction()
        if not faction:
            GameWorld.Log("»¹Î´ÉèÖÃÕóÓªµÄÍæ¼ÒÔݲ»´¦Àí£¡¿ÉÄÜÊÇDoEnterÖУ¡", playerID)
            continue
        # ¼ì²é×ø±ê£¬·ÀÖ¹×÷±×
        factionIndex = GetFactionIndex(faction)
        centrePosX, centrePosY, radius = factionAreaInfo[factionIndex]
        curPosX, curPosY = curPlayer.GetPosX(), curPlayer.GetPosY()
        dist = GameWorld.GetDist(curPosX, curPosY, centrePosX, centrePosY)
        maxDist = maxDistList[factionIndex]
        # ÅжϾàÀë
        if dist > maxDist:
            posPoint = GameMap.GetEmptyPlaceInArea(centrePosX, centrePosY, radius)
            curPlayer.ResetPos(posPoint.GetPosX(), posPoint.GetPosY())
            GameWorld.Log("Íæ¼Ò²»ÔÚÓªµØ·¶Î§ÄÚ£¬Ç¿ÖÆÀ»Ø£¡faction=%s,curPos=(%s,%s),centerPos=(%s,%s), dist=%s > maxDist=%s" 
                          % (faction, curPosX, curPosY, centrePosX, centrePosY, dist, maxDist), playerID)
    return
def __DoLogic_FB_Fighting(tick):
    __NotifyWarHelp_Info(tick)
    __AddPlayerFightTimeByTime(tick) # ¸üÐÂÍæ¼ÒÕ½¶·Ê±³¤
    if __AddFamilyResPointByTime(tick):
        return
    
    remaindTick = GetFWarStepTime()[Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    if remaindTick > 0:
        __RefreshRandBuff(tick)
        return
    
    __DoLogicFamilyWarOver(tick) # Ö´ÐбÈÈü½áÊøÂß¼
    return
def __AddPlayerFightTimeByTime(tick):
    # ¸üÐÂÍæ¼ÒÕ½¶·Ê±³¤
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        playerID = curPlayer.GetPlayerID()
        if not playerID:
            continue
        warPlayer = GetFamilyWarPlayer(playerID)
        lastCalcTick = warPlayer.calcFightTimeTick
        warPlayer.calcFightTimeTick = tick
        if not lastCalcTick:
            continue
        addTick = tick - lastCalcTick
        lastFightMinute = warPlayer.fightTime / 60000 # ÒѾս¶··ÖÖÓÊý
        warPlayer.fightTime += addTick
        updFightMinute = warPlayer.fightTime / 60000 # ¸üÐÂÕ½¶··ÖÖÓÊý
        addFightMinute = updFightMinute - lastFightMinute
        # Âú·ÖÖӲżÓ
        if not addFightMinute:
            continue
        addScore = GetScorePerMinute() * addFightMinute
        warPlayer.score += addScore
        #GameWorld.DebugLog("¶¨Ê±Ôö¼ÓÍæ¼Ò»ý·Ö: fightTime=%s,addScore=%s,updScore=%s" 
        #                   % (warPlayer.fightTime, addScore, warPlayer.score), playerID)
    return
def __AddFamilyResPointByTime(tick):
    # ¶¨Ê±Ôö¼Ó×ÊÔ´µã
    # @return: ÊÇ·ñÓÐÏÉÃË»ñʤ
    
    resPointPerSecond = GetResourcePointPerSecond()
    pointMultipleDict = GetResourcePointMultiple()
    gameFB = GameWorld.GetGameFB()
    resourceNPCIDList = GetResourceNPCIDList()
    addResPointDict = {} # Ôö¼ÓµÄ×ÊÔ´µã×ÜÊý {familyID:addPoint, ...}
    for npcID in resourceNPCIDList:
        pointTick = gameFB.GetGameFBDictByKey(GameFBDict_FamilyResPointTick % npcID)
        familyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if not pointTick or not familyID:
            continue
        # ÿÃë¼Ó»ý·Ö, ÔÝдËÀ
        addTime = (tick - pointTick) / 1000
        if not addTime:
            continue
        gameFB.SetGameFBDict(GameFBDict_FamilyResPointTick % npcID, tick)
        
        addPoint = resPointPerSecond * addTime
        if npcID in pointMultipleDict:
            addPoint = int(math.ceil(addPoint * pointMultipleDict[npcID]))
            #GameWorld.DebugLog("ÌØÊâË®¾§Ôö¼Ó×ÊÔ´µã: resPointPerSecond=%s,addTime=%s,addPoint=%s" % (resPointPerSecond, addTime, addPoint))
        addResPointDict[familyID] = addResPointDict.get(familyID, 0) + addPoint
        
    familyVsMgr = gameFB.GetFamilyVS()
    familyIDA = familyVsMgr.GetFamilyID()
    familyIDB = familyVsMgr.GetVSFamilyID()
    warFamilyA = GetFamilyWarFamily(familyIDA)
    warFamilyB = GetFamilyWarFamily(familyIDB)
    
    buffResPointPerA = warFamilyA.GetBuffResPointPer(tick)
    buffResPointPerB = warFamilyB.GetBuffResPointPer(tick)
    addResPointA = addResPointDict.get(familyIDA, 0) * (10000 + buffResPointPerA) / 10000.0 # ²»È¡Õû£¬Ö§³ÖСÊý
    addResPointB = addResPointDict.get(familyIDB, 0) * (10000 + buffResPointPerB) / 10000.0 # ²»È¡Õû£¬Ö§³ÖСÊý
    resPointA = warFamilyA.AddResPoint(addResPointA)
    resPointB = warFamilyB.AddResPoint(addResPointB)
    
    resWinPoint = GetResourceWinPoint()
    #if addResPointDict:
    #    GameWorld.DebugLog("Ôö¼ÓÏÉÃË×ÊÔ´: addResPointDict=%s,buffResPointPerAB(%s, %s),addResPointAB=(%s, %s),updResPointAB=(%s, %s)" 
    #                       % (addResPointDict, buffResPointPerA, buffResPointPerB, addResPointA, addResPointB, resPointA, resPointB))
    #else:
    #    GameWorld.DebugLog("ûÏÉÃËÔö¼Ó×ÊÔ´")
    if resPointA < resWinPoint and resPointB < resWinPoint:
        #GameWorld.DebugLog("ûÓÐÏÉÃ˵½´ï»ñʤ×ÊÔ´µã£¡")
        return
    
    GameWorld.Log("ÓÐÏÉÃË×ÊÔ´µãµ½´ïʤÀûÌõ¼þ, ±ÈÈü½áÊø!familyIDA=%s,resPointA=%s VS familyIDB=%s,resPointB=%s,resWinPoint=%s" 
                  % (familyIDA, resPointA, familyIDB, resPointB, resWinPoint))
    __DoLogicFamilyWarOver(tick) # Ö´ÐбÈÈü½áÊøÂß¼
    return True
def __AddFamilyResPoint(warFamily, resPointAdd, tick):
    # Ôö¼Ó×ÊÔ´µã£¬´ËÇé¿öÊÊÓÃÓÚ²»ÊÇÁ½¸öÏÉÃËͬʱ´¥·¢µÄ£¬¼ÓÍêºóÁ¢¼´ÅжÏÊÇ·ñ»ñʤ
    
    resPoint = warFamily.AddResPoint(resPointAdd)
    resWinPoint = GetResourceWinPoint()
    GameWorld.DebugLog("Ôö¼Ó×ÊÔ´µã: familyID=%s,resPointAdd=%s£¬updPoint=%s,resWinPoint=%s" 
                       % (warFamily.familyID, resPointAdd, resPoint, resWinPoint))
    if resPoint >= resWinPoint:
        __DoLogicFamilyWarOver(tick)
    return
def __RefreshRandBuff(tick):
    ## Ëæ»úbuff
    gameFB = GameWorld.GetGameFB()
    lastRefreshTick = gameFB.GetGameFBDictByKey(GameFBDict_RandBuffRefreshTick)
    if not lastRefreshTick:
        gameFB.SetGameFBDict(GameFBDict_RandBuffRefreshTick, tick)
        return
    
    if tick - lastRefreshTick < GetRandBuffRefreshTime() * 1000:
        return
    
    lastCollectTick = gameFB.GetGameFBDictByKey(GameFBDict_RandBuffCollectTick)
    if tick - lastCollectTick < 3000:
        # ¸Õ±»²ÉÍê3ÃëÄÚ²»ÂíÉÏË¢£¬·ÀÖ¹Ò»²ÉÍê¾ÍÂíÉϳöÀ´buff£¬Óиö»º³å
        return
    
    randPosList = GetRandBuffPosList()
    maxBuffCount = len(randPosList)
    emptyBuffPosIndexList = range(maxBuffCount)
    for i in xrange(maxBuffCount):
        if gameFB.GetGameFBDictByKey(GameFBDict_RandBuffObjID % i):
            emptyBuffPosIndexList.remove(i)
    if not emptyBuffPosIndexList:
        #GameWorld.DebugLog("³¬¹ý×î´óËæ»úbuffÊý£¬²»Ë¢Ð£¡")
        return
    
    lineID = GameWorld.GetGameWorld().GetLineID()
    randCount = min(GetRandBuffCount(), len(emptyBuffPosIndexList))
    randNPCIDList = GetRandBuffNPCIDList()
    for i in xrange(randCount):
        randNPCID = random.choice(randNPCIDList)
        randPosIndex = random.choice(emptyBuffPosIndexList)
        randPosX, randPosY = randPosList[randPosIndex]
        
        # ÕÙ»½³öËæ»úbuff
        randBuffNPC = NPCCommon.SummonMapNpc(randNPCID, randPosX, randPosY)
        if not randBuffNPC:
            continue
        emptyBuffPosIndexList.remove(randPosIndex)
        buffObjID = randBuffNPC.GetID()
        gameFB.SetGameFBDict(GameFBDict_RandBuffObjID % randPosIndex, buffObjID)
        GameWorld.Log("Ë¢ÐÂËæ»úbuff: lineID=%s,randPosIndex=%s,randNPCID=%s,buffObjID=%s" % (lineID, randPosIndex, randNPCID, buffObjID))
    
    # Ç¿Á¦BUFFÉú³ÉÔÚÕ½³¡ÄÚ£¬¿ì¿ìÈ¥Õù¶á
    PlayerControl.FBNotify("FamilyMatchBuff")
    gameFB.SetGameFBDict(GameFBDict_RandBuffRefreshTick, tick)
    return
def __DoLogicFamilyWarOver(tick):
    ## ±ÈÈü½áÊøÂß¼
    
    gameFB = GameWorld.GetGameFB()
    familyVsMgr = gameFB.GetFamilyVS()
    familyIDA = familyVsMgr.GetFamilyID()
    familyIDB = familyVsMgr.GetVSFamilyID()
    
    vsFamilyIDList = [familyIDA, familyIDB]
    vsFamilyIDList.sort(cmp=CmpFamilyWinner)
    winnerFamilyID = vsFamilyIDList[0]
    gameFB.SetGameFBDict(GameFBDict_WinnerFamilyID, winnerFamilyID)
    isFinalMatch = gameFB.GetGameFBDictByKey(GameFBDict_IsFinalMatch)
    roundNum = gameFB.GetGameFBDictByKey(GameFBDict_RoundNum)
    groupID = gameFB.GetGameFBDictByKey(GameFBDict_GroupID)
    lineID = GameWorld.GetGameWorld().GetLineID()
    
    winnerWarFamily = GetFamilyWarFamily(winnerFamilyID)
    winFaction = winnerWarFamily.faction
    winCount = winnerWarFamily.winCount + 1
    
    GameWorld.Log("±ÈÈü½áÊø: isFinalMatch=%s,roundNum=%s,groupID=%s,familyIDA=%s VS familyIDB=%s,winnerFamilyID=%s,winFaction=%s,winCount=%s" 
                  % (isFinalMatch, roundNum, groupID, familyIDA, familyIDB, winnerFamilyID, winFaction, winCount), lineID)
    
    # ͬ²½GameServer ±ÈÈü½á¹û
    msgInfo = str([familyIDA, familyIDB, winnerFamilyID, isFinalMatch])
    GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'FamilyWarOver', msgInfo, len(msgInfo))
    
    # »ñʤÏÉÃËÍæ¼Ò»ý·Ö¼Ó³É
    winnerScoreAddPer = GetScoreWinerAddPer()
    familyWarPlayerDict = FBCommon.GetGameFBData(GameFBData_FamilyWarPlayer)
    for playerID, warPlayer in familyWarPlayerDict.items():
        if warPlayer.familyID != winnerFamilyID:
            continue
        score = warPlayer.score
        warPlayer.score = int(score * (100 + winnerScoreAddPer) / 100.0)
        GameWorld.DebugLog("    »ñʤÏÉÃËÍæ¼Ò½áËã»ý·Ö¼Ó³É: familyID=%s,playerID=%s,score=%s,upScore=%s" 
                           % (warPlayer.familyID, playerID, score, warPlayer.score), lineID)
        
    rankAwardDict = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRankReward", 1)
    awardPerList = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRankReward", 2)
    joinAwardItemList = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRankReward", 3)
    
    if groupID <= 0:
        awardPer = awardPerList[0]
    elif groupID > len(awardPerList):
        awardPer = awardPerList[-1]
    else:
        awardPer = awardPerList[groupID - 1]
    rankAwardDictCopy = {}
    for rank, itemList in rankAwardDict.items():
        copyItemList = []
        for itemID, itemCount, isBind, isPer in itemList:
            if isPer: # ½±Àø¸öÊýÊÇ·ñÊܰٷֱÈÓ°Ïì, ĬÈÏÊÜÓ°Ïì
                copyItemList.append([itemID, max(1, int(itemCount * awardPer / 100.0)), isBind])
            else:
                copyItemList.append([itemID, itemCount, isBind])
        rankAwardDictCopy[rank] = copyItemList
        
    # ×î¸ß¼¶±ðÁªÈüµÚÒ»Ãû¶îÍâ½±Àø
    winnerFirstAwardEx = [] # »ñʤ·½µÚÒ»Ãû¶îÍâ½±Àø
    loserFirstAwardEx = [] # ʧ°Ü·½µÚÒ»Ãû¶îÍâ½±Àø
    firstAwardEx, firstAwardEx2= [], []
    if groupID == FamilyWar_MaxGroupID:
        worldLv = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)
        if isFinalMatch:
            firstAwardExDict = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchSRankOneReward", 1)
            firstAwardExDict2 = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchSRankOneReward", 2)
        else:
            firstAwardExDict = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRankOneReward", 1)
            firstAwardExDict2 = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchRankOneReward", 2)
        firstAwardEx = GameWorld.GetOrderValueByDict(firstAwardExDict, worldLv)
        firstAwardEx = [] if not firstAwardEx else firstAwardEx
        GameWorld.Log("×î¸ß¼¶±ðÁªÈüʤÕßµÚÒ»Ãû¶îÍâ½±Àø: firstAwardEx=%s,firstAwardExDict=%s,worldLv=%s" 
                      % (firstAwardEx, firstAwardExDict, worldLv), lineID)
        firstAwardEx2 = GameWorld.GetOrderValueByDict(firstAwardExDict2, worldLv)
        firstAwardEx2 = [] if not firstAwardEx2 else firstAwardEx2
        GameWorld.Log("×î¸ß¼¶±ðÁªÈü°ÜÕßµÚÒ»Ãû¶îÍâ½±Àø: firstAwardEx2=%s,firstAwardExDict2=%s,worldLv=%s" 
                      % (firstAwardEx2, firstAwardExDict2, worldLv), lineID)
        
    GameWorld.Log("Ãû´Î½±ÀøÅäÖÃ: rankAwardDict=%s,awardPer=%s,rankAwardDictCopy=%s,firstAwardEx=%s,joinAwardItemList=%s" 
                  % (rankAwardDict, awardPer, rankAwardDictCopy, firstAwardEx, joinAwardItemList), lineID)
    
    # ´Ë´¦½áËã½±ÀøµÈ
    joinPlayerIDList = [] # ²ÎÓëµÄÍæ¼ÒIDÁбí [playerID, ...]
    championPlayerIDList = [] # ¹Ú¾üÍæ¼ÒIDÁбí [playerID, ...]
    batchPlayerIDList, batchAddItemList, batchParamList = [], [], []
    
    leaveTime = GetFWarStepTime()[Time_Leave] * 1000
    sortWarPlayerList = SortFamilyWarPlayer()
    billboardPack = GetFamilyWarBillboardPack(gameFB, sortWarPlayerList, tick, winFaction)
    copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
    for rank, warPlayer in enumerate(sortWarPlayerList, 1):
        rankItemList = GameWorld.GetOrderValueByDict(rankAwardDictCopy, rank)
        if firstAwardEx and not winnerFirstAwardEx and warPlayer.familyID == winnerFamilyID:
            winnerFirstAwardEx = firstAwardEx
            awardItemList = rankItemList + winnerFirstAwardEx
            # %s0ÔÚÏÉÃËÁªÈüÖбíÏÖÓÅÒ죬»ñµÃ¶îÍâ½±Àø
            PlayerControl.WorldNotify(0, "FamilyMatchRankNoOne", [warPlayer.name, winnerFirstAwardEx[0][0]])
        elif firstAwardEx2 and not loserFirstAwardEx and warPlayer.familyID != winnerFamilyID:
            loserFirstAwardEx = firstAwardEx2
            awardItemList = rankItemList + loserFirstAwardEx
            PlayerControl.WorldNotify(0, "FamilyMatchRankNoOneLose", [warPlayer.name, loserFirstAwardEx[0][0]])
        else:
            awardItemList = rankItemList
        playerID = warPlayer.playerID
        GameWorld.Log("    ½±Àø:rank=%s,awardItemList=%s,playerID=%s,score=%s," % (rank, awardItemList, playerID, warPlayer.score), lineID)
        batchPlayerIDList.append([playerID])
        batchAddItemList.append(awardItemList)
        batchParamList.append([rank])
        joinPlayerIDList.append(playerID)
        if isFinalMatch and warPlayer.familyID == winnerFamilyID:
            championPlayerIDList.append(playerID)
            
        player = copyPlayerMgr.FindPlayerByID(playerID)
        if player:
            NetPackCommon.SendFakePack(player, billboardPack)
            player.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTime, True)
            PlayerFamily.AddFamilyActivity(player, ShareDefine.FamilyActive_War)
            
    # ÅÅÃû½±ÀøÓʼþ
    PlayerControl.SendMailBatch("FamilyMatchRankMail", batchPlayerIDList, batchAddItemList, batchParamList)
    # ²ÎÓë½±Óʼþ
    PlayerControl.SendMailByKey("FamilyMatchJoinMail", joinPlayerIDList, joinAwardItemList)
    # ³ÆºÅÓʼþ, Çø·ÖÃËÖ÷Óë³ÉÔ±£¬¸ÄΪʵʱ¸üÐÂ
    #if championPlayerIDList:
    #    titleItemID = IpyGameDataPY.GetFuncCfg("FamilyMatchDayReward", 2)
    #    PlayerControl.SendMailByKey("FamilyMatchTitleMail", championPlayerIDList, [[titleItemID, 1, 1]])
    
    FBCommon.SetFBStep(FB_Step_LeaveTime, tick)
    return
def CmpFamilyWinner(familyIDA, familyIDB):
    ## »ñʤÅÅÐò¹æÔò: ×ÊÔ´µã > Õ¼ÁìË®¾§Êý > Õ½³¡ÖÐÏÉÃËÈËÊý > ÏÉÃËÁбíÖÐÅÅÃû
    
    lineID = GameWorld.GetGameWorld().GetLineID()
    # ×ÊÔ´µã
    resPointA = GetFamilyWarFamily(familyIDA).GetResPoint()
    resPointB = GetFamilyWarFamily(familyIDB).GetResPoint()
    cmpRet = cmp(resPointB, resPointA) # µ¹Ðò
    GameWorld.Log("    ×ÊÔ´µãÊý: familyIDA=%s,familyIDB=%s,resPointB=%s,resPointA=%s,cmpRet=%s" 
                  % (familyIDA, familyIDB, resPointB, resPointA, cmpRet), lineID)
    if cmpRet != 0:
        return cmpRet
    
    gameFB = GameWorld.GetGameFB()
    # Õ¼ÁìË®¾§Êý
    getFlagCountA = 0
    getFlagCountB = 0
    resourceNPCIDList = GetResourceNPCIDList()
    for npcID in resourceNPCIDList:
        familyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if not familyID:
            continue
        if familyID == familyIDA:
            getFlagCountA += 1
        if familyID == familyIDB:
            getFlagCountB += 1
    cmpRet = cmp(getFlagCountB, getFlagCountA) # µ¹Ðò
    GameWorld.Log("    Õ¼ÁìË®¾§Êý: getFlagCountB=%s,getFlagCountA=%s,cmpRet=%s" % (getFlagCountB, getFlagCountA, cmpRet), lineID)
    if cmpRet != 0:
        return cmpRet
    
    # Õ½³¡ÖÐÏÉÃËÈËÊý
    familyPlayerCountA = 0
    familyPlayerCountB = 0
    copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(copyPlayerMgr.GetPlayerCount()):
        player = copyPlayerMgr.GetPlayerByIndex(index)
        if not player:
            continue
        familyID = player.GetFamilyID()
        if not familyID:
            continue
        if familyID == familyIDA:
            familyPlayerCountA += 1
        if familyID == familyIDB:
            familyPlayerCountB += 1
    cmpRet = cmp(familyPlayerCountB, familyPlayerCountA) # µ¹Ðò
    GameWorld.Log("    Õ½³¡ÖÐÏÉÃËÈËÊý: familyPlayerCountB=%s,familyPlayerCountA=%s,cmpRet=%s" % (familyPlayerCountB, familyPlayerCountA, cmpRet), lineID)
    if cmpRet != 0:
        return cmpRet
    
    # ÏÉÃËÁбíÖÐÅÅÃû, Ò»¶¨ÊDz»Ò»ÑùµÄ
    familyRankA = GetFamilyWarFamily(familyIDA).rank
    familyRankB = GetFamilyWarFamily(familyIDB).rank
    cmpRet = cmp(familyRankA, familyRankB) # ÕýÐò
    GameWorld.Log("    ÏÉÃËÁбíÖÐÅÅÃû: familyRankA=%s,familyRankB=%s,cmpRet=%s" % (familyRankA, familyRankB, cmpRet), lineID)
    return cmpRet
def __DoLogic_FB_Over(tick):
    remaindTick = GetFWarStepTime()[Time_Leave] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())
    if remaindTick > 0:
        return
    
    GameWorldProcess.CloseFB(tick)
    FBCommon.SetFBStep(FB_Step_Over, tick)
    return
## ÊÇ·ñ¸±±¾¸´»î
def OnPlayerReborn():
    return True
## ÖØÖø±±¾¸´»îÍæ¼Ò×ø±êµã
def OnResetFBRebornPlacePos(curPlayer, rebornPlace, tick):
    gameFB = GameWorld.GetGameFB()
    faction = curPlayer.GetFaction()
    factionIndex = GetFactionIndex(faction)
    posRankList = GetResourceRebornRank()[factionIndex]
    resNPCIDList = GetResourceNPCIDList()
    resRebornPosList = GetResourceRebornPosList()
    playerFamilyID = curPlayer.GetFamilyID()
    if len(resNPCIDList) != len(resRebornPosList):
        return
    
    for posRank in posRankList:
        index = posRank - 1
        if index < 0 or index >= len(resNPCIDList):
            continue
        npcID = resNPCIDList[index]
        flagFamilyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if playerFamilyID != flagFamilyID:
            #GameWorld.DebugLog("²»ÊÇÍæ¼ÒËùÊôÏÉÃËÕ¼ÁìµÄ×ÊÔ´£¡playerFamilyID=%s,flagFamilyID=%s,npcID=%s" 
            #                   % (playerFamilyID, flagFamilyID, npcID))
            continue
        randPosX, randPosY, randDist = random.choice(resRebornPosList[index])
        posPoint = GameMap.GetEmptyPlaceInArea(randPosX, randPosY, randDist)
        curPlayer.ResetPos(posPoint.GetPosX(), posPoint.GetPosY())
        GameWorld.DebugLog("Íæ¼ÒÓÅÏȸ´»îµã: faction=%s,posNum=%s,npcID=%s" % (faction, posRank, npcID))
        return
    
    # ĬÈÏÓªµØ
    centrePosX, centrePosY, radius = GetFactionArea()[factionIndex]
    posPoint = GameMap.GetEmptyPlaceInArea(centrePosX, centrePosY, radius)
    curPlayer.ResetPos(posPoint.GetPosX(), posPoint.GetPosY())
    GameWorld.DebugLog("Íæ¼ÒÓªµØ¸´»î: faction=%s" % (faction))
    return
##´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼
def DoFBOnKill_Player(curPlayer, defender, tick):
    playerID = curPlayer.GetPlayerID()
    
    killPlayerScore = GetScoreKillPlayer()
    warPlayer = GetFamilyWarPlayer(playerID)
    warPlayer.killPlayerCount += 1
    warPlayer.score += killPlayerScore
    GameWorld.DebugLog("»÷É±Íæ¼Ò: addScore=%s,score=%s,killPlayerCount=%s" 
                       % (killPlayerScore, warPlayer.score, warPlayer.killPlayerCount), playerID)
    return True
#¹ØÏµÓÐ3²ã£¬ÎÞ-ÓѺÃ-µÐÈË
##ÅжÏÊÇ·ñÓѺùØÏµ£¬¸Ã²ãÅж¨ÎªÓѺÃÂß¼ÖеÄ×îºóÅжÏ
def CheckPlayersRelation_IsFriend(curPlayer, curTagPlayer):
    return not __CanAttackPlayer(curPlayer, curTagPlayer)
##¸±±¾ÖÐ,¹¥»÷¶ÓÓÑÂß¼
def DoCanAttackTeamer(curPlayer, curTagPlayer):
    return __CanAttackPlayer(curPlayer, curTagPlayer)
def __CanAttackPlayer(curPlayer, curTagPlayer):
    if GameWorld.GetGameFB().GetFBStep() != FB_Step_Fighting:
        return False
    return curPlayer.GetFamilyID() != curTagPlayer.GetFamilyID()
## Íæ¼Ò¹¥»÷Íæ¼ÒÊÇ·ñÓгͷ£
def DoFBAttackHasPunish(atkPlayer, defPlayer):
    return False
## ¼ì²éÊÇ·ñ¿É¹¥»÷£¬ Ö÷Åж¨²»¿É¹¥»÷µÄÇé¿ö£¬ÆäËûÂß¼ÓÉÍâ²ã¾ö¶¨
def CheckCanAttackTagObjInFB(attacker, defender):
    if GameWorld.GetGameFB().GetFBStep() != FB_Step_Fighting:
        return False
    return True
##ÊÇ·ñ¿ÉÒÔ¶áÆì
# @param curPlayer Íæ¼ÒʵÀý
# @param curNPC NPCʵÀý
# @param tick ʱ¼ä´Á
# @return ÎÞÒâÒå
# @remarks
def OnCanCollect(curPlayer, curNPC, tick):
    npcID = curNPC.GetNPCID()
    familyID = curPlayer.GetFamilyID()
    
    GameWorld.DebugLog("OnCanCollect npcID=%s,familyID=%s" % (npcID, familyID), curPlayer.GetPlayerID())
    if not familyID:
        return False
    
    gameFB = GameWorld.GetGameFB()
    fbStep = gameFB.GetFBStep()
    
    # ·ÇÕ½¶·½×¶Î²»¿É²É¼¯
    if fbStep != FB_Step_Fighting:
        PlayerControl.NotifyCode(curPlayer, "NotFightStepCanNotCollect")
        return False
    
    if npcID in GetResourceNPCIDList():
        # ÒÑ»ñµÃÕ½ÆìµÄÕ½Ã˲»¿É²É¼¯
        getFlagFamilyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if getFlagFamilyID == familyID:
            PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_976459")
            return False
        
    return True
##¸±±¾ÖÐ,Õ¼ÁìNPCµÄLoadingʱ¼ä.
# @param curPlayer Íæ¼ÒʵÀý
# @param curNPC NPCʵÀý
# @return ·µ»ØÖµ, Loadingʱ¼ä
# @remarks ¸±±¾ÖÐ,Õ¼ÁìNPCµÄLoadingʱ¼ä
def GetFBPrepareTime(curPlayer, curNPC):
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    collectTimeList = GetCollectTimeList()
    cfgIndex = 1 if npcID in GetRandBuffNPCIDList() else 0
    
    tick = GameWorld.GetGameWorld().GetTick()
    warPlayer = GetFamilyWarPlayer(playerID)
    warPlayer.collectTypeIndex = cfgIndex
    warPlayer.collectLostHPTick = tick
    
    prepareTime = collectTimeList[cfgIndex] * 1000
    GameWorld.DebugLog("CollectPrepare npcID=%s,cfgIndex=%s,tick=%s,prepareTime=%s" % (npcID, cfgIndex, tick, prepareTime))
    return prepareTime
## ÊÕ¼¯ÖÐ
def OnCollecting(curPlayer, tick):
    playerID = curPlayer.GetPlayerID()
    warPlayer = GetFamilyWarPlayer(playerID)
    
    ## ÿÃëµôѪ£¬ÔÝдËÀ
    lostTime = (tick - warPlayer.collectLostHPTick) / 1000 # µôѪ´ÎÊý
    if not lostTime:
        return
    warPlayer.collectLostHPTick = tick
    
    lostHPPerList = GetCollectLostHPPerList()
    lostHPPer = lostHPPerList[warPlayer.collectTypeIndex]
    skillTypeID, buffOwner = 0, None
    lostValue = int(GameObj.GetMaxHP(curPlayer) * lostHPPer / 100.0) * lostTime
    #GameWorld.DebugLog("OnCollecting lostHPPer=%s,lostTime=%s,lostValue=%s" % (lostHPPer, lostTime, lostValue), playerID)
    SkillCommon.SkillLostHP(curPlayer, skillTypeID, buffOwner, lostValue, tick)
    return
##Íæ¼ÒÊÕ¼¯³É¹¦(Ëþ, Æì)
# @param curPlayer Íæ¼ÒʵÀý
# @param tick ʱ¼ä´Á
# @return ÎÞÒâÒå
# @remarks
def OnCollectOK(curPlayer, npcID, tick):
    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 GetResourceNPCIDList():
        __OnCollectOK_Resource(curPlayer, curNPC, tick)
        
    # Ëæ»úbuff
    else:
        __OnCollectOK_Buff(curPlayer, curNPC, tick)
    return
def __OnCollectOK_Resource(curPlayer, curNPC, tick):
    objID = curNPC.GetID()
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    GameWorld.Log("²É¼¯Ë®¾§ objID=%s,npcID=%s,familyID=%s" % (objID, npcID, familyID), playerID)
    
    gameFB = GameWorld.GetGameFB()
    lastFlagFamilyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
    nextFlagFamilyID = familyID
    if lastFlagFamilyID == nextFlagFamilyID:
        return
    
    # ¸üÐÂÕ½Æì¹éÊôÐÅÏ¢
    gameFB.SetGameFBDict(GameFBDict_GetFlagFamilyID % npcID, nextFlagFamilyID)
    gameFB.SetGameFBDict(GameFBDict_FamilyResPointTick % npcID, tick)
    
    collRescourceScoreDict = GetScoreCollectRescource()
    if npcID in collRescourceScoreDict:
        collRescourceScore = collRescourceScoreDict[npcID]
    else:
        collRescourceScore = collRescourceScoreDict[0]
    warPlayer = GetFamilyWarPlayer(playerID)
    warPlayer.collResourceCount += 1
    warPlayer.score += collRescourceScore
    GameWorld.DebugLog("    Íæ¼ÒÕ¼ÁìË®¾§: addScore=%s,score=%s,collResourceCount=%s" 
                       % (collRescourceScore, warPlayer.score, warPlayer.collResourceCount), playerID)
    
    # Õ¼Áì¹ã²¥¸ø¶ÔÊÖÕóÓª
    # ÓÐÒ»¸ö×ÊÔ´Ë®¾§±»µÐ·½Õ¼ÁìÁË£¬¿ìÈ¥ÇÀ¶á»ØÀ´
    PlayerControl.FBFactionNotifyOther(curPlayer.GetFaction(), "FamilyMatchOccupied")
    return
def __OnCollectOK_Buff(curPlayer, curNPC, tick):
    
    objID = curNPC.GetID()
    npcID = curNPC.GetNPCID()
    playerID = curPlayer.GetPlayerID()
    familyID = curPlayer.GetFamilyID()
    gameFB = GameWorld.GetGameFB()
    
    # ÉèÖÃbuff±»²É¼¯
    gameFB.SetGameFBDict(GameFBDict_RandBuffCollectTick, tick)
    for i in xrange(len(GetRandBuffPosList())):
        if objID == gameFB.GetGameFBDictByKey(GameFBDict_RandBuffObjID % i):
            gameFB.SetGameFBDict(GameFBDict_RandBuffObjID % i, 0)
            break
        
    collBuffScore = GetScoreCollectRandBuff()
    warPlayer = GetFamilyWarPlayer(playerID)
    warPlayer.collRandBuffCount += 1
    warPlayer.score += collBuffScore
    GameWorld.DebugLog("    Íæ¼ÒÕ¼ÁìBuff: addScore=%s,score=%s,collRandBuffCount=%s" 
                       % (collBuffScore, warPlayer.score, warPlayer.collRandBuffCount), playerID)
    
    warFamily = GetFamilyWarFamily(familyID)
    # Ôö¼ÓbuffЧ¹û
    buffSkill = curNPC.GetSkillManager().GetSkillByIndex(0)
    if buffSkill:
        buffSkillTypeID = buffSkill.GetSkillTypeID()
        GameWorld.Log("²É¼¯buff objID=%s,npcID=%s,familyID=%s,buffSkillTypeID=%s" 
                      % (objID, npcID, familyID, buffSkillTypeID), curPlayer.GetPlayerID())
        if buffSkillTypeID == ChConfig.Def_SkillID_FamilyWar_ResPointAdd:
            resPointAdd = buffSkill.GetEffect(0).GetEffectValue(0)
            warFamily.randBuffResPoint += resPointAdd
            __AddFamilyResPoint(warFamily, resPointAdd, tick)
        elif buffSkillTypeID == ChConfig.Def_SkillID_FamilyWar_ResPointAddPer:
            warFamily.randBuffResPointPerDict[tick] = [buffSkill.GetLastTime(), buffSkill.GetEffect(0).GetEffectValue(0)]
        elif buffSkillTypeID == ChConfig.Def_SkillID_FamilyWar_RandBuffAttr:
            warFamily.randBuffAttrLV += 1
            __AddFamilyWarBuff(familyID, buffSkillTypeID, tick, warFamily.randBuffAttrLV)
        elif buffSkillTypeID == ChConfig.Def_SkillID_FamilyWar_OwnerlessBuff:
            familyVsMgr = gameFB.GetFamilyVS()
            familyIDA = familyVsMgr.GetFamilyID()
            familyIDB = familyVsMgr.GetVSFamilyID()
            tagFamilyID = familyIDB if familyID == familyIDA else familyIDA
            __RandBuffOwnerless(warFamily.faction, familyID, tagFamilyID, buffSkill.GetEffect(0).GetEffectValue(0))
        else:
            GameWorld.ErrLog("²»Ö§³Ö¸ÃËæ»úbuffЧ¹û£¡npcID=%s,buffSkillTypeID=%s" % (npcID, buffSkillTypeID))
            
        # BUFFÒѱ»¼º·½ÏÉÃË»ñµÃ£¬Ê¿Æø´óÕÇ
        # BUFFÒѱ»µÐ·½ÏÉÃË»ñµÃ£¬Å¬Á¦Õù¶áÏÂÒ»¸ö£¬²»ÒªÆøÄÙ
        PlayerControl.FBFactionNotify(curPlayer.GetFaction(), "FamilyMatchBuffOccupied", [buffSkillTypeID], 
                                      "FamilyMatchBuffOccupiedEnimy", [buffSkillTypeID])
    else:
        GameWorld.ErrLog("Ëæ»úbuffûÅäÖòɼ¯Ð§¹û£¡npcID=%s" % npcID)
        
    NPCCommon.SetDeadEx(curNPC)
    return
def __AddFamilyWarBuff(familyID, buffSkillTypeID, tick, skillLV=None, isDelFirst=False):
    ## ¸øÏÉÃ˳ÉÔ±¼Óbuff
    buffSkill = GameWorld.GetGameData().GetSkillBySkillID(buffSkillTypeID)
    if not buffSkill:
        return
    GameWorld.DebugLog("ÏÉÃ˳ÉÔ±¼ÓBuff(%s): familyID=%s,buffSkillTypeID=%s,skillLV=%s,isDelFirst=%s" 
                       % (buffSkill.GetSkillName(), familyID, buffSkillTypeID, skillLV, isDelFirst))
    maxSkillLV = buffSkill.GetSkillMaxLV()
    if skillLV > maxSkillLV:
        skillLV = maxSkillLV
        GameWorld.DebugLog("    ³¬¹ý×î´ó¼¼Äܵȼ¶£¬È¡×î´ó¼¼Äܵȼ¶!skillLV=%s" % skillLV)
        
    playerManager = GameWorld.GetMapCopyPlayerManager()
    for index in xrange(playerManager.GetPlayerCount()):
        curPlayer = playerManager.GetPlayerByIndex(index)
        playerID = curPlayer.GetPlayerID()
        if not playerID:
            continue
        if curPlayer.GetFamilyID() != familyID:
            continue
        #Ìí¼Ó½ÏµÍ¼¶µÄbuff£¬ÐèÒªÏÈɾ³ý
        if isDelFirst:
            BuffSkill.DelBuffBySkillID(curPlayer, buffSkillTypeID, tick)
        SkillCommon.AddBuffBySkillType(curPlayer, buffSkillTypeID, tick, skillLV)
        
    return
def __RandBuffOwnerless(faction, curFamilyID, tagFamilyID, randCount):
    # Ë®¾§×ÊÔ´
    
    randResNPCIDList = []
    gameFB = GameWorld.GetGameFB()
    for npcID in GetResourceNPCIDList():
        curNPC = GameWorld.FindNPCByNPCID(npcID)
        if not curNPC:
            continue
        familyID = gameFB.GetGameFBDictByKey(GameFBDict_GetFlagFamilyID % npcID)
        if not familyID:
            continue
        
        if familyID == tagFamilyID:
            randResNPCIDList.append(npcID)
            
    GameWorld.DebugLog("²É¼¯ÎÞÖ÷buff: curFamilyID=%s,tagFamilyID=%s,randResNPCIDList=%s" 
                       % (curFamilyID, tagFamilyID, randResNPCIDList))
    random.shuffle(randResNPCIDList)
    GameWorld.DebugLog("    ´òÂÒºó: randResNPCIDList=%s,randCount=%s" % (randResNPCIDList, randCount))
    
    ownerLessNPCIDList = randResNPCIDList[:randCount]
    for npcID in ownerLessNPCIDList:
        gameFB.SetGameFBDict(GameFBDict_GetFlagFamilyID % npcID, 0)
        PlayerControl.FBFactionNotify(faction, "FamilyWarIneffctive1", [], "FamilyWarIneffctive2", [])
        
    if not ownerLessNPCIDList:
        PlayerControl.FBFactionNotify(faction, "FamilyWarIneffctive3", [], "FamilyWarIneffctive4", [])
    return
## ------------------------------------------------------------------------
def GetChampionFamilyDailyReward(curPlayer):
    ## ¹Ú¾üÏÉÃËÿÈÕٺ»½±Àø
    
    playerID = curPlayer.GetPlayerID()
    curFamilyID = curPlayer.GetFamilyID()
    if not curFamilyID:
        GameWorld.DebugLog("¹Ú¾üÏÉÃËÿÈÕٺ»½±Àø£¬ÎÞÏÉÃË£¬²»¿ÉÁì½±!", playerID)
        return
    
    championFamilyID = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_ChampionFamilyID)
    if curFamilyID != championFamilyID:
        GameWorld.DebugLog("¹Ú¾üÏÉÃËÿÈÕٺ»½±Àø, Íæ¼ÒÏÉÃË·Ç»ñʤÏÉÃË£¬²»¿ÉÁì½±!championFamilyID=%s,curFamilyID=%s" 
                           % (championFamilyID, curFamilyID), playerID)
        return
    
    dailyRewardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyWarDailyReward)
    if dailyRewardState:
        # ÒÑÁìÈ¡¹ý¸Ã½±Àø
        PlayerControl.NotifyCode(curPlayer, 'GeRen_admin_327925')
        return
    
    itemList = IpyGameDataPY.GetFuncEvalCfg("FamilyMatchDayReward")
    if not itemList:
        return
    
    needSpace = len(itemList)
    # ±³°ü¿Õ¼ä
    packSpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)
    if packSpace < needSpace:
        PlayerControl.NotifyCode(curPlayer, "GeRen_lhs_202580")
        return
    
    # ÉèÖÃÁì½±¼Ç¼Ϊ1£¬Í¨Öª¿Í»§¶Ë
    PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_FamilyWarDailyReward, 1)
    
    Sync_ChampionFamilyDailyRewardState(curPlayer)
    
    for itemID, itemCnt, isBind in itemList:
        ItemControler.GivePlayerItem(curPlayer, itemID, itemCnt, isBind, [IPY_GameWorld.rptItem])
        
    GameWorld.DebugLog("ÁìÈ¡ÍõÕßÏÉÃËÿÈÕٺ»: itemList=%s" % itemList, playerID)
    return
def Sync_ChampionFamilyDailyRewardState(curPlayer):
    clientPack = ChPyNetSendPack.tagMCChampionFamilyDailyReward()
    clientPack.GetState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_FamilyWarDailyReward)
    NetPackCommon.SendFakePack(curPlayer, clientPack)
    return