| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_CrossChampionship  | 
| #  | 
| # @todo:¿ç·þÅÅλÕù°ÔÈü  | 
| # @author hxp  | 
| # @date 2022-09-21  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ¿ç·þÅÅλÕù°ÔÈü  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2022-09-21 21:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import ChPlayer  | 
| import GameWorld  | 
| import IPY_GameWorld  | 
| import PlayerControl  | 
| import GameWorldProcess  | 
| import IpyGameDataPY  | 
| import SkillCommon  | 
| import FBCommon  | 
| import ChConfig  | 
| import GameObj  | 
|   | 
| (  | 
| Def_Time_MaxWait, # ×µÈ´ýʱ¼ä, Ãë  | 
| Def_Time_MapPrepare, # ×¼±¸Ê±¼ä, Ãë  | 
| Def_Time_Fight, # Õ½¶·Ê±¼ä, Ãë  | 
| Def_Time_Protect, # ±£»¤Ê±¼ä£¬Ãë£¬Íæ¼ÒÕ½¶·ÖеôÏß±£»¤Ê±³¤  | 
| Def_Time_Leave, # ½áÊøÍ˳öʱ¼ä, Ãë  | 
| ) = range(5)  | 
|   | 
| # µ±Ç°¸±±¾µØÍ¼µÄ״̬  | 
| (  | 
| FB_State_Open,  | 
| FB_State_Waiting, # µÈ´ý¶ÔÊÖ½×¶Î  | 
| FB_State_MapPrepare, # µØÍ¼×¼±¸  | 
| FB_State_Fight, # Õ½¶·½×¶Î  | 
| FB_State_Reborn, # ¸´»î½×¶Î  | 
| FB_State_Leave, # À뿪½×¶Î  | 
| FB_State_Close, # ¹Ø±Õ½×¶Î  | 
| ) = range(7)  | 
|   | 
| # ¶ÔÕ½½áÊøÀàÐͶ¨Òå  | 
| (  | 
| Def_OverType_LackPlayer, # È±ÉÙ¶ÔÊÖ  | 
| Def_OverType_PlayerExit, # ¶ÔÊÖÍ˳ö(ÊÓΪÈÏÊä)  | 
| Def_OverType_Kill, # »÷ɱ¶ÔÊÖ  | 
| Def_OverType_TimeOut, # PKʱ¼ä³¬Ê±  | 
| ) = range(4)  | 
|   | 
| # ¸±±¾Ïà¹Ø×Öµäkey  | 
| GameFBDict_FBPlayerID = "FBD_FBPlayerID_%s" # Íæ¼ÒID, ²ÎÊý, ½øÈë˳Ðò  | 
| GameFBDict_PlayerWinCnt = "FBD_PlayerWinCnt_%s" # Íæ¼ÒÒÑ»ñʤ´ÎÊý, ²ÎÊý[playerID]  | 
| GameFBDict_PlayerLeaveTick = "FBD_PlayerLeaveTick_%s" # Íæ¼ÒÒÑ»ñʤ´ÎÊý, ²ÎÊý[playerID]  | 
|   | 
| FBPDict_PVPDamage = "FBPD_PVPDamage" # Íæ¼ÒÉ˺¦Êä³ö  | 
| FBPDict_PVPDamUpdTick = "FBPD_PVPDamUpdTick" # ¸üÐÂÉ˺¦tick  | 
| FBPDict_ResetPosX = "FBPD_ResetPosX" # Íæ¼ÒÖØÖÃ×ø±êX  | 
| FBPDict_ResetPosY = "FBPD_ResetPosY" # Íæ¼ÒÖØÖÃ×ø±êY  | 
| FBPDict_RoundNum = "FBPD_RoundNum" # Íæ¼Òµ±Ç°ËùÊô»ØºÏÊý  | 
|   | 
| FB_RoundNum = "FB_RoundNum" # ¸±±¾µ±Ç°»ØºÏÊý  | 
| FB_RoundWinPlayerID = "FB_RoundWinPlayerID_%s" # »ØºÏ»ñÊ¤Íæ¼ÒID, ²ÎÊý[»ØºÏÊý]  | 
|   | 
| def OnOpenFB(tick):  | 
|     # ¿ªÆô¸±±¾Ö±½Ó½øÈëµÈ´ý½×¶Î  | 
|     FBCommon.SetFBStep(FB_State_Waiting, tick)  | 
|     return  | 
|   | 
| ## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     return True  | 
|   | 
| #def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):  | 
| #    posDict = {117401:(40,37), 117403:(10, 7)}  | 
| #    return posDict.get(curPlayer.GetPlayerID())  | 
|   | 
| ## Íæ¼Ò½øÈ븱±¾  | 
| def DoEnterFB(curPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerVSRoomID = curPlayer.GetVsRoomId()  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()          | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|     GameWorld.Log("DoEnterFB fbRoomID=%s,playerVSRoomID=%s,fbStep=%s" % (roomID, playerVSRoomID, fbStep), playerID)  | 
|       | 
|     if gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerID):  | 
|         GameWorld.Log("    Íæ¼ÒÀëÏß±£»¤Ê±¼äÄÚÉÏÏß!", playerID)  | 
|         gameFB.SetGameFBDict(GameFBDict_PlayerLeaveTick % playerID, 0)  | 
|         playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|         for index in xrange(playerManager.GetPlayerCount()):  | 
|             player = playerManager.GetPlayerByIndex(index)  | 
|             if player and player.GetPlayerID() != curPlayer.GetPlayerID():  | 
|                 player.Sync_TimeTick(ChConfig.tttPlayerLeave, 0, 0, True)  | 
|                   | 
|     fbRoundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)  | 
|     playerRoundNum = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_RoundNum)  | 
|     if playerRoundNum and fbRoundNum and playerRoundNum != fbRoundNum:  | 
|         # Ò»°ãÊǵôÏßʱÉϸö»ØºÏÒѾ½áÊøÁË  | 
|         GameWorld.DebugLog("Íæ¼Ò½øÈ븱±¾Ê±Ó뵱ǰ¸±±¾»ØºÏÊý²»Ò»ÖÂʱ£¬ÖØÖÃ״̬£¡fbRoundNum=%s,playerRoundNum=%s"   | 
|                            % (fbRoundNum, playerRoundNum), playerID)  | 
|         gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, fbRoundNum)  | 
|         __ResetPlayerState(gameFB, curPlayer, playerID)  | 
|           | 
|     if fbStep >= FB_State_Leave or not roomID or not playerVSRoomID or roomID != playerVSRoomID:  | 
|         PlayerControl.PlayerLeaveFB(curPlayer)  | 
|         return  | 
|     PlayerControl.SetSight(curPlayer, ChConfig.Def_PlayerSight_Default * 3)  | 
|       | 
|     # ·ÇÕ½¶·½×¶Î£¬Í¨Öª¶¯Ì¬Õϰµã  | 
|     if fbStep < FB_State_Fight:  | 
|         FBCommon.SyncDynamicBarrierState(IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 2), 1, curPlayer) # ×¼±¸ÆÚ¼äÓж¯Ì¬Õϰµã  | 
|           | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|       | 
|     if fbStep == FB_State_Open:  | 
|         pass  | 
|       | 
|     elif fbStep == FB_State_Waiting:  | 
|         playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|         playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|         if not playerIDA and not playerIDB:  | 
|             gameFB.SetGameFBDict(GameFBDict_FBPlayerID % 1, playerID)  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosX, curPlayer.GetPosX())  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosY, curPlayer.GetPosY())  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, 1)  | 
|             GameWorld.Log("    µÚÒ»¸ö½øÈ룬ÕóÓª1£¬roomID=%s" % (roomID), playerID)  | 
|             __ResetPlayerState(gameFB, curPlayer, playerID)  | 
|               | 
|         elif not playerIDB and playerIDA != playerID:  | 
|             gameFB.SetGameFBDict(GameFBDict_FBPlayerID % 2, playerID)  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosX, curPlayer.GetPosX())  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_ResetPosY, curPlayer.GetPosY())  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, 1)  | 
|             GameWorld.Log("    µÚ¶þ¸ö½øÈ룬ÕóÓª2£¬roomID=%s" % (roomID), playerID)  | 
|             __ResetPlayerState(gameFB, curPlayer, playerID)  | 
|               | 
|         playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|         playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|         if GameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 2 and playerIDA and playerIDB:  | 
|             GameWorld.Log("    Á½¸öÈ˶¼ÔÚ£¬ÉèÖø±±¾½øÈëÕ½¶·µ¹¼ÆÊ±½×¶Î£¡roomID=%s" % (roomID), playerID)  | 
|             FBCommon.SetFBStep(FB_State_MapPrepare, tick)  | 
|             FBCommon.Sync_Player_TimeTick(ChConfig.tttWaitStart, fbTimeList[Def_Time_MapPrepare] * 1000)  | 
|             gameFB.SetGameFBDict(FB_RoundNum, 1)  | 
|         else:  | 
|             notify_tick = fbTimeList[Def_Time_MaxWait] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|             curPlayer.Sync_TimeTick(ChConfig.tttWaitPlayer, 0, max(notify_tick, 0), True)  | 
|             GameWorld.Log("    ¶ÔÊÖ²»ÔÚ£¬¼ÌÐøµÈ´ý£¡roomID=%s" % (roomID), playerID)  | 
|               | 
|     elif fbStep == FB_State_MapPrepare:  | 
|         notify_tick = fbTimeList[Def_Time_MapPrepare] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|         curPlayer.Sync_TimeTick(ChConfig.tttWaitStart, 0, max(notify_tick, 0), True)  | 
|           | 
|     elif fbStep == FB_State_Fight:  | 
|         notify_tick = fbTimeList[Def_Time_Fight] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|         curPlayer.Sync_TimeTick(ChConfig.tttTowerTake, 0, max(notify_tick, 0), True)  | 
|           | 
|     FBCommon.Notify_FBHelp(curPlayer, __GetFBHelpInfo())  | 
|     PlayerControl.DelLimitSuperBuff(curPlayer, tick)  | 
|     PlayerControl.PlayerControl(curPlayer).RefreshPlayerAttrState()  | 
|     return  | 
|   | 
| def __GetFBHelpInfo():  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     roundWinerIDList = []  | 
|     roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)  | 
|     for roundNum in xrange(1, roundNum + 1):  | 
|         winnerID = gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum)  | 
|         if not winnerID:  | 
|             break  | 
|         roundWinerIDList.append(winnerID)  | 
|           | 
|     return {"roundNum":roundNum, "roundWinerIDList":roundWinerIDList}  | 
|   | 
|   | 
| ## Íæ¼ÒÍ˳ö¸±±¾  | 
| def DoExitFB(curPlayer, tick):  | 
|     # ½áËãʱ¼ä  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep >= FB_State_Leave:  | 
|         return  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     gameFB.SetGameFBDict(GameFBDict_PlayerLeaveTick % playerID, tick)  | 
|     GameWorld.Log("Íæ¼ÒÕ½¶·½×¶ÎÏÂÏߣ¡playerID=%s,waitPlayerID=%s" % (playerID, playerID))  | 
|       | 
|     ## Í¨Öª¶Ô·½£¬¶ÔÊÖµôÏß  | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for index in xrange(playerManager.GetPlayerCount()):  | 
|         player = playerManager.GetPlayerByIndex(index)  | 
|         if player and player.GetPlayerID() != curPlayer.GetPlayerID():  | 
|             fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|             player.Sync_TimeTick(ChConfig.tttPlayerLeave, 0, max(fbTimeList[Def_Time_Protect] * 1000, 0), True)  | 
|               | 
|     return  | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep <= FB_State_Waiting or fbStep >= FB_State_Leave:  | 
|         return  | 
|       | 
|     leavePlayerID = curPlayer.GetPlayerID()  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|     playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|       | 
|     loser, loserID = curPlayer, leavePlayerID  | 
|     winnerID = playerIDA if playerIDB == loserID else playerIDB  | 
|     winner = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(winnerID)  | 
|     GameWorld.Log("Íæ¼ÒÖ÷¶¯Í˳ö£¬Ö±½ÓËãÊä! roomID=%s,leavePlayerID=%s,loserID=%s,winnerID=%s" % (roomID, leavePlayerID, loserID, winnerID))  | 
|     __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_PlayerExit, tick)  | 
|     return  | 
|   | 
| ## »ñµÃ¸±±¾°ïÖúÐÅÏ¢  | 
| def DoFBHelp(curPlayer, tick):  | 
|     return  | 
|   | 
| ## ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep == FB_State_Waiting:  | 
|         __DoLogic_Waiting(tick)  | 
|     elif fbStep == FB_State_MapPrepare:  | 
|         if not __CheckLeaveProtectTimeout(tick):  | 
|             __DoLogic_MapPrepare(tick)  | 
|     elif fbStep == FB_State_Fight:  | 
|         if not __CheckLeaveProtectTimeout(tick):  | 
|             __DoLogic_MapFight(tick)  | 
|     elif fbStep == FB_State_Reborn:  | 
|         __DoLogic_Reborn(tick)  | 
|     elif fbStep == FB_State_Leave:  | 
|         __DoLogic_LeaveTime(tick)  | 
|           | 
|     return  | 
|   | 
| ##µÈ´ýÍæ¼Ò½øÈë½×¶Î´¦Àí  | 
| def __DoLogic_Waiting(tick):  | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_MaxWait] * 1000:  | 
|         return  | 
|       | 
|     winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)  | 
|     # ¶ÔÊÖûÀ´£¬Ö±½Ó»ñʤ  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     GameWorld.Log("սǰµÈ´ý¶ÔÊֽ׶γ¬Ê±£¬Ö±½Ó½áÊø£¡roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))  | 
|     __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_LackPlayer, tick)  | 
|     return  | 
|   | 
| def __CheckLeaveProtectTimeout(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|     playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|     playerLeaveTickA = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDA)  | 
|     playerLeaveTickB = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDB)  | 
|     if not playerLeaveTickA and not playerLeaveTickB:  | 
|         return  | 
|       | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     if playerLeaveTickA > playerLeaveTickB:  | 
|         if tick - playerLeaveTickA < fbTimeList[Def_Time_Protect] * 1000:  | 
|             return  | 
|     else:  | 
|         if tick - playerLeaveTickB < fbTimeList[Def_Time_Protect] * 1000:  | 
|             return  | 
|           | 
|     winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)  | 
|     # ¶ÔÊÖûÀ´£¬Ö±½Ó»ñʤ  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     GameWorld.Log("Õ½¶·ÖжÔÊÖÀëÏß³¬Ê±£¬Ö±½Ó½áÊø£¡roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))  | 
|     __DoFBPKAllOver(winner, winnerID, loser, loserID, Def_OverType_PlayerExit, tick)  | 
|     return True  | 
|   | 
| def __GetTimeoutWinerInfo(tick):  | 
|     ''' Ê±¼ä³¬Ê±£¬»ñÈ¡»ñʤµÄÍæ¼Ò  | 
|                     Õ½¶·½×¶ÎÓÐÁ½¸öÍæ¼ÒʱÓÅÏȱȽÏÊä³ö  | 
|                     ÆäËûÇé¿öÔòÔÚÏßÍæ¼Ò»ñʤ£¬Èç¹ûûÓÐÍæ¼ÒÔÚÏߣ¬Ôò×î³ÙÀëÏߵĻñʤ  | 
|     '''  | 
|     winner, winnerID, loser, loserID = None, 0, None, 0  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|     playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|       | 
|     # Õ½¶·½×¶ÎÓÐÁ½¸öÍæ¼ÒʱÓÅÏȱȽÏÊä³ö  | 
|     if fbStep == FB_State_Fight and copyMapPlayerManager.GetPlayerCount() == 2:  | 
|         # Ê±¼äµ½»¹Ã»·Ö³öʤ¸º, ¸ù¾ÝÒÔϹæÔò¾ö¶¨Ê¤¸º£¬ÕâÀïÓÃÍæ¼ÒID´¦Àí£¬·ÀÖ¹½áËãʱ¶¼µôÏßÁ˵¼ÖÂûÓнá¹û  | 
|         # É˺¦Êä³ö > ÓÅÏȵ½´ïʱ¼ä > Ê£ÓàHP > ×î´óHP > playerID  | 
|           | 
|         GameWorld.Log("Á½¸öÈ˶¼ÔÚÏߣ¬¸ù¾Ý³¬Ê±¹æÔòÅжÏʤ¸ºÍæ¼Ò! roomID=%s" % (roomID))  | 
|         playerInfoList = []  | 
|         for playerID in [playerIDA, playerIDB]:  | 
|             player = copyMapPlayerManager.FindPlayerByID(playerID)  | 
|             # »¹ÊÇÀëÏßʱ¼äµÄ£¬×ßµôÏßÂß¼£¬Ô½ÍíµôÏßµÄÓ®£»ÐèÒª¼ÓÕâ¸öÂß¼Ö÷ÒªÊÇÒòΪµ±Íæ¼ÒûÓд¥·¢ÍêÕûµÇ¼Á÷³Ìµ¼ÖÂÍæ¼ÒÔÚÏßµ«ÊÇûÓд¥·¢DoEnter  | 
|             playerLeaveTick = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerID)  | 
|             if playerLeaveTick:  | 
|                 pvpDamage, sortTick, curHP, curMaxHP = 0, 0, 0, 0  | 
|                 playerInfoList.append([pvpDamage, sortTick, curHP, curMaxHP, playerLeaveTick, playerID, player])  | 
|                 GameWorld.Log("PK³¬Ê±: playerLeaveTick=%s" % (playerLeaveTick), playerID)  | 
|                 continue  | 
|             pvpDamage = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamage)  | 
|             pvpDamTick = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamUpdTick)  | 
|             sortTick = tick - pvpDamTick  | 
|             curHP = 0 if not player else GameObj.GetHP(player)  | 
|             curMaxHP = 0 if not player else GameObj.GetMaxHP(player)  | 
|             playerInfoList.append([pvpDamage, sortTick, curHP, curMaxHP, playerLeaveTick, playerID, player])  | 
|             GameWorld.Log("PK³¬Ê±: pvpDamge=%s,pvpDamTick=%s,tick=%s,sortTick=%s,HP=%s/%s,playerLeaveTick=%s"   | 
|                           % (pvpDamage, pvpDamTick, tick, sortTick, curHP, curMaxHP, playerLeaveTick), playerID)  | 
|               | 
|         playerInfoList.sort(reverse=True)  | 
|         GameWorld.Log("PK³¬Ê±, ½øÈë½áËã!playerInfoList=%s" % str(playerInfoList))  | 
|         winner = playerInfoList[0][-1] if len(playerInfoList) > 0 else None  | 
|         loser = playerInfoList[1][-1] if len(playerInfoList) > 1 else None  | 
|         winnerID = 0 if not winner else winner.GetPlayerID()  | 
|         loserID = 0 if not loser else loser.GetPlayerID()  | 
|         return winner, winnerID, loser, loserID  | 
|       | 
|     # ÆäËûÇé¿öÔòÔÚÏßÍæ¼Ò»ñʤ£¬Èç¹ûûÓÐÍæ¼ÒÔÚÏߣ¬Ôò×î³ÙÀëÏߵĻñʤ  | 
|     for i in xrange(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|         playerID = player.GetPlayerID()  | 
|         if playerID not in [playerIDA, playerIDB]:  | 
|             GameWorld.ErrLog("¸±±¾ÖÐÍæ¼Ò²»ÔÚ½øÈëµÄÍæ¼ÒIDÀ²»´¦Àí! roomID=%s,playerID=%s" % (roomID, playerID))  | 
|             continue  | 
|         winner = player  | 
|         winnerID = player.GetPlayerID()  | 
|         GameWorld.Log("³¬Ê±½áËã£¬Íæ¼ÒÔÚÏߣ¬Ö±½Ó»ñʤ: roomID=%s,winnerID=%s" % (roomID, winnerID))  | 
|         break  | 
|       | 
|     if not winner:  | 
|         playerLeaveTickA = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDA)  | 
|         playerLeaveTickB = gameFB.GetGameFBDictByKey(GameFBDict_PlayerLeaveTick % playerIDB)  | 
|         GameWorld.Log("³¬Ê±½áË㣬ûÓÐÍæ¼ÒÔÚÏߣ¬ºóÀëÏߵĻñʤ: playerLeaveTickA=%s,playerLeaveTickB=%s" % (playerLeaveTickA, playerLeaveTickB))  | 
|         # ÀëÏßtick½Ï´óµÄ¾ÍÊDZȽÏÍíÀëÏßµÄ  | 
|         if playerLeaveTickA > playerLeaveTickB:  | 
|             winnerID = playerIDA  | 
|             loserID = playerIDB  | 
|         else:  | 
|             winnerID = playerIDB  | 
|             loserID = playerIDA  | 
|     else:  | 
|         loserID = playerIDB if playerIDA == winnerID else playerIDA  | 
|     return winner, winnerID, loser, loserID  | 
|   | 
| ##¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapPrepare(tick):  | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_MapPrepare] * 1000:  | 
|         return  | 
|       | 
|     FBCommon.SetFBStep(FB_State_Fight, tick)  | 
|     FBCommon.Sync_Player_TimeTick(ChConfig.tttTowerTake, fbTimeList[Def_Time_Fight] * 1000)  | 
|     FBCommon.SyncDynamicBarrierState(IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 2), 0)  | 
|       | 
|     # Í¨Öª»ØºÏ¿ªÊ¼  | 
|     helpDict = __GetFBHelpInfo()  | 
|     helpDict["isStart"] = 1  | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in xrange(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|         FBCommon.Notify_FBHelp(player, helpDict)  | 
|           | 
|     return  | 
|   | 
| ##Õ½¶·½×¶Î  | 
| def __DoLogic_MapFight(tick):  | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_Fight] * 1000:  | 
|         return  | 
|       | 
|     winner, winnerID, loser, loserID = __GetTimeoutWinerInfo(tick)  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     GameWorld.Log("PK³¬Ê±, ½øÈë½áËã! roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID))  | 
|     __DoLogicAddPlayerWinCnt(winner, winnerID, loser, loserID, Def_OverType_TimeOut, tick)  | 
|     return  | 
|   | 
| ##¸´»î½×¶Î½×¶Î  | 
| def __DoLogic_Reborn(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     helpDict = __GetFBHelpInfo()  | 
|       | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     prepareTime = fbTimeList[Def_Time_MapPrepare] * 1000  | 
|     helpDict["prepareTime"] = prepareTime  | 
|       | 
|     roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)  | 
|     winnerID = gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum)  | 
|       | 
|     nextRoundNum = gameFB.GetGameFBDictByKey(FB_RoundNum) + 1  | 
|     gameFB.SetGameFBDict(FB_RoundNum, nextRoundNum)  | 
|       | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in xrange(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|           | 
|         playerID = player.GetPlayerID()  | 
|         gameFB.SetPlayerGameFBDict(playerID, FBPDict_RoundNum, nextRoundNum)  | 
|           | 
|         if player.GetPlayerAction() == IPY_GameWorld.paDie or GameObj.GetHP(player) <= 0:  | 
|             GameWorld.DebugLog("¸´»îÍæ¼Ò...", player.GetPlayerID())  | 
|             ChPlayer.PlayerRebornByType(player, ChConfig.rebornType_System, tick, isAddSuperBuff=False)  | 
|             __ResetPlayerState(gameFB, player, playerID)  | 
|         elif winnerID and playerID != winnerID:  | 
|             GameWorld.DebugLog("ƽ¾Ö£¬ÊäµÄÍæ¼Ò»ØÂúѪ!", playerID)  | 
|             __ResetPlayerState(gameFB, player, playerID)           | 
|         else:  | 
|             __ResetPlayerState(gameFB, player, playerID, False)  | 
|                   | 
|         FBCommon.Notify_FBHelp(player, helpDict)  | 
|           | 
|     GameWorld.Log("¿ªÊ¼ÏÂÒ»»ØºÏ: nextRoundNum=%s" % (nextRoundNum))  | 
|       | 
|     # ÖØÖÃÉ˺¦Êä³ö  | 
|     playerIDA = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 1)  | 
|     playerIDB = gameFB.GetGameFBDictByKey(GameFBDict_FBPlayerID % 2)  | 
|     gameFB.SetPlayerGameFBDict(playerIDA, FBPDict_PVPDamage, 0)  | 
|     gameFB.SetPlayerGameFBDict(playerIDA, FBPDict_PVPDamUpdTick, tick)  | 
|     gameFB.SetPlayerGameFBDict(playerIDB, FBPDict_PVPDamage, 0)  | 
|     gameFB.SetPlayerGameFBDict(playerIDB, FBPDict_PVPDamUpdTick, tick)  | 
|       | 
|     # ½øÈë×¼±¸µ¹¼ÆÊ±£¬¿ªÊ¼ÏÂÒ»¾Ö×¼±¸  | 
|     FBCommon.SetFBStep(FB_State_MapPrepare, tick)  | 
|     #FBCommon.Sync_Player_TimeTick(ChConfig.tttWaitStart, prepareTime)  | 
|     return  | 
|   | 
| ##±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| def __DoLogic_LeaveTime(tick):  | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbTimeList[Def_Time_Leave] * 1000:  | 
|         return  | 
|     FBCommon.SetFBStep(FB_State_Close, tick)  | 
|     GameWorldProcess.CloseFB(tick)  | 
|     return  | 
|   | 
| ## PVPÉ˺¦Ïà¹Ø  | 
| def OnPVPDamage(curPlayer, damageValue, tagPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     tagPlayerID = tagPlayer.GetPlayerID()  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     curPlayerDamage = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamage)  | 
|     updDamage = min(ChConfig.Def_UpperLimit_DWord, curPlayerDamage + damageValue)  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPDict_PVPDamage, updDamage)  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPDict_PVPDamUpdTick, tick)  | 
|     GameWorld.DebugLog("OnPVPDamage playerID=%s,tagPlayerID=%s,damageValue=%s,updDamage=%s,tick=%s"   | 
|                        % (playerID, tagPlayerID, damageValue, updDamage, tick))  | 
|       | 
|     #helpDict = {"PVPDamage":[playerID, updDamage, tick]}  | 
|     #FBCommon.Notify_FBHelp(curPlayer, helpDict)  | 
|     #FBCommon.Notify_FBHelp(tagPlayer, helpDict)  | 
|     return  | 
|   | 
| ##´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼  | 
| def DoFBOnKill_Player(curPlayer, defender, tick):  | 
|     winnerID = curPlayer.GetPlayerID()  | 
|     loserID = defender.GetPlayerID()  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|       | 
|     GameWorld.Log("DoFBOnKill_Player roomID=%s,winnerID=%s,loserID=%s" % (roomID, winnerID, loserID), winnerID)  | 
|     if GameWorld.GetGameFB().GetFBStep() != FB_State_Fight:  | 
|         return  | 
|       | 
|     __DoLogicAddPlayerWinCnt(curPlayer, winnerID, defender, loserID, Def_OverType_Kill, tick)  | 
|     return True  | 
|   | 
| def __DoLogicAddPlayerWinCnt(winner, winnerID, loser, loserID, overType, tick):  | 
|           | 
|     gameFB = GameWorld.GetGameFB()  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|       | 
|     winnerWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % winnerID)  | 
|     updWinCnt = winnerWinCnt + 1  | 
|     gameFB.SetGameFBDict(GameFBDict_PlayerWinCnt % winnerID, updWinCnt)  | 
|       | 
|     roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)  | 
|     gameFB.SetGameFBDict(FB_RoundWinPlayerID % roundNum, winnerID)  | 
|       | 
|     GameWorld.Log("»ØºÏ½áÊø: roomID=%s,roundNum=%s,winnerID=%s,loserID=%s,updWinCnt=%s" % (roomID, roundNum, winnerID, loserID, updWinCnt))  | 
|     isOver = (updWinCnt >= IpyGameDataPY.GetFuncCfg("CrossChamPKFB", 3))  | 
|     if not isOver:  | 
|         if winner:  | 
|             clearDeBuff = False  | 
|             # Ê¤ÀûÕßÂíÉÏÇå³ý¸ºÃæbuff£¬·ÀÖ¹ËÀÍöµ¼Ö»غϱíÏÖÒì³££¬ÈçÖж¾  | 
|             for buffType in [IPY_GameWorld.bfDeBuff, IPY_GameWorld.bfProcessDeBuff, IPY_GameWorld.bfActionBuff]:  | 
|                 buffTuple = SkillCommon.GetBuffManagerByBuffType(winner, buffType)  | 
|                 if buffTuple:  | 
|                     buffState = buffTuple[0]  | 
|                     buffCount = buffState.GetBuffCount()  | 
|                     if buffCount:  | 
|                         clearDeBuff = True  | 
|                         buffState.Clear()  | 
|                         GameWorld.DebugLog("ʤÕßÂíÉÏÇå³ý buffType=%s,buffCount=%s" % (buffType, buffCount), winner.GetPlayerID())  | 
|                           | 
|             if clearDeBuff:  | 
|                 PlayerControl.PlayerControl(winner).RefreshAllState()  | 
|                   | 
|         FBCommon.SetFBStep(FB_State_Reborn, tick)  | 
|         return  | 
|       | 
|     GameWorld.Log("    ÒÑ´ïµ½×î´óʤ³¡£¬»ñµÃ×îÖÕʤÀû£¡winnerID=%s" % winnerID)  | 
|     __DoFBPKAllOver(winner, winnerID, loser, loserID, overType, tick)  | 
|     return  | 
|   | 
| def __ResetPlayerState(gameFB, player, playerID, resetAttr=True):  | 
|     posX = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_ResetPosX)  | 
|     posY = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_ResetPosY)  | 
|     player.ResetPos(posX, posY)  | 
|       | 
|     if not resetAttr:  | 
|         return  | 
|       | 
|     if GameObj.GetHP(player) != GameObj.GetMaxHP(player):  | 
|         GameObj.SetHP(player, GameObj.GetMaxHP(player))  | 
|           | 
|     if PlayerControl.GetProDef(player) != PlayerControl.GetMaxProDef(player):  | 
|         PlayerControl.SetProDef(player, PlayerControl.GetMaxProDef(player))  | 
|           | 
|     SkillCommon.ResetAllSkillCD(player)  | 
|     return  | 
|   | 
| ## ¿ç·þPK½áÊø´¦Àí£¬×¢Òâ winner¡¢loser ²ÎÊý¿ÉÄÜΪNone  | 
| def __DoFBPKAllOver(winner, winnerID, loser, loserID, overType, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     roundWinerIDList = []  | 
|     roundNum = gameFB.GetGameFBDictByKey(FB_RoundNum)  | 
|     for roundNum in xrange(1, roundNum + 1):  | 
|         roundWinerIDList.append(gameFB.GetGameFBDictByKey(FB_RoundWinPlayerID % roundNum))  | 
|           | 
|     #¸±±¾×´Ì¬½øÈë¹Ø±Õµ¹¼ÆÊ±  | 
|     fbTimeList = IpyGameDataPY.GetFuncEvalCfg("CrossChamPKFB", 1)  | 
|     FBCommon.Sync_Player_TimeTick(ChConfig.tttLeaveMap, fbTimeList[Def_Time_Leave] * 1000)  | 
|     FBCommon.SetFBStep(FB_State_Leave, tick)  | 
|       | 
|     #·¢ËÍÒ»ÌõÏûÏ¢µ½GameServer֪ͨPK¶ÔÕ½½áÊø£¬ÒòΪµØÍ¼¿ÉÄܶÔÊÖûÀ´µ¼ÖÂûÓÐʧ°ÜÍæ¼ÒID£¬ËùÒÔ½áËãͳһÔÚGameServer´¦Àí  | 
|     overType = 1 if overType in [Def_OverType_LackPlayer, Def_OverType_PlayerExit] else 0  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     sendMsg = str([roomID, winnerID, loserID, roundWinerIDList, overType])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "CrossChampionshipPKOver", sendMsg, len(sendMsg))  | 
|     GameWorld.Log("PK½áËãSendToGameServer: roomID=%s,winnerID=%s,loserID=%s,roundWinerIDList=%s,overType=%s"   | 
|                   % (roomID, winnerID, loserID, roundWinerIDList, overType))  | 
|     return  | 
|   | 
| #¹ØÏµÓÐ3²ã£¬ÎÞ-ÓѺÃ-µÐÈË  | 
| def CheckPlayersRelation_IsFriend(curPlayer, curTagPlayer):  | 
|     return not CanAttackPlayer(curPlayer, curTagPlayer)  | 
|   | 
| ##¸±±¾ÖÐ,¹¥»÷¶ÓÓÑÂß¼  | 
| def DoCanAttackTeamer(curPlayer, curTagPlayer):  | 
|     return CanAttackPlayer(curPlayer, curTagPlayer)  | 
|   | 
| ##¸±±¾ÖÐ,ÊÇ·ñ¿É¹¥»÷  | 
| def CanAttackPlayer(curPlayer, curTagPlayer):  | 
|     fbStep = GameWorld.GetGameFB().GetFBStep()  | 
|       | 
|     if fbStep != FB_State_Fight:  | 
|         GameWorld.DebugLog("·ÇÕ½¶·½×¶Î£¬²»¿É¹¥»÷£¡")  | 
|         return False  | 
|       | 
|     return True  | 
|   |