| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_MergeBoss  | 
| #  | 
| # @todo:¿ç·þbossÕ½³¡  | 
| # @author hxp  | 
| # @date 2015-9-23  | 
| # @version 1.5  | 
| #  | 
| # ÏêϸÃèÊö: ¿ç·þbossÕ½³¡  | 
| # @change: "2015-10-10 10:10" hxp È¥³ý¹ú¼ÒÉèÖã¬Ö»ÓÃÕóÓª£»Ôö¼Ó¶àµØÍ¼Ö§³ÖÐÞ¸Ä  | 
| # @change: "2015-10-29 15:30" hxp »î¶¯½áÊøºó£¬bossδ»÷ɱҲ¿É»ñµÃÉ˺¦ÅÅÐн±Àø  | 
| # @change: "2017-05-23 10:30" hxp ÐÞ¸ÄÓÀºã°æÏµÍ³Ìáʾ£»ÐÞ¸´µôÏßÖØÐÂÔÙ½øÈëʱÕóÓª×ÜÕ½Á¦Öظ´ÀÛ¼ÆÎÊÌâ  | 
| # @change: "2017-07-06 20:30" hxp ¸ÄΪ¸±±¾µØÍ¼£»Ö§³ÖÖ¸¶¨µØÍ¼¼°°´ÈËÊý·ÖÅäµØÍ¼Á½ÖÖģʽ²¢´æ  | 
| # @change: "2017-07-11 16:00" hxp ¿ç·þbossÊ״βÎÓë½±Àø  | 
| #  | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2017-07-11 16:00"""  | 
| #---------------------------------------------------------------------  | 
|   | 
| import ChConfig  | 
| import GameWorld  | 
| import ReadChConfig  | 
| import IPY_GameWorld  | 
| import NPCCustomRefresh  | 
| import GameWorldProcess  | 
| import PlayerControl  | 
| import ShareDefine  | 
| import ChPyNetSendPack  | 
| import NetPackCommon  | 
| import ItemControler  | 
| import ItemCommon  | 
| import SkillCommon  | 
| import FBCommon  | 
| import GameMap  | 
| import NPCCommon  | 
| import BuffSkill  | 
| import ChNPC  | 
| import GameObj  | 
| import random  | 
|   | 
| #µ±Ç°¸±±¾µØÍ¼µÄ״̬  | 
| (  | 
| FB_State_Open, # µØÍ¼¿ªÆô  | 
| FB_State_MapPrepare, # µØÍ¼×¼±¸  | 
| FB_State_MapPrepareNotify, # µØÍ¼×¼±¸µ¹¼ÆÊ±ÌØÐ§  | 
| FB_State_Fight, # Õ½¶·  | 
| FB_State_FreeTime, # ×ÔÓÉʱ¼ä  | 
| FB_State_Over, # ¸±±¾¹Ø±Õ  | 
| ) = range(6)  | 
|   | 
| #---¸±±¾ÅäÖöÔÓ¦keyÖµ---  | 
| (  | 
| Def_NotifyStartList, # Ìáʾ¿ªÊ¼Ê±¼äÁбí0  | 
| Def_NotifyEndList, # Ìáʾ½áÊøÊ±¼äÁбí1  | 
| Def_Time_MapPrepare, # ¸±±¾×¼±¸Ê±¼ä2  | 
| Def_Time_MapPrepareNotify, # ×¼±¸ÌØÐ§Ê±¼ä3  | 
| Def_Time_Fight, # ½øÐÐʱ¼ä4  | 
| Def_FBLeaveTime, # Í˳öʱ¼ä5  | 
| Def_CountryInfo, # [[°óÕóÓªÌØÐ§buffID, ·ÖÅäÕóÓªÌáʾmark, ¼¯ºÏµã×ø±ê, ¸´»î×ø±êµã], ...]6  | 
| Def_BossRefreshMarkList, # boss½×¶Î¶ÔÓ¦±êʶµãÁбí7  | 
| Def_BossRefreshNPCIDList, # boss½×¶Î¶ÔÓ¦bossIDÁбí8  | 
| Def_BossAwardMaxOrder, # µ¥bossÉ˺¦½±ÀøÏÞÖÆ×î´óÅÅÐÐ9  | 
| Def_BuffNPCID, # buffNPCID 10  | 
| Def_BuffCollectTime, # buff²É¼¯Ê±¼ä11  | 
| Def_BuffGongXun, # buff²É¼¯¿É»ñµÃ¹¦Ñ«12  | 
| Def_EndDelayTime, # ×¼ñ¶«Î÷ÑÓ³Ù½áËãʱ¼ä13  | 
| Def_EnterPosList, # ½øÈ븱±¾×ø±ê14  | 
| ) = range(15)  | 
|   | 
| # ¸±±¾key  | 
| FBDict_CountryFightpower = "FBD_CountryFightpower_%s" # ¸±±¾¸÷ÕóÓª×ÜÕ½Á¦, ²ÎÊý[ÕóÓª±àºÅ]  | 
| FBDict_BossStep = "FBD_BossStep" # µ±Ç°Ë¢ÐÂboss½×¶Î, ´Ó1¿ªÊ¼  | 
| FBDict_KillBossCnt = "FBD_KillBossCnt" # µ±Ç°½×¶ÎÒÑ»÷ɱbossÊý  | 
| FBDict_BossCountryHurt = "BossHurt_%s_%s_%s" # µ¥¸öboss¶ÔÓ¦ÕóÓª×ÜÉ˺¦,²ÎÊý(bossObjID, npcID, ÕóÓªID)  | 
| FBDict_BossHPPerMark = "BossHPPerMark_%s_%s" # µ¥¸öbossѪÁ¿°Ù·Ö±È±ê¼Ç,²ÎÊý(bossObjID, npcID)  | 
| FBDict_AllBossCountryHurt = "FBD_AllHurtValue_%s" # ËùÓÐboss¶ÔÓ¦ÕóÓª×ÜÉ˺¦ÇóÓàÖµ,²ÎÊý(ÕóÓªID)  | 
| FBDict_AllBossCountryHurtPoint = "FBD_AllHurtPoint_%s" # ËùÓÐboss¶ÔÓ¦ÕóÓª×ÜÉ˺¦ÀÛ¼ÆÉ˺¦µã,²ÎÊý(ÕóÓªID)  | 
| FBDict_LastRefreshBossTick = "FBD_LastRefreshBossTick" # ÉÏÒ»´ÎbossË¢ÐÂ״̬tick  | 
| FBDict_EndDelayStartTime = "FBD_EndDelayStartTime" # ÑÓ³Ù½áË㿪ʼtick  | 
|   | 
| # ¸±±¾Íæ¼Ò×Öµäkey  | 
| FBPlayerDict_Country = "FBPlayerDict_Country" # Íæ¼Ò¹ú¼ÒÕóÓª  | 
| FBPlayerDict_GongXun = "FBPlayerDict_GongXun" # Íæ¼Ò±¾´Î»ñµÃµÄ¹¦Ñ«  | 
|   | 
| # boss±»»÷ɱ˲¼ä»áÓõ½£¬Ò»°ãÖØ¶Á½Å±¾²»»áÓÐʲôӰÏì  | 
| g_lastHurtPlayerIDDict = {}  # boss×îºóÒ»»÷Íæ¼ÒID¶ÔÓ¦×Öµä{objID_npcID:playerID, ...}  | 
| g_lastHurtPlayerNameDict = {}  # boss×îºóÒ»»÷Íæ¼ÒID¶ÔÓ¦×Öµä{objID_npcID:playerName, ...}  | 
|   | 
| # µ¥bossÕóÓªÉ˺¦{"objID_npcID_factionID":value, ...}, ÖضÁ¿ÉÄܵ¼Ö¿ͻ§¶ËÒÑ»÷ɱµÄbossÏÔʾÒì³£  | 
| g_bossFactionHurtDict = {}  | 
|   | 
| # 10Ãë»áË¢ÐÂÒ»´Î£¬ÖضÁ½Å±¾²»»áÓÐʲôӰÏì, Ö»ÊÇÒѱ»»÷ɱµÄbossÔÚÏÂÒ»½×¶ÎÏÔʾ¿ÉÄÜ»áÒì³£  | 
| g_curBossDict = {} # µ±Ç°bossID×ÖµäÐÅÏ¢{objID_npcID:[objID,npcID,curHP,maxHP,posX,posY], ...}  | 
|   | 
| # buffNPC¹éÊôbossÐÅÏ¢  | 
| g_buffOwnerNPCDict = {} # {buffObjID_npcID:bossObjID_npcID, ...}  | 
| # bossµ±Ç°²úÉúµÄ»¹Î´²É¼¯µÄbuffNPC¸öÊýÐÅÏ¢  | 
| g_bossBuffCntDict = {} # {bossObjID_npcID:buffCnt,...}  | 
| # ÕóÓª¶ÔÓ¦µÄbuff  | 
| g_factionBuffDict = {} # {factionID:{buffID:[addTick,lastTime],...}, ...}  | 
|   | 
| # ÓвμӸûµÄÍæ¼ÒÁÐ±í£¬°üº¬ÏÂÏߵģ¬ÖضÁ¿ÉÄܵ¼ÖÂÀëÏßÍæ¼ÒÊÕ²»µ½½áËã½±ÀøÓʼþ  | 
| g_joinPlayerIDList = []  | 
|   | 
| def DoMergeBossPlayerLogin(curPlayer):  | 
|     if GameWorld.IsMergeServer():  | 
|         return  | 
|     Sync_MergeBossAwardRecord(curPlayer)  | 
|     return  | 
|   | 
| ##---»ñµÃ¸±±¾ÅäÖÃ---  | 
| #  @param None  | 
| #  @return ÅäÖÃÐÅÏ¢  | 
| def GetMergeBossCfg():          | 
|     return ReadChConfig.GetEvalChConfig("MergeBoss_Cfg")    | 
|   | 
| ## ¿ç·þboss»î¶¯±ä¸ü  | 
| #  @param value: ×´Ì¬Öµ  | 
| #  @param tick  | 
| #  @return  | 
| def OnMergeBossStateChange(value, tick):  | 
|     # ·Ç¿ç·þ²»´¦Àí  | 
|     if not GameWorld.IsMergeServer():  | 
|         GameWorld.DebugLog("·Ç¿ç·þ²»´¦Àí¿ç·þbossÕ½³¡×´Ì¬±ä¸ü£¡")  | 
|         return  | 
|       | 
|     curState = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_MergeBoss)  | 
|       | 
|     # ±¾µØÍ¼ÒÑÊǸÃÖµ£¬²»´¦Àí£¬ÆäËûµØÍ¼Æô¶¯»áÔÙ´Îͬ²½  | 
|     if curState == value:  | 
|         GameWorld.DebugLog("OnMergeBossStateChange ÒÑÊǸÃÖµ£¬²»´¦Àí£¡value=%s" % value)  | 
|         return  | 
|       | 
| #    if value == ChConfig.Def_Action_Open:  | 
| #        __OnOpen(tick)  | 
|     if value == ChConfig.Def_Action_Close:  | 
|         GameWorld.Log("¿ªÊ¼¹Ø±Õ¸±±¾!")  | 
|         gameFB = GameWorld.GetGameFB()  | 
|         fbStep = gameFB.GetFBStep()  | 
|         if fbStep == FB_State_Fight:  | 
|             GameWorld.Log("Õ½¶·½áËãÇ¿ÖÆ¹Ø±Õ¸±±¾£¬Ç¿ÖƽáËã!")  | 
|             __MergeBossOver(tick)  | 
|         GameWorldProcess.CloseFB(tick)  | 
|     return  | 
|   | 
| ##¸±±¾¿ªÆôʱ¼ä  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks  | 
| def OnCanOpen(tick):  | 
|     curState = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_MergeBoss)  | 
|     if not curState:  | 
|         return False  | 
|     GameWorld.Log("×¼±¸¿ªÆô¿ç·þboss¸±±¾£¡")  | 
|     return True  | 
|   | 
| ##¿ªÆô¸±±¾  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ¿ªÆô¸±±¾  | 
| def OnOpenFB(tick):  | 
|     __OnOpen(tick)  | 
|     return  | 
|   | 
|   | 
| ## ¿ç·þboss__OnOpen  | 
| #  @param tick  | 
| #  @return  | 
| def __OnOpen(tick):  | 
|     GameWorld.Log("MergeBoss __OnOpen ...")  | 
|       | 
|     __ResetFBData()  | 
|   | 
|     FBCommon.SetFBStep(FB_State_MapPrepare, tick)  | 
|           | 
| #    # µØÍ¼Íæ¼Ò¼ÓÈëÕ½³¡, ·ÀÖ¹Íæ¼Ò½øÈë¿ç·þbossÕ½³¡Ê±£¬»î¶¯»¹Î´¿ªÊ¼  | 
| #    # Ôڻ¿ªÊ¼Ê±Í¬Ò»¶Ôµ±Ç°ÒÑÔڸõØÍ¼µÄÍæ¼Ò½øÐмÓÈëÕ½³¡´¦Àí  | 
| #    # ¸ÃÔÒòÖ÷ÒªÊÇÒòΪ×Ó·þ¸ú¿ç·þʱ¼ä¿ÉÄÜÓÐÒ»¶¨²îÒìµÄÔÒò  | 
| #    playerManager = GameWorld.GetMapCopyPlayerManager()  | 
| #    for index in xrange(playerManager.GetPlayerCount()):  | 
| #        curPlayer = playerManager.GetPlayerByIndex(index)  | 
| #        if not curPlayer:  | 
| #            continue  | 
| #          | 
| #        __DoPlayerJoinMergeBoss(curPlayer, tick)  | 
|           | 
|     return  | 
|   | 
| ## ¿ç·þboss¹Ø±Õ  | 
| #  @param tick  | 
| #  @return  | 
| def __OnClose(tick):  | 
|     GameWorld.Log("MergeBoss __OnClose ...")  | 
|     __ResetFBData()  | 
|     FBCommon.SetFBStep(FB_State_Over, tick)  | 
|     return  | 
|   | 
| ## ÖØÖø±±¾Êý¾Ý  | 
| #  @param None  | 
| #  @return  | 
| def __ResetFBData():  | 
|     global g_lastHurtPlayerNameDict  | 
|     global g_lastHurtPlayerIDDict  | 
|     global g_bossFactionHurtDict  | 
|     global g_curBossDict  | 
|     global g_buffOwnerNPCDict  | 
|     global g_bossBuffCntDict  | 
|     global g_factionBuffDict  | 
|     global g_joinPlayerIDList  | 
|       | 
|     GameWorld.Log("MergeBoss __ResetFBData ...")  | 
|     g_lastHurtPlayerNameDict = {}  | 
|     g_lastHurtPlayerIDDict = {}  | 
|     g_bossFactionHurtDict = {}  | 
|     g_curBossDict = {}  | 
|     g_buffOwnerNPCDict = {}  | 
|     g_bossBuffCntDict = {}  | 
|     g_factionBuffDict = {}  | 
|     g_joinPlayerIDList = []  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     gameFB.ClearGameFBDict()  | 
|     gameFB.ClearAllPlayerGameFBDict()  | 
|       | 
|     FBCommon.ClearFBNPC()  | 
|     return  | 
|   | 
| ## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineID Ïß·id  | 
| #  @param tick Ê±¼ä´Á  | 
| #  @return ²¼¶ûÖµ  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     return True  | 
|   | 
| ##ÊÇ·ñ¿ÉÒÔ½øÈë  | 
| # @param ask ÇëÇó½á¹¹Ìå  | 
| # @param tick Ê±¼ä´Á  | 
| # @return  | 
| def OnChangeMapAsk(ask, tick):  | 
|     if GameWorld.GetGameWorld().GetOpenState() != IPY_GameWorld.fbosOpen:  | 
|         return IPY_GameWorld.cmeNotInFbDefineTime  | 
|       | 
|     if GameWorld.GetGameWorld().GetOpenState() == IPY_GameWorld.fbosClosed:  | 
|         return IPY_GameWorld.cmeNotInFbDefineTime  | 
|       | 
| #    curStep = GameWorld.GetGameFB().GetFBStep()     | 
| #    if curStep not in [FB_State_MapPrepare, FB_State_MapPrepareNotify, FB_State_Fight]:  | 
| #        return IPY_GameWorld.cmeNotInFbDefineTime  | 
|       | 
|     return IPY_GameWorld.cmeAccept  | 
|   | 
| ##¸±±¾Íæ¼Ò½øÈëµã  | 
| def OnGetFBEnterPos(curPlayer, mapID, lineId, tick):  | 
|     enterPos = random.choice(GetMergeBossCfg()[Def_EnterPosList])  | 
|     dist = 3 if len(enterPos) <= 2 else enterPos[2]  | 
|     posPoint = GameMap.GetEmptyPlaceInArea(enterPos[0], enterPos[1], dist)  | 
|     return posPoint.GetPosX(), posPoint.GetPosY()  | 
|   | 
| ##Íæ¼Ò½øÈ븱±¾  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks Íæ¼Ò½øÈ븱±¾  | 
| def DoEnterFB(curPlayer, tick):  | 
|     GameWorld.Log("DoEnterFB...")  | 
|       | 
|     __DoPlayerJoinMergeBoss(curPlayer, tick)   | 
|     return  | 
|   | 
| ##Íæ¼Ò¼ÓÈë¿ç·þboss  | 
| def __DoPlayerJoinMergeBoss(curPlayer, tick):  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     mapPrepareNotify = mergeBossCfg[Def_Time_MapPrepareNotify] * 1000      | 
|     if fbStep == FB_State_MapPrepare:  | 
|         #³õʼ»¯²¢Í¨ÖªµÈ´ýµ¹¼ÆÊ±  | 
|         EnterFBInPrepare(curPlayer, mergeBossCfg[Def_Time_MapPrepare] * 1000   | 
|                          + mapPrepareNotify, gameFB, tick)  | 
|     elif fbStep == FB_State_MapPrepareNotify:  | 
|         #³õʼ»¯²¢Í¨ÖªµÈ´ýµ¹¼ÆÊ±´øÌØÐ§  | 
|         EnterFBInPrepare(curPlayer, mapPrepareNotify, gameFB, tick, True)  | 
|   | 
|     elif fbStep == FB_State_Fight:  | 
|         #֪ͨ½øÈëʱ¼ä  | 
|         notifyTick = max(mergeBossCfg[Def_Time_Fight] * 1000 - (tick - gameFB.GetFBStepTick()), 0)  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttFlagTake, 0, notifyTick, True)  | 
|           | 
|         # ÕâÀïÓÃÕâÑù´æ´¢Ö÷Òª·ÀÖ¹Íæ¼ÒµôÏߺóÖØÐÂÉÏ´«Êý¾Ýµ½¿ç·þ·þÎñÆ÷ʱCoutryÖµ±»¸²¸Ç  | 
|         pCountry = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_Country)  | 
|           | 
|         # ÉèÖÃÕóÓª  | 
|         countryInfo = mergeBossCfg[Def_CountryInfo]  | 
|         if pCountry > 0 and pCountry <= len(countryInfo):  | 
|             GameWorld.Log("    ÒÑ´æÔÚÕóÓª£¬ÉèÖÃÕóÓª%s" % pCountry, playerID)  | 
|             SetPlayerCampInfo(curPlayer, pCountry, countryInfo[pCountry - 1], tick, False)  | 
|         else:  | 
|             GameWorld.Log("    ²»´æÔÚÕóÓª£¬·ÖÅäÕóÓª!", playerID)  | 
|             __DistributeCountryByEnter(curPlayer, tick)  | 
|     elif fbStep >= FB_State_FreeTime:  | 
|         GameWorld.Log("·Ç¿ç·þboss»î¶¯Ê±¼ä½øÈëµØÍ¼...fbStep=%s" % fbStep, curPlayer.GetPlayerID())  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, mergeBossCfg[Def_FBLeaveTime] * 1000, True)  | 
|           | 
|     return  | 
|   | 
| ##ÉèÖÃÍæ¼ÒµÄÕóÓªÏà¹ØÐÅÏ¢£¬ÔÚÕóÓª·ÖÅäºó  | 
| # @param curPlayer Íæ¼Ò  | 
| # @param country ¹ú¼ÒÕóÓª  | 
| # @param countryInfo ÕóÓªÐÅÏ¢  | 
| # @param tick  Ê±ÖÓ  | 
| # @return None  | 
| def SetPlayerCampInfo(curPlayer, country, countryInfo, tick, isAddFightPower=True):  | 
|     global g_joinPlayerIDList  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     if playerID not in g_joinPlayerIDList:  | 
|         g_joinPlayerIDList.append(playerID)  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     buffTypeID, notifyMsg, gatherPos, bornPos = countryInfo  | 
|     curPlayer.SetFaction(country)  | 
|     #curPlayer.SetCountry(country)  | 
|     gameFB.SetPlayerGameFBDict(curPlayer.GetPlayerID(), FBPlayerDict_Country, country)  | 
|       | 
|     # ¸´»îµã  | 
|     curPlayer.SetFBRebornMapID(GameWorld.GetMap().GetMapID())  | 
|     curPlayer.SetFBRebornPosX(bornPos[0])  | 
|     curPlayer.SetFBRebornPosY(bornPos[1])  | 
|   | 
|     # ·ÖÇøÓò  | 
|     posPoint = GameMap.GetEmptyPlaceInArea(gatherPos[0], gatherPos[1], 3)  | 
|     GameWorld.ResetPlayerPos(curPlayer, posPoint.GetPosX(), posPoint.GetPosY())  | 
|       | 
|     SkillCommon.AddBuffBySkillType(curPlayer, buffTypeID, tick)  | 
|     if notifyMsg:  | 
|         PlayerControl.NotifyCode(curPlayer, notifyMsg)  | 
|           | 
|     #¸üÐÂÕóÓª×ÜÕ½Á¦  | 
|     nowFightPower = gameFB.GetGameFBDictByKey(FBDict_CountryFightpower % country)  | 
|     if isAddFightPower:  | 
|         updFightPower = nowFightPower + curPlayer.GetFightPower()  | 
|         updFightPower = min(updFightPower, ChConfig.Def_UpperLimit_DWord)  | 
|         gameFB.SetGameFBDict(FBDict_CountryFightpower % country, updFightPower)  | 
|         GameWorld.DebugLog("ÉèÖÃÍæ¼ÒÕóÓª: country=%s,fightPower=%s,updFightPower=%s"   | 
|                            % (country, curPlayer.GetFightPower(), updFightPower), playerID)  | 
|     else:  | 
|         GameWorld.DebugLog("ÉèÖõôÏßÍæ¼ÒÕóÓª: country=%s,nowFightPower=%s" % (country, nowFightPower), playerID)  | 
|           | 
|     return  | 
|   | 
| ##Íæ¼ÒÔÚ×¼±¸Ê±¼ä½øÈëFBÂß¼  | 
| # @param curPlayer Íæ¼Ò  | 
| # @param downTime µ¹¼ÆÊ±Ê±¼ä  | 
| # @param gameFB ¸±±¾ÊµÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @param notifyEff ÊÇ·ñÍ¨ÖªÌØÐ§  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def EnterFBInPrepare(curPlayer, downTime, gameFB, tick, notifyEff=False):  | 
|       | 
|     #֪ͨ׼±¸µ¹¼ÆÊ±  | 
|     notifyTick = max(downTime - (tick - gameFB.GetFBStepTick()), 0)  | 
|     curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, notifyTick, True)  | 
|       | 
|     if notifyEff:  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttAddUpTime, 0, notifyTick, True)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def DoExitFB(curPlayer, tick):  | 
|     __DoPlayerExitFB(curPlayer, tick)  | 
|     return  | 
|   | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     __DoPlayerExitFB(curPlayer, tick)  | 
|     return  | 
|   | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾´¦Àí.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def __DoPlayerExitFB(curPlayer, tick):  | 
|   | 
|     return  | 
|   | 
|   | 
| ##¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep == FB_State_MapPrepare:  | 
|         __DoLogic_MapPrepare(tick)  | 
|     elif fbStep == FB_State_MapPrepareNotify:  | 
|         __DoLogic_MapPrepareNotify(tick)  | 
|     elif fbStep == FB_State_Fight:  | 
|         __DoLogic_Fight(tick)  | 
|     elif fbStep == FB_State_FreeTime:  | 
|         __DoLogic_FreeTime(tick)  | 
|     return  | 
|   | 
| ##ͬ²½¸±±¾ÖÐËùÓÐÍæ¼Ò¸±±¾°ïÖúÐÅÏ¢  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def __Sync_FBPlayerHelp(tick):  | 
|     playManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in xrange(playManager.GetPlayerCount()):  | 
|         player = playManager.GetPlayerByIndex(i)  | 
|         if not player:  | 
|             continue  | 
|         DoFBHelp(player, tick)  | 
|     return  | 
|           | 
| ##»ñµÃ¸±±¾°ïÖúÐÅÏ¢, ÓÃÓÚ֪ͨÕóÓª±È·ÖÌõ  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ÓÃÓÚ֪ͨÕóÓª±È·ÖÌõ  | 
| def DoFBHelp(curPlayer, tick):  | 
|     global g_bossFactionHurtDict  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     bossStep = gameFB.GetGameFBDictByKey(FBDict_BossStep)  | 
|       | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|       | 
|     factionTotalHurtDict = {} # ÕóÓª×ÜÉ˺¦{factionID:value, ...}  | 
|     for factionID in xrange(1, groupCnt + 1):  | 
|         for npcInfo in g_curBossDict.values():  | 
|             objID = npcInfo[0]  | 
|             npcID = npcInfo[1]  | 
|             hurtValue = gameFB.GetGameFBDictByKey(FBDict_BossCountryHurt % (objID, npcID, factionID))  | 
|             g_bossFactionHurtDict["%s_%s_%s" % (objID, npcID, factionID)] = hurtValue  | 
|               | 
|         allHurtValue = gameFB.GetGameFBDictByKey(FBDict_AllBossCountryHurt % factionID)  | 
|         allHhurtPoint = gameFB.GetGameFBDictByKey(FBDict_AllBossCountryHurtPoint % factionID)  | 
|         factionTotalHurtDict[factionID] = allHhurtPoint * ChConfig.Def_PerPointValue + allHurtValue  | 
|               | 
|     gongXun = gameFB.GetPlayerGameFBDictByKey(curPlayer.GetPlayerID(), FBPlayerDict_GongXun)  | 
|       | 
|     helpDict = {"BossStep":bossStep, "BossInfo":g_curBossDict, "BossHurtDict":g_bossFactionHurtDict,  | 
|                 "TotalHurtDict":factionTotalHurtDict, "GongXun":gongXun, "Tick":tick,   | 
|                 "FactionBuff":g_factionBuffDict, "BuffCntDict":g_bossBuffCntDict}  | 
|       | 
|     GameWorld.DebugLog("DoFBHelp %s" % str(helpDict), curPlayer.GetPlayerID())  | 
|     FBCommon.Notify_FBHelp(curPlayer, helpDict)  | 
|     return  | 
|       | 
| ##¸±±¾×¼±¸Ê±¼ä  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapPrepare(tick):  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     mapPrepare = mergeBossCfg[Def_Time_MapPrepare] * 1000  | 
|     mapPrepareNotify = mergeBossCfg[Def_Time_MapPrepareNotify] * 1000  | 
|     __PrepareTimeWorldNotify(mapPrepare + mapPrepareNotify, tick)  | 
|       | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < mapPrepare:  | 
|         return  | 
|       | 
|     #Í¨ÖªÌØÐ§  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttAddUpTime, mapPrepareNotify)  | 
|     FBCommon.SetFBStep(FB_State_MapPrepareNotify, tick)  | 
|     return  | 
|   | 
|   | 
| ##¸±±¾×¼±¸Ê±¼ä£¬Í¨Öª¿Í»§¶Ëµ¹¼ÆÊ±  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapPrepareNotify(tick):  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     mapPrepareNotify = mergeBossCfg[Def_Time_MapPrepareNotify] * 1000  | 
|     __PrepareTimeWorldNotify(mapPrepareNotify, tick)  | 
|       | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < mapPrepareNotify:  | 
|         return  | 
|   | 
|     FBCommon.SetFBStep(FB_State_Fight, tick)  | 
|   | 
|     #¿ªÆôË¢boss  | 
|     __RefreshNextBoss(tick)  | 
|   | 
|     #·Ö¹ú¼ÒÕóÓª  | 
|     __DistributeCountry(tick)  | 
|       | 
|     #»î¶¯ÒѾ¿ªÊ¼£¬Çë´øÉÏÄúµÄÎäÆ÷½øÈëÕ½¶·ÇøÓò°É  | 
|     #PlayerControl.FBNotify("FB_liubo_976459")  | 
|       | 
|     #¸±±¾µ¹¼ÆÊ±£¨ºÁÃ룩  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttFlagTake, mergeBossCfg[Def_Time_Fight] * 1000)  | 
|     return  | 
|   | 
| ##Ë¢ÐÂÏÂÒ»Ö»boss  | 
| def __RefreshNextBoss(tick):  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     curBossStep = gameFB.GetGameFBDictByKey(FBDict_BossStep)  | 
|       | 
|     bossRefreshMarkList = mergeBossCfg[Def_BossRefreshMarkList]  | 
|     bossRefreshNPCIDList = mergeBossCfg[Def_BossRefreshNPCIDList]  | 
|       | 
|     nextStep = curBossStep + 1  | 
|     if nextStep > len(bossRefreshMarkList) or nextStep > len(bossRefreshNPCIDList):  | 
|         GameWorld.ErrLog("ÕÒ²»µ½boss½×¶Î£¨%s£©¶ÔӦˢÐÂÐÅÏ¢£¡" % nextStep)  | 
|         return  | 
|       | 
|     rMark, maxCnt = bossRefreshMarkList[nextStep - 1]  | 
|     npcIDList = bossRefreshNPCIDList[nextStep - 1]  | 
|       | 
|     NPCCustomRefresh.SetNPCRefresh(rMark, npcIDList, 1, maxCnt, ChConfig.Def_SuperFBBossAngryCount)  | 
|     gameFB.SetGameFBDict(FBDict_BossStep, nextStep)  | 
|     gameFB.SetGameFBDict(FBDict_KillBossCnt, 0)  | 
|       | 
|     #ˢй㲥ÌáÐÑ  | 
|     bigNPCIDList = bossRefreshNPCIDList[-1] # ×îºóÒ»²¨  | 
|     if len(bigNPCIDList) > 0 and len(npcIDList) > 0:  | 
|         npcID = npcIDList[0]  | 
|         bigNPCID = bigNPCIDList[0]  | 
|         remainTick = max(mergeBossCfg[Def_Time_Fight] * 1000 - (tick - gameFB.GetFBStepTick()), 0)  | 
|         remainM = remainTick / 60000  | 
|         MergeBoss_NotifyList = eval(ReadChConfig.GetChConfig('MergeBoss_Notify'))  | 
|         msgMark, msgParamList = MergeBoss_NotifyList[nextStep - 1]  | 
|         PlayerControl.FBNotify(msgMark, msgParamList)  | 
|     return  | 
|   | 
| ##»î¶¯¿ªÊ¼Ê±·ÖÕóÓª  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ·ÖÕóÓª  | 
| def __DistributeCountry(tick):  | 
|     GameWorld.Log("===¿ªÊ¼·ÖÕóÓª===")  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     playManager = GameWorld.GetMapCopyPlayerManager()  | 
|     playerCount = playManager.GetPlayerCount()  | 
|       | 
|     playerFightPowerList = []  | 
|   | 
|     #---´´½¨ÁÐ±í£¬¸ù¾ÝÕ½¶·Á¦ÅÅÐò---  | 
|     for i in xrange(playerCount):  | 
|         curPlayer = playManager.GetPlayerByIndex(i)  | 
|           | 
|         #ûÓÐÕâ¸öÍæ¼Ò  | 
|         if not curPlayer:  | 
|             continue  | 
|           | 
|         playerFightPowerList.append([curPlayer.GetFightPower(), curPlayer])  | 
|       | 
|     playerFightPowerList.sort(reverse=True)  | 
|     maxCount = len(playerFightPowerList)  | 
|       | 
|     #---·ÖÕóÓª---=  | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|     # »ñÈ¡ÕóÓª·Ö×éË÷ÒýÁÐ±í  | 
|     groupIndexList = FBCommon.GetGroupList(maxCount, groupCnt)  | 
|       | 
|     GameWorld.Log("    µ±Ç°¸±±¾ÈËÊý£º%s£¬ ·ÖΪ%s×é" % (maxCount, groupCnt))  | 
|     GameWorld.Log("    ·Ö×é½á¹û£º%s" % str(groupIndexList))  | 
|     for i in xrange(groupCnt):  | 
|         for playerIndex in groupIndexList[i]:  | 
|             #ÑéÖ¤ÊÇ·ñÔ½½ç  | 
|             if playerIndex >= maxCount:  | 
|                 continue  | 
|               | 
|             curPlayer = playerFightPowerList[playerIndex][1]  | 
|               | 
|             if curPlayer == None:  | 
|                 continue  | 
|               | 
|             SetPlayerCampInfo(curPlayer, i + 1, countryInfo[i], tick)  | 
|               | 
|     for i in xrange(1, groupCnt + 1):  | 
|         gTFP = gameFB.GetGameFBDictByKey(FBDict_CountryFightpower % (i))  | 
|         GameWorld.Log("    ×é%s×ÜÕ½Á¦£º%s" % (i, gTFP))  | 
|     return  | 
|   | 
| ##»î¶¯ÒÑ¿ªÊ¼ºó£¬ÐÂÍæ¼Ò½øÈëÕ½³¡·ÖÅäÕóÓª  | 
| # @param tick  Ê±ÖÓ  | 
| # @return   | 
| def __DistributeCountryByEnter(curPlayer, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|       | 
|     fightPowerList = []  | 
|     for groupType in xrange(1, groupCnt + 1):  | 
|         fightPower = gameFB.GetGameFBDictByKey(FBDict_CountryFightpower % groupType)  | 
|         fightPowerList.append([fightPower, groupType])  | 
|     fightPowerList.sort()  | 
|       | 
|     GameWorld.Log("    µ±Ç°ËùÓÐÕóÓªÕ½Á¦Ã÷ϸ£º%s" % str(fightPowerList))  | 
|       | 
|     # Ä¬ÈϼÓÈëÕ½Á¦½ÏµÍµÄÕóÓª  | 
|     if len(fightPowerList) > 0:  | 
|         joinGroupType = fightPowerList[0][1]  | 
|     else:  | 
|         joinGroupType = random.randint(1, groupCnt + 1)  | 
|           | 
|     if joinGroupType > groupCnt:  | 
|         GameWorld.ErrLog("    ·ÖÅäÕóÓª²»´æÔÚ£¡£º%s" % joinGroupType)  | 
|         return  | 
|       | 
|     GameWorld.Log("    Ð½øÈëÍæ¼Ò¼ÓÈëÕ½Á¦×îµÍÕóÓª£º%s" % joinGroupType, curPlayer.GetPlayerID())  | 
|     SetPlayerCampInfo(curPlayer, joinGroupType, countryInfo[joinGroupType - 1], tick)  | 
|     return  | 
|   | 
|   | 
| ##¸±±¾½ø³¡µ¹¼ÆÊ±¹ã²¥  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __PrepareTimeWorldNotify(prepareTime, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     remaindTick = prepareTime - (tick - gameFB.GetFBStepTick())  | 
|       | 
|     # ÔÚÅäÖÃÖÐÐèÒª¿ªÊ¼Ìáʾ£¬ÇÒδÌáʾ¹ý  | 
|     notifyIndex = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Map_FBDict_NotifyStart)  | 
|     if notifyIndex < len(mergeBossCfg[Def_NotifyStartList]):       | 
|         notifySecond = mergeBossCfg[Def_NotifyStartList][notifyIndex]  | 
|         if remaindTick <= (notifySecond + 1) * 1000:     | 
|             remaindSecond = remaindTick / 1000  | 
|               | 
|             # Ö»ÔÚµÚÒ»ÏßÖÐÌáʾ  | 
|             if GameWorld.GetGameWorld().GetCurGameWorldIndex() == 0:  | 
|                 if remaindSecond >= 60:  | 
|                     PlayerControl.FBNotify("Campaign_liubo_75078", [remaindSecond / 60])  | 
|                 elif remaindSecond > 0:  | 
|                     PlayerControl.FBNotify("Campaign_liubo_367085 ", [notifySecond])  | 
|                       | 
|             # ¼Ç¼Ï´Î×¼±¸ÌáʾµÄʱ¼äË÷Òý  | 
|             GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_FBDict_NotifyStart, notifyIndex + 1)  | 
|     return  | 
|   | 
| ##Õ½¶·Âß¼  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks Õ½¶·Âß¼  | 
| def __DoLogic_Fight(tick):  | 
|     __RefreshBoss(tick) # Ë¢Ðµ±Ç°boss״̬  | 
|     isTimeOver = tick - GameWorld.GetGameFB().GetFBStepTick() >= GetMergeBossCfg()[Def_Time_Fight] * 1000  | 
|     isItemAllPickUp = False  | 
|     isEndDelayTime = False  | 
|     endDelayStartTime = GameWorld.GetGameFB().GetGameFBDictByKey(FBDict_EndDelayStartTime)  | 
|     if endDelayStartTime and tick > endDelayStartTime:  | 
|         isItemAllPickUp = (GameWorld.GetMapItemManager().GetMapItemCount() <= 0)  | 
|         maxDelayTime = GetMergeBossCfg()[Def_EndDelayTime] * 1000  | 
|         isEndDelayTime = (tick - endDelayStartTime) >= maxDelayTime  | 
|         GameWorld.Log("ÑÓ³Ù½áÊøµÈ´ý£ºtick(%s) - endDelayStartTime(%s) =(%s)! maxDelayTime=%s! isItemAllPickUp=%s"   | 
|                       % (tick, endDelayStartTime, tick - endDelayStartTime, maxDelayTime, isItemAllPickUp))  | 
|       | 
|     # Õ½¶·Ê±¼ä½áËã or Ìáǰ½áÊøÇÒ¶«Î÷¶¼¼ñÍê or µ½´ï×ÑÓ³¤½áËãʱ¼ä(¼´Ê¹¶«Î÷û¼ñÍê)  | 
|     if isTimeOver or isItemAllPickUp or isEndDelayTime:  | 
|         GameWorld.Log("½áÊø»î¶¯: isTimeOver=%s,isItemAllPickUp=%s,isEndDelayTime=%s"   | 
|                       % (isTimeOver, isItemAllPickUp, isEndDelayTime))  | 
|         __MergeBossOver(tick)  | 
|     return  | 
|   | 
| ## ¿ç·þboss»î¶¯½áÊø  | 
| #  @param tick   | 
| #  @return None  | 
| def __MergeBossOver(tick):  | 
|     global g_joinPlayerIDList  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|       | 
|     # Çå³ýδ»÷ɱµÄboss  | 
|     FBCommon.ClearFBNPC()  | 
|       | 
|     # ÕóÓª×ÜÉ˺¦½áËã  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|       | 
|     factionTotalHurtList = [] # ÕóÓª×ÜÉ˺¦[[value,factionID], ...]  | 
|     for factionID in xrange(1, groupCnt + 1):  | 
|         allHurtValue = gameFB.GetGameFBDictByKey(FBDict_AllBossCountryHurt % factionID)  | 
|         allHurtPoint = gameFB.GetGameFBDictByKey(FBDict_AllBossCountryHurtPoint % factionID)  | 
|         allHurt = allHurtPoint * ChConfig.Def_PerPointValue + allHurtValue  | 
|         factionTotalHurtList.append([allHurt, factionID])  | 
|           | 
|     factionTotalHurtList.sort(reverse=True)  | 
|     factionHurtOrderList = [] # ÕóÓª×ÜÉ˺¦ÅÅÐÐÁÐ±í  | 
|     for hurtValue, factionID in factionTotalHurtList:  | 
|         factionHurtOrderList.append(factionID)  | 
|           | 
|     GameWorld.Log("»î¶¯×ܽáË㣺ÕóÓª×ÜÉ˺¦ÅÅÐÐÁбí%s" % (str(factionTotalHurtList)))  | 
|           | 
|     #ÕóÓª×ÜÉ˺¦ÅÅÐмӹ¦Ñ«  | 
|     gongXunDict = ReadChConfig.GetEvalChConfig("MergeBoss_GongXunAllHurt")  | 
|       | 
|     # ¹ã²¥×Ó·þ½áËãÐÅÏ¢ {playerID:[ÕóÓªÃû´Î, »ñµÃ¹¦Ñ«]}  | 
|     playerScoreDict = {}  | 
|       | 
|     # ·ÀÖ¹ÖØ¶Á½Å±¾µ¼Ö²μӵÄÍæ¼Ò¼Ç¼¶ªÊ§£¬Èç¹û¶ªÊ§ÔòÖ»ÄÜ·¢¸ø¼á³Öµ½»î¶¯½áÊøµÄÍæ¼Ò  | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in xrange(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|         playerID = player.GetPlayerID()  | 
|         if playerID not in g_joinPlayerIDList:  | 
|             g_joinPlayerIDList.append(playerID)  | 
|             GameWorld.Log("    g_joinPlayerIDList append %s" % playerID)  | 
|               | 
|     for playerID in g_joinPlayerIDList:  | 
|           | 
|         curPlayer = copyMapPlayerManager.FindPlayerByID(playerID)  | 
|           | 
|         order = 0 # Ã»ÓÐÅÅÃû  | 
|         factionID = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_Country)  | 
|         if factionID in factionHurtOrderList:  | 
|             order = factionHurtOrderList.index(factionID) + 1  | 
|               | 
|         addGongXun = GameWorld.GetOrderValueByDict(gongXunDict, order)  | 
|         if addGongXun:  | 
|             __AddPlayerGongXun(curPlayer, addGongXun, True, playerID)  | 
|               | 
|         gongXun = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_GongXun)  | 
|         playerScoreDict[playerID] = [order, gongXun]  | 
|           | 
|         # Í¨Öªover  | 
|         if curPlayer:  | 
|             overMsgDict = {ShareDefine.ScoreTypeName:ShareDefine.ScoreType_MergeBoss,  | 
|                            "TotalHurtList":factionTotalHurtList, "GongXun":gongXun}  | 
|             FBCommon.Notify_FB_Over(curPlayer, overMsgDict)  | 
|               | 
|             # Í¨Öª½áÊøÊ±¼ä  | 
|             curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, mergeBossCfg[Def_FBLeaveTime] * 1000, True)  | 
|           | 
|     # ¹ã²¥×Ó·þ»î¶¯½áËãÐÅÏ¢  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     dataDict = {"MapID":mapID, "PlayerScore":playerScoreDict}  | 
|     GameWorld.Log("ËùÓÐÍæ¼ÒÕóÓªÅÅÃû¼°»ñµÃ¹¦Ñ«%s" % (str(dataDict)))  | 
|     GameWorld.SendBroadcastMerge(ChConfig.Def_MergeBossResult, 0, dataDict, False)  | 
|       | 
|     FBCommon.SetFBStep(FB_State_FreeTime, tick)  | 
|     return  | 
|   | 
| ##±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| def __DoLogic_FreeTime(tick):  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < mergeBossCfg[Def_FBLeaveTime] * 1000:  | 
|         return  | 
|       | 
|     __OnClose(tick)  | 
|     return  | 
|       | 
| ## ±êʶµã¹Ø±ÕË¢¹Ö֪ͨ  | 
| #  @param refreshMark   | 
| #  @param tick   | 
| #  @return None  | 
| def OnCloseNPCRefresh(refreshMark, tick):  | 
|     # Ë¢Íê¹Öºó£¬Ë¢ÐÂϵ±Ç°boss״̬  | 
|     __RefreshBoss(tick, True)  | 
|     GameWorld.Log("OnCloseNPCRefresh mark=%s,bossDict=%s" % (refreshMark, g_curBossDict))  | 
|     __Sync_FBPlayerHelp(tick)  | 
|     return  | 
|   | 
| ## Boss״̬ˢР | 
| # @param tick Ê±¼ä´Á  | 
| # @return None  | 
| def __RefreshBoss(tick, isForce=False):  | 
|     global g_curBossDict  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     lastTick = gameFB.GetGameFBDictByKey(FBDict_LastRefreshBossTick)  | 
|     # 10ÃëË¢Ò»´Î  | 
|     if not isForce and tick - lastTick < 10000:  | 
|         return  | 
|       | 
|     gameFB.SetGameFBDict(FBDict_LastRefreshBossTick, tick)  | 
|       | 
|     gameNPCManager = GameWorld.GetNPCManager()  | 
|     for index in xrange(gameNPCManager.GetNPCCount()):  | 
|         curNPC = gameNPCManager.GetNPCByIndex(index)  | 
|           | 
|         if not curNPC.GetID():  | 
|             continue  | 
|           | 
|         if not ChConfig.IsGameBoss(curNPC):  | 
|             continue  | 
|           | 
|         objID = curNPC.GetID()  | 
|         npcID = curNPC.GetNPCID()  | 
|         g_curBossDict["%s_%s" % (objID, npcID)] = [objID, npcID, GameObj.GetHP(curNPC), GameObj.GetMaxHP(curNPC),   | 
|                                                    curNPC.GetPosX(), curNPC.GetPosY()]  | 
|         | 
|     __CheckOutTimeBuff(tick)    | 
|     return  | 
|   | 
|   | 
| #¹ØÏµÓÐ3²ã£¬ÎÞ-ÓѺÃ-µÐÈË  | 
| ##ÅжÏÊÇ·ñÓѺùØÏµ£¬¸Ã²ãÅж¨ÎªÓѺÃÂß¼ÖеÄ×îºóÅÐ¶Ï  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curTagPlayer Ä¿±êÍæ¼ÒʵÀý  | 
| # @return ²¼¶ûÖµ  | 
| def CheckPlayersRelation_IsFriend(curPlayer, curTagPlayer):  | 
|     return not __CanAttackPlayer(curPlayer, curTagPlayer)  | 
|   | 
|   | 
| ##¸±±¾ÖÐ,¹¥»÷¶ÓÓÑÂß¼  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curTagPlayer Ä¿±êÍæ¼ÒʵÀý  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks  | 
| def DoCanAttackTeamer(curPlayer, curTagPlayer):  | 
|     return __CanAttackPlayer(curPlayer, curTagPlayer)  | 
|   | 
|   | 
| ##¸±±¾ÖÐ,ÊÇ·ñ¿É¹¥»÷  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curTagPlayer Ä¿±êÍæ¼ÒʵÀý  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ¸±±¾ÖÐ,ÊÇ·ñ¿É¹¥»÷  | 
| def __CanAttackPlayer(curPlayer, curTagPlayer):  | 
|     if GameWorld.GetGameFB().GetFBStep() != FB_State_Fight:  | 
|         return False  | 
|       | 
|     return curPlayer.GetFaction() != curTagPlayer.GetFaction()  | 
|   | 
| ## »ñÈ¡NPCÎïÆ·µôÂä±£»¤ÕóÓª  | 
| #  @param curNPC  | 
| #  @return >0±íʾÓÐÕóÓª±£»¤  | 
| def GetNPCItemProtectFaction(curNPC):  | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     return __GetNPCItemProtectFaction(objID, npcID)  | 
|   | 
| ## »ñÈ¡NPCÎïÆ·µôÂä±£»¤ÕóÓª  | 
| def __GetNPCItemProtectFaction(objID, npcID):  | 
|     MergeBoss_BossBuff = ReadChConfig.GetEvalChConfig("MergeBoss_BossBuff")  | 
|     if npcID not in MergeBoss_BossBuff:  | 
|         return 0  | 
|       | 
|     #GameWorld.DebugLog("»ñÈ¡NPCÎïÆ·µôÂä±£»¤ÕóÓª objID=%s,npcID=%s" % (objID, npcID))  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|       | 
|     protectFaction = 0  | 
|     maxHurt = 0  | 
|     for factionID in xrange(1, groupCnt + 1):  | 
|         hurtValue = gameFB.GetGameFBDictByKey(FBDict_BossCountryHurt % (objID, npcID, factionID))  | 
|         #GameWorld.DebugLog("    faction=%s,hurtValue=%s" % (factionID, hurtValue))  | 
|         if hurtValue > maxHurt:  | 
|             maxHurt = hurtValue  | 
|             protectFaction = factionID  | 
|       | 
|     #GameWorld.DebugLog("    return protectFaction=%s" % (protectFaction))  | 
|     return protectFaction  | 
|   | 
| ## Íæ¼Ò¶ÔNPCÔì³ÉÉ˺¦  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param curNPC   | 
| #  @param hurtHP   | 
| #  @return None  | 
| def DoFB_Player_HurtNPC(curPlayer, curNPC, hurtHP):  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     bossRefreshNPCIDList = mergeBossCfg[Def_BossRefreshNPCIDList]  | 
|     curBossStep = gameFB.GetGameFBDictByKey(FBDict_BossStep)  | 
|       | 
|     if curBossStep > len(bossRefreshNPCIDList):  | 
|         return  | 
|       | 
|     npcID = curNPC.GetNPCID()  | 
|     npcIDList = bossRefreshNPCIDList[curBossStep - 1]  | 
|       | 
|     if npcID not in npcIDList:  | 
|         return  | 
|       | 
|     __AddFactionHurt(curNPC, curPlayer.GetFaction(), hurtHP)  | 
|     return  | 
|   | 
| ## Ôö¼ÓÕóÓªÊä³öÖµ  | 
| #  @param factionID ÕóÓªID  | 
| #  @param addHurt   | 
| #  @return None  | 
| def __AddFactionHurt(curNPC, factionID, addHurt):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     # µ¥¸öbossÉ˺¦ÀÛ¼Ó  | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     bossHurtKey = FBDict_BossCountryHurt % (objID, npcID, factionID)  | 
|     nowHurtValue = gameFB.GetGameFBDictByKey(bossHurtKey)  | 
|     updHurtValue = nowHurtValue + addHurt  | 
|     updHurtValue = min(updHurtValue, ChConfig.Def_UpperLimit_DWord)  | 
|     gameFB.SetGameFBDict(bossHurtKey, updHurtValue)  | 
|       | 
|     # ×ÜÉ˺¦ÀÛ¼Ó, Ö§³Ö³¬¹ý20E  | 
|     allHurtKey = FBDict_AllBossCountryHurt % (factionID)  | 
|     allHurtPointKey = FBDict_AllBossCountryHurtPoint % (factionID)  | 
|     hurtValue = gameFB.GetGameFBDictByKey(allHurtKey)  | 
|     hurtPoint = gameFB.GetGameFBDictByKey(allHurtPointKey)  | 
|     allHurtValue = hurtPoint * ChConfig.Def_PerPointValue + hurtValue + addHurt  | 
|     updHurtValue = allHurtValue % ChConfig.Def_PerPointValue  | 
|     updHurtPoint = allHurtValue / ChConfig.Def_PerPointValue  | 
|     gameFB.SetGameFBDict(allHurtKey, updHurtValue)  | 
|     gameFB.SetGameFBDict(allHurtPointKey, updHurtPoint)  | 
|     return  | 
|   | 
| ## Ôö¼Ó±¾´Î»î¶¯»ñµÃµÄ¹¦Ñ«  | 
| #  @param curPlayer   | 
| #  @param addGongXun   | 
| #  @return None  | 
| def __AddPlayerGongXun(curPlayer, addGongXun, isSyncFBHelp=False, curPlayerID=0):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     playerID = curPlayer.GetPlayerID() if curPlayer else curPlayerID  | 
|     if playerID <= 0:  | 
|         return  | 
|       | 
|     nowGongXun = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_GongXun)  | 
|     updGongXun = nowGongXun + addGongXun  | 
|     updGongXun = min(updGongXun, ChConfig.Def_UpperLimit_DWord)  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_GongXun, updGongXun)  | 
|       | 
|     if not curPlayer:  | 
|         GameWorld.Log("    ¸øÀëÏßÍæ¼Ò¼Ó¹¦Ñ«£ºplayerID=%s,nowGongXun=%s,add=%s,updGongXun=%s"   | 
|                       % (playerID, nowGongXun, addGongXun, updGongXun))  | 
|     if isSyncFBHelp and curPlayer:  | 
|         DoFBHelp(curPlayer, GameWorld.GetGameWorld().GetTick())  | 
|     return  | 
|   | 
| ##ÉËѪÅÅÐÐͬ²½, ÊÕµ½¸ÃÐÅÏ¢£¬´ú±íNPCÒѱ»»÷ɱ  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @return None  | 
| def OnBossHurtListClear(objID, npcID, sortHurtList):  | 
|       | 
|     if len(sortHurtList) == 0:  | 
|         return  | 
|       | 
|     GameWorld.Log("OnBossHurtListClear objID=%s, npcID=%s, len(sortHurtList)=%s"   | 
|                        % (objID, npcID, len(sortHurtList)))  | 
|   | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     #¹ã²¥×Ó·þboss±»»÷ɱ  | 
|     __SendBroadcastMergeClient_BossKilled(objID, npcID, mergeBossCfg, sortHurtList)  | 
|     GameWorld.Log("ϵͳɱËÀboss£ºobjID=%s,npcID=%s; ¹ã²¥×Ó·þ·¢·ÅÅÅÐн±Àø£¡" % (objID, npcID))  | 
|     return  | 
|   | 
| ##ÉËѪÅÅÐÐͬ²½, ÊÕµ½¸ÃÐÅÏ¢£¬´ú±íNPCÒѱ»»÷ɱ  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @return None  | 
| # @remarks ÒòΪ´ËÂß¼±ÈDoFB_Player_KillNPCÍí£¬¹Ê»÷ɱÂß¼·ÅÔÚ´Ë´¦´¦Àí  | 
| def OnBossKilledHurtList(objID, npcID, sortHurtList):  | 
|     global g_curBossDict  | 
|     GameWorld.Log("OnBossKilledHurtList objID=%s, npcID=%s, len(sortHurtList)=%s"   | 
|                        % (objID, npcID, len(sortHurtList)))  | 
|       | 
|     mergeBossCfg = GetMergeBossCfg()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     curBossStep = gameFB.GetGameFBDictByKey(FBDict_BossStep)  | 
|     if curBossStep <= 0:  | 
|         GameWorld.DebugLog("    curBossStep <= 0")  | 
|         return  | 
|       | 
|     bossRefreshMarkList = mergeBossCfg[Def_BossRefreshMarkList]  | 
|     bossRefreshNPCIDList = mergeBossCfg[Def_BossRefreshNPCIDList]  | 
|       | 
|     if curBossStep > len(bossRefreshMarkList) or curBossStep > len(bossRefreshNPCIDList):  | 
|         GameWorld.DebugLog("    curBossStep > len(bossRefreshMarkList) or curBossStep > len(bossRefreshNPCIDList)")  | 
|         return  | 
|       | 
|     maxCnt = bossRefreshMarkList[curBossStep - 1][1]  | 
|     npcIDList = bossRefreshNPCIDList[curBossStep - 1]  | 
|       | 
|     if npcID not in npcIDList:  | 
|         GameWorld.DebugLog("    npcID not in npcIDList")  | 
|         return  | 
|   | 
|     bossKey = "%s_%s" % (objID, npcID)  | 
|     if bossKey in g_curBossDict:  | 
|         bossInfo = g_curBossDict[bossKey]  | 
|         bossInfo[2] = 0 # µ±Ç°ÑªÁ¿ÉèÖÃΪ0, ´ú±íÒѱ»»÷ɱ  | 
|       | 
|     #»÷ɱÉ˺¦ÅÅÐмӹ¦Ñ«  | 
|     maxOrder = mergeBossCfg[Def_BossAwardMaxOrder]  | 
|     gongXunDict = ReadChConfig.GetEvalChConfig("MergeBoss_GongXunKillBoss")  | 
|     bossAddGXDict = gongXunDict.get(npcID, {})  | 
|     #if bossAddGXDict:  | 
|     playerMng = GameWorld.GetPlayerManager()  | 
|     for order, hurtPlayer in enumerate(sortHurtList, 1):  | 
|         curPlayer = playerMng.FindPlayerByID(hurtPlayer.playerID)  | 
|         if not curPlayer:  | 
|             continue  | 
|           | 
|         addGongXun = 0  | 
|         if bossAddGXDict:  | 
|             addGongXun = GameWorld.GetOrderValueByDict(bossAddGXDict, order)  | 
|           | 
|         if order <= maxOrder:  | 
|             PlayerControl.NotifyCode(curPlayer, "Campaign_liubo_635889", [npcID, order])  | 
|           | 
|         if addGongXun > 0:  | 
|             __AddPlayerGongXun(curPlayer, addGongXun)  | 
|           | 
|     #»÷ɱ¹ã²¥  | 
|     factionID = __GetNPCItemProtectFaction(objID, npcID)  | 
|     lastHurtPlayerName = g_lastHurtPlayerNameDict.get("%s_%s" % (objID, npcID), "")  | 
|     if lastHurtPlayerName and factionID:  | 
|         PlayerControl.FBNotify("Campaign_liubo_758177", [lastHurtPlayerName, npcID, npcID, factionID])  | 
|       | 
|     #¹ã²¥×Ó·þboss±»»÷ɱ  | 
|     __SendBroadcastMergeClient_BossKilled(objID, npcID, mergeBossCfg, sortHurtList)  | 
|       | 
|     nowKillBossCnt = gameFB.GetGameFBDictByKey(FBDict_KillBossCnt)  | 
|     updKillBossCnt = nowKillBossCnt + 1  | 
|     gameFB.SetGameFBDict(FBDict_KillBossCnt, updKillBossCnt)  | 
|       | 
|     GameWorld.Log("»÷ɱboss£ºstep=%s,bossID=%s,updKillBossCnt=%s" % (curBossStep, npcID, updKillBossCnt))  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     __Sync_FBPlayerHelp(tick)  | 
|       | 
|     if updKillBossCnt < maxCnt:  | 
|         return  | 
|       | 
|     if curBossStep >= len(bossRefreshMarkList):  | 
|         GameWorld.Log("    ËùÓÐbossÒѾ»÷ɱÍ꣬½øÈëÑÓ³Ù½áË㣡")  | 
|         gameFB.SetGameFBDict(FBDict_EndDelayStartTime, tick)  | 
|     else:  | 
|         GameWorld.Log("    ±¾½×¶ÎbossÈ«²¿É±Í꣬ˢÐÂÏÂÒ»½×¶Îboss£¡")  | 
|         __RefreshNextBoss(tick)  | 
|     return  | 
|   | 
| ##¹ã²¥×Ó·þboss±»»÷ɱ  | 
| # @param   | 
| # @return ÎÞÒâÒå  | 
| def __SendBroadcastMergeClient_BossKilled(objID, npcID, mergeBossCfg, sortHurtList):  | 
|     playerIDList = []  | 
|     maxOrder = mergeBossCfg[Def_BossAwardMaxOrder]  | 
|     awardPlayerList = sortHurtList[:maxOrder]  | 
|     for hurtPlayer in awardPlayerList:  | 
|         playerIDList.append(hurtPlayer.playerID)  | 
|           | 
|     lastHurtPlayerID = g_lastHurtPlayerIDDict.get("%s_%s" % (objID, npcID), 0)  | 
|     hurtOrderPlayerIDList = playerIDList  | 
|       | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     dataDict = {"MapID":mapID, "NPCID":npcID, "LastHurtID":lastHurtPlayerID, "OrderIDList":hurtOrderPlayerIDList}  | 
|     GameWorld.SendBroadcastMerge(ChConfig.Def_MergeBossKilled, 0, dataDict, False)  | 
|     GameWorld.Log("¹ã²¥×Ó·þboss±»»÷ɱ£ºdataDict=%s" % str(dataDict))  | 
|     return  | 
|   | 
| ##¸±±¾Öл÷ɱ¹ÖÎï  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curNPC NPCʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾Öл÷ɱ¹ÖÎï  | 
| def DoFB_Player_KillNPC(curPlayer, curNPC, tick):  | 
|     global g_lastHurtPlayerIDDict  | 
|     global g_lastHurtPlayerNameDict  | 
|     #´æ´¢×îºóÒ»»÷Íæ¼Ò  | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     g_lastHurtPlayerIDDict["%s_%s" % (objID, npcID)] = playerID  | 
|     g_lastHurtPlayerNameDict["%s_%s" % (objID, npcID)] = curPlayer.GetPlayerName()      | 
|     GameWorld.DebugLog("DoFB_Player_KillNPC ×îºóÒ»»÷objID=%s,npcID=%s" % (objID, npcID), playerID)  | 
|     return  | 
|   | 
| ##´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param defender ·ÀÊØÕß  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼  | 
| def DoFBOnKill_Player(curPlayer, defender, tick):  | 
|     return  | 
|   | 
| ## Ê°È¡ÎïÆ·  | 
| #  @param curPlayer ¹¥»÷·½  | 
| #  @param curItem ÎïÆ·  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def OnPickUpItem(curPlayer, curItem, tick):  | 
|     if GameWorld.GetGameFB().GetFBStep() != FB_State_Fight:  | 
|         return  | 
|   | 
|     curEff = curItem.GetEffectByIndex(0)  | 
|     effID = curEff.GetEffectID()  | 
|     if effID != ChConfig.Def_Effect_ItemGiveGongXun:  | 
|         return  | 
|       | 
|     addGongXun = curEff.GetEffectValue(0) * curItem.GetCount()  | 
|     GameWorld.DebugLog("OnPickUpItem addGongXun=%s" % addGongXun, curPlayer.GetPlayerID())  | 
|     __AddPlayerGongXun(curPlayer, addGongXun, True)  | 
|     return  | 
|   | 
| ## ¹¥»÷½áÊø  | 
| #  @param curPlayer ¹¥»÷·½  | 
| #  @param target ·ÀÊØ·½  | 
| #  @param curSkill   | 
| #  @param tick   | 
| #  @return   | 
| def DoBeAttackOver(attacker, defender, curSkill, tick):  | 
|     if not defender:  | 
|         return  | 
|       | 
|     tagObjType = defender.GetGameObjType()  | 
|       | 
|     if tagObjType != IPY_GameWorld.gotNPC:  | 
|         return  | 
|   | 
|     objID = defender.GetID()  | 
|     npcID = defender.GetNPCID()  | 
|   | 
|     MergeBoss_BossBuff = ReadChConfig.GetEvalChConfig("MergeBoss_BossBuff")  | 
|     if npcID not in MergeBoss_BossBuff:  | 
|         return  | 
|       | 
|     bossBuffInfo = MergeBoss_BossBuff[npcID]  | 
|     radiusList = bossBuffInfo[0]  | 
|     hpPerDict = bossBuffInfo[1]  | 
|     hpPerList = sorted(hpPerDict.keys(), reverse = True)  | 
|     maxBuffCnt = bossBuffInfo[2]  | 
|   | 
|     nowHPPer = GameObj.GetHP(defender) * 100 / GameObj.GetMaxHP(defender) # µ±Ç°°Ù·Ö±È  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     hpPerMarkKey = FBDict_BossHPPerMark % (objID, npcID)  | 
|     hpPerLogicMark = gameFB.GetGameFBDictByKey(hpPerMarkKey)  | 
|     logicHPPerList = hpPerList[hpPerLogicMark:]  | 
|     for hpPer in logicHPPerList:  | 
|           | 
|         if nowHPPer > hpPer:  | 
|             break  | 
|         __SummonBossBuff(defender, radiusList, hpPerDict[hpPer], maxBuffCnt, tick)  | 
|         hpPerLogicMark += 1  | 
|               | 
|     gameFB.SetGameFBDict(hpPerMarkKey, hpPerLogicMark)  | 
|     return  | 
|   | 
| ## ÕÙ»½³öboss²ú³öµÄbuff  | 
| def __SummonBossBuff(curNPC, radiusList, summonCnt, maxCnt, tick):  | 
|     global g_buffOwnerNPCDict  | 
|     global g_bossBuffCntDict  | 
|       | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|       | 
|     buffCntKey = "%s_%s" % (objID, npcID)  | 
|     nowBuffCnt = g_bossBuffCntDict.get(buffCntKey, 0)  | 
|     summonCnt = min(summonCnt, maxCnt - nowBuffCnt)  | 
|     summonCnt = max(summonCnt, 0)  | 
|       | 
|     if summonCnt <= 0:  | 
|         GameWorld.Log("¸Ãboss²ú³öbuff¸öÊýÒÑÂú£¡objID=%s,npcID=%s,maxCnt=%s" % (objID, npcID, maxCnt))  | 
|         return  | 
|       | 
|     buffNPCID = GetMergeBossCfg()[Def_BuffNPCID]  | 
|     posX, posY = curNPC.GetPosX(), curNPC.GetPosY()  | 
|       | 
|     for i in xrange(summonCnt):  | 
|         position = GameMap.GetEmptyPlaceInAreaEx(posX, posY, radiusList[0], radiusList[1])  | 
|         buffPosX, buffPosY = position.GetPosX(), position.GetPosY()  | 
|         buffNPC = NPCCommon.SummonMapNpc(buffNPCID, buffPosX, buffPosY)  | 
|         if not buffNPC:  | 
|             continue  | 
|           | 
|         buffNPCObjID = buffNPC.GetID()  | 
|         buffNPCNPCID = buffNPC.GetNPCID()  | 
|         g_buffOwnerNPCDict["%s_%s" % (buffNPCObjID, buffNPCNPCID)] = buffCntKey  | 
|         nowBuffCnt += 1  | 
|           | 
|     g_bossBuffCntDict[buffCntKey] = nowBuffCnt  | 
|     __Sync_FBPlayerHelp(tick)  | 
|       | 
|     GameWorld.Log("g_buffOwnerNPCDict=%s" % str(g_buffOwnerNPCDict))  | 
|     GameWorld.Log("g_bossBuffCntDict=%s" % str(g_bossBuffCntDict))  | 
|     return  | 
|   | 
| ##¸±±¾ÖÐ,Õ¼ÁìNPCµÄLoadingʱ¼ä.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curNPC NPCʵÀý  | 
| # @return ·µ»ØÖµ, Loadingʱ¼ä  | 
| # @remarks ¸±±¾ÖÐ,Õ¼ÁìNPCµÄLoadingʱ¼ä  | 
| def GetFBPrepareTime(curPlayer, curNPC):  | 
|     return GetMergeBossCfg()[Def_BuffCollectTime]  | 
|   | 
| ##ÊÇ·ñ¿ÉÒÔ¶áÆì  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curNPC NPCʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks  | 
| def OnCanCollect(curPlayer, curNPC, tick):  | 
|     return GameWorld.GetGameFB().GetFBStep() == FB_State_Fight  | 
|   | 
|   | 
| ##Íæ¼ÒÊÕ¼¯³É¹¦(¿ó, buff)  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks  | 
| def OnCollectOK(curPlayer, npcID, tick):  | 
|     global g_buffOwnerNPCDict  | 
|     global g_bossBuffCntDict  | 
|       | 
|     GameWorld.Log("OnCollectOK...", curPlayer.GetPlayerID())   | 
|     tagObj = curPlayer.GetActionObj()  | 
|     if not tagObj:  | 
|         return  | 
|     if tagObj.GetGameObjType() != IPY_GameWorld.gotNPC:  | 
|         return  | 
|       | 
|     curNPC = GameWorld.GetNPCManager().GetNPCByIndex(tagObj.GetIndex())  | 
|     if not curNPC:  | 
|         return  | 
|       | 
|     objID = curNPC.GetID()  | 
|     npcID = curNPC.GetNPCID()  | 
|     buffNPCID = GetMergeBossCfg()[Def_BuffNPCID]  | 
|     if npcID != buffNPCID:  | 
|         GameWorld.Log("OnCollectOK ·ÇbuffNPCID£¬²»´¦Àí£¡npcID=%s,buffNPCID=%s" % (npcID, buffNPCID))  | 
|         return  | 
|       | 
|     ownerNPCKey = "%s_%s" % (objID, npcID)  | 
|     if ownerNPCKey not in g_buffOwnerNPCDict:  | 
|         # ¿ÉÄÜÖØ¶Á½Å±¾µ¼Ö¶ªÊ§£¬¿É²»×ö´¦Àí£¬µ«ÊÇÏàÓ¦buffÂß¼ÕÕÑùÖ´ÐÐ  | 
|         GameWorld.ErrLog("OnCollectOK ÕÒ²»µ½buffËùÊôµÄbossID!")  | 
|     else:  | 
|         bossBuffCntKey = g_buffOwnerNPCDict[ownerNPCKey]  | 
|         buffCnt = g_bossBuffCntDict.get(bossBuffCntKey, 0)  | 
|         g_bossBuffCntDict[bossBuffCntKey] = max(0, buffCnt - 1)  | 
|           | 
|     # Ëæ»ú¸øÕóÓª¼Óbuff  | 
|     __DoFactionRandomAddBuff(curPlayer, tick)  | 
|     __AddPlayerGongXun(curPlayer, GetMergeBossCfg()[Def_BuffGongXun], True)  | 
|     ChNPC.OnCollectEnd(curPlayer, curNPC)  | 
|     GameWorld.Log("    g_buffOwnerNPCDict=%s" % str(g_buffOwnerNPCDict))  | 
|     GameWorld.Log("    g_bossBuffCntDict=%s" % str(g_bossBuffCntDict))  | 
|     return  | 
|   | 
| ## Ëæ»ú¸øÕóÓª¼Óbuff  | 
| def __DoFactionRandomAddBuff(curPlayer, tick):  | 
|     global g_factionBuffDict  | 
|       | 
|     curPlayerfactionID = curPlayer.GetFaction()  | 
|     curPlayerName = curPlayer.GetPlayerName()  | 
|     mergeBoss_BossBuffList = ReadChConfig.GetEvalChConfig("MergeBoss_BossBuffList")  | 
|     addBuffID = GameWorld.GetResultByRandomList(mergeBoss_BossBuffList)  | 
|       | 
|     if not addBuffID:  | 
|         return  | 
|   | 
|     curSkill = GameWorld.GetGameData().GetSkillBySkillID(addBuffID)  | 
|     if not curSkill:  | 
|         return  | 
|       | 
|     skillType = curSkill.GetSkillType()  | 
|     lastTime = curSkill.GetLastTime()  | 
|     lastSecond = lastTime / 1000  | 
|     bossBuffNotify = eval(ReadChConfig.GetChConfig('MergeBoss_BossBuffNotify'))  | 
|       | 
|     isSelf = False if skillType in ChConfig.Def_CanAttackSkill_List else True  | 
|                        | 
|     notifyList = bossBuffNotify[0] if isSelf else bossBuffNotify[1]  | 
|     fbNotifyInfo, playerNotifyInfo = notifyList  | 
|     if fbNotifyInfo[0]:  | 
|         PlayerControl.FBNotify(fbNotifyInfo[0], fbNotifyInfo[1])  | 
|       | 
|     GameWorld.Log("¸øÕóÓªËæ»ú¼Óbuff! addBuffID=%s,isSelf=%s,curPlayerfactionID=%s"   | 
|                   % (addBuffID, isSelf, curPlayerfactionID), curPlayer.GetPlayerID())  | 
|     #GameWorld.DebugLog("bossBuffNotify=%s" % str(bossBuffNotify))  | 
|     #GameWorld.DebugLog("notifyList=%s" % str(notifyList))  | 
|     buffType = SkillCommon.GetBuffType(curSkill)                   | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for index in xrange(playerManager.GetPlayerCount()):  | 
|         player = playerManager.GetPlayerByIndex(index)  | 
|         if not player:  | 
|             continue  | 
|           | 
|         tagPlayerID = player.GetPlayerID()  | 
|         tagPlayerFactionID = player.GetFaction()  | 
|           | 
|         # ¼Ó×Ô¼ºÕóÓªµÄ  | 
|         if isSelf and curPlayerfactionID != tagPlayerFactionID:  | 
|             GameWorld.DebugLog("    ²»ÊÇ×Ô¼ºÕóÓª²»¼Óbuff£¡tagPlayerID=%s" % tagPlayerID)  | 
|             continue  | 
|           | 
|         # ¼Ó±ðÈËÕóÓªµÄ  | 
|         if not isSelf and curPlayerfactionID == tagPlayerFactionID:  | 
|             GameWorld.DebugLog("    ×Ô¼ºÕóÓª²»¼Óbuff£¡tagPlayerID=%s" % tagPlayerID)  | 
|             continue  | 
|           | 
|         # ÓÉÓÚͬÀàÐÍbuff²»¿¼Âǵȼ¶¹ØÏµ£¬Ö±½ÓÌæ»»£¬¹ÊÏÈɾ³ýÔÓÐͬÀàÐÍbuff£¬ÔÙÔö¼ÓеÄbuff  | 
|         BuffSkill.DelBuffBySkillID(curPlayer, addBuffID, tick)  | 
|         BuffSkill.DoAddBuff(player, buffType, curSkill, tick)  | 
|         if playerNotifyInfo[0]:  | 
|             PlayerControl.NotifyCode(player, playerNotifyInfo[0], playerNotifyInfo[1])  | 
|         GameWorld.DebugLog("    ¸øÕóÓªÍæ¼Ò¼Óbuff£ºtagPlayerID=%s,tagPlayerFactionID=%s"   | 
|                            % (tagPlayerID, tagPlayerFactionID))  | 
|       | 
|     # ¸üÐÂËùÓÐÕóÓªµ±Ç°buff  | 
|     skillTypeID = curSkill.GetSkillTypeID()  | 
|     countryInfo = GetMergeBossCfg()[Def_CountryInfo]  | 
|     groupCnt = len(countryInfo)  | 
|     GameWorld.DebugLog("¸üÐÂËùÓÐÕóÓªbuffǰ: skillTypeID=%s,g_factionBuffDict=%s"   | 
|                        % (skillTypeID, str(g_factionBuffDict)))  | 
|     for factionID in xrange(1, groupCnt + 1):  | 
|         if isSelf and curPlayerfactionID != factionID:  | 
|             continue  | 
|         if not isSelf and curPlayerfactionID == factionID:  | 
|             continue  | 
|           | 
|         factionBuffDict = g_factionBuffDict.get(factionID, {})  | 
|         for buffID in factionBuffDict.keys():  | 
|             skill = GameWorld.GetGameData().GetSkillBySkillID(buffID)  | 
|             # Çå³ýÓëÌí¼ÓµÄbuffͬһÀàÐ͵Äbuff  | 
|             if not skill or skillTypeID == skill.GetSkillTypeID():  | 
|                 factionBuffDict.pop(buffID)  | 
|                 GameWorld.DebugLog("    pop factionID=%s,buffID=%s" % (factionID, buffID))  | 
|                       | 
|         factionBuffDict[addBuffID] = [tick, lastTime]  | 
|         g_factionBuffDict[factionID] = factionBuffDict  | 
|       | 
|     GameWorld.DebugLog("¸üÐÂËùÓÐÕóÓªbuffºó: g_factionBuffDict=%s" % str(g_factionBuffDict))  | 
|     __CheckOutTimeBuff(tick)  | 
|     return  | 
|   | 
| ## ¼ì²é³¬Ê±µÄbuff  | 
| def __CheckOutTimeBuff(tick):  | 
|     global g_factionBuffDict  | 
|       | 
|     #GameWorld.DebugLog("ÕóÓªbuff³¬Ê±¼ì²é: tick=%s,g_factionBuffDict=%s" % (tick, str(g_factionBuffDict)))  | 
|     for factionID, buffInfoDict in g_factionBuffDict.items():  | 
|         for buffID, buffInfo in buffInfoDict.items():  | 
|             addBuffTick, lastTime = buffInfo  | 
|             passTick = tick - addBuffTick  | 
|             if passTick >= lastTime:  | 
|                 buffInfoDict.pop(buffID)  | 
|                 #GameWorld.DebugLog("    pop factionID=%s,buffID=%s,passTick=%s,lastTime=%s"   | 
|                 #                   % (factionID, buffID, passTick, lastTime))  | 
|                   | 
|         g_factionBuffDict[factionID] = buffInfoDict  | 
|     #GameWorld.DebugLog("    ¸üÐÂg_factionBuffDict=%s" % str(g_factionBuffDict))  | 
|     return  | 
|   | 
| ## »Ø³Ç¸´»îΪ¸±±¾Öи´»î  | 
| # @param None  | 
| # @return ÎÞÒâÒå  | 
| def OnPlayerReborn():  | 
|     return True  | 
|   | 
| ## ÖØÖø±±¾¸´»îÍæ¼Ò×ø±êµã  | 
| # @param None  | 
| # @return ÎÞÒâÒå  | 
| def OnResetFBRebornPlacePos(curPlayer, rebornPlace, tick):  | 
|     posPoint = GameMap.GetEmptyPlaceInArea(curPlayer.GetFBRebornPosX(), curPlayer.GetFBRebornPosY(), 3)  | 
|     curPlayer.ResetPos(posPoint.GetPosX(), posPoint.GetPosY())  | 
|     return  | 
|   | 
| ##--------------------------------------------------------------------------------------------------  | 
|   | 
| def OnGetMergeBossFirstJoinAward(curPlayer):  | 
|     # ÁìÈ¡¿ç·þboss½±Àø  | 
|     firstJoinAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MergeBoss_FirstJoinAwardRecord)  | 
|     if firstJoinAwardState == 2:  | 
|         GameWorld.DebugLog("ÒѾÁìÈ¡¹ý¿ç·þbossÊ״βÎÓë½±Àø£¡", curPlayer.GetPlayerID())  | 
|         return  | 
|     if firstJoinAwardState != 1:  | 
|         GameWorld.DebugLog("²»¿ÉÁìÈ¡¹ý¿ç·þbossÊ״βÎÓë½±Àø£¡", curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     firstJoinAwardItemList = ReadChConfig.GetEvalChConfig("MergeBoss_FirstJoinAward")  | 
|     needSpace = len(firstJoinAwardItemList)  | 
|     emptySpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)  | 
|     if needSpace > emptySpace:  | 
|         PlayerControl.NotifyCode(curPlayer, "GeRen_chenxin_998371")  | 
|         return  | 
|       | 
|     # ¸üÐÂΪÒÑÁìÈ¡  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_MergeBoss_FirstJoinAwardRecord, 2)  | 
|       | 
|     for item in firstJoinAwardItemList:  | 
|         itemID, itemCount, isBind = item[:3]  | 
|         isAppoint = item[3] if len(item) > 3 else 0  | 
|         if isAppoint:  | 
|             ItemControler.GivePlayerAppointItem(curPlayer, itemID, isBind, True, event=["MergeBossFirstJoin", True, {}])  | 
|         else:  | 
|             ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, isBind, [IPY_GameWorld.rptItem],   | 
|                                          True, event=["MergeBossFirstJoin", True, {}])  | 
|               | 
|     Sync_MergeBossAwardRecord(curPlayer)  | 
|     return  | 
|   | 
| def Sync_MergeBossAwardRecord(curPlayer):  | 
|     # Í¨Öª¿ç·þboss½±ÀøÁìÈ¡¼Ç¼  | 
|     recordPack = ChPyNetSendPack.tagMCMergeBossAwardRecord()  | 
|     recordPack.Clear()  | 
|     recordPack.FirstJoinAwardState = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_MergeBoss_FirstJoinAwardRecord)  | 
|     NetPackCommon.SendFakePack(curPlayer, recordPack)  | 
|     return  | 
|   |