| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_MergePK  | 
| #  | 
| # @todo:¿ç·þÆ¥ÅäPK  | 
| # @author hxp  | 
| # @date 2015-10-22  | 
| # @version 1.4  | 
| #  | 
| # @change: "2015-11-04 12:00" hxp ÐÞ¸ÄÕóÓªµ¼ÖÂÎÞ·¨PKÎÊÌâ(ÅäÖÃÖÐתµØÍ¼²»ÖØÖÃÕóÓª)  | 
| # @change: "2015-12-28 17:00" hxp Õ½¶·½á¹û¸ÄΪGameServer֪ͨ¿Í»§¶Ë  | 
| # @change: "2016-02-26 17:00" hxp PK³¬Ê±Ê¤¸º¹æÔòÅжÏÐÞ¸Ä  | 
| # @change: "2016-12-20 17:30" hxp ÓÀºã°æÐ޸ģ»Ö§³ÖÅäÖÃʤÀû³¡´ÎÖÆ£»»ý·Ö¼ÆËã¸ÄΪÓÉGameServerË㣬µØÍ¼Ö»Ëãʤ¸º  | 
| # ÏêϸÃèÊö: ¿ç·þÆ¥ÅäPK  | 
| #  | 
| #---------------------------------------------------------------------  | 
| #"""Version = 2016-12-20 17:30"""  | 
| #---------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import ShareDefine  | 
| import ReadChConfig  | 
| import IPY_GameWorld  | 
| import GameWorldProcess  | 
| import PlayerControl  | 
| import ChPlayer  | 
| import FBCommon  | 
| import ChConfig  | 
| import ChEquip  | 
|   | 
|   | 
| #---¸±±¾ÅäÖöÔÓ¦keyÖµ---  | 
| (  | 
| Def_Time_MaxWait, # 0×µÈ´ýʱ¼ä, ºÁÃë  | 
| Def_Time_MapPrepare, # 1·ÇÌØÐ§×¼±¸Ê±¼ä, ºÁÃë  | 
| Def_Time_MapPrepareEff, # 2ÌØÐ§µ¹¼ÆÊ±×¼±¸Ê±¼ä, ºÁÃë  | 
| Def_Time_Fight, # 3Õ½¶·Ê±¼ä, ºÁÃë  | 
| Def_Time_Leave, # 4½áÊøÍ˳öʱ¼ä, ºÁÃë  | 
| Def_Pos_Enter, # 5½ø³¡×ø±ê[(A·½×ø±êx,y), (B·½×ø±êx,y)],  | 
| Def_Pos_Start, # 6¿ªÊ¼PK³õÊ¼×ø±ê[(A·½×ø±êx,y), (B·½×ø±êx,y)],  | 
| Def_MaxWinCnt, # 7×î´óʤ³¡£¬Èç2´ú±íÈý¾ÖÁ½Ê¤ÖÆ£¬3´ú±íÎå¾ÖÈýÊ¤ÖÆ  | 
| Def_AutoRebornTime, # 8ËÀÍö×Ô¶¯¸´»îʱ¼ä  | 
| Def_GateIDList, # 9¹âǽNPCIDÁÐ±í  | 
| Def_GatePos, # 10¹âǽÏÔʾʱ¿ÉÒÆ¶¯×ø±êµã[(A·½×ø±êx,y), (B·½×ø±êx,y)]  | 
| Def_IsFullHP, # 11ÿ¾ÖÖØÐ¿ªÊ¼Ê±ÊÇ·ñÂúѪ  | 
| ) = range(12)  | 
|   | 
| # µ±Ç°¸±±¾µØÍ¼µÄ״̬  | 
| (  | 
| FB_State_Open, # µØÍ¼¿ªÆô  | 
| FB_State_Waiting, # µÈ´ý¶ÔÊÖ½×¶Î  | 
| FB_State_MapPrepare, # µØÍ¼×¼±¸  | 
| FB_State_MapPrepareEff, # µØÍ¼×¼±¸µ¹¼ÆÊ±ÌØÐ§  | 
| FB_State_Fight, # Õ½¶·  | 
| FB_State_Reborn, # ¸´»îµÈ´ýʱ¼ä  | 
| FB_State_FreeTime, # ×ÔÓÉʱ¼ä  | 
| FB_State_Over, # ¸±±¾½áÊø  | 
| ) = range(8)  | 
|   | 
| # ¶ÔÕ½½áÊøÀàÐͶ¨Òå  | 
| (  | 
| Def_OverType_LackPlayer, # È±ÉÙ¶ÔÊÖ  | 
| Def_OverType_PlayerExit, # ¶ÔÊÖÍ˳ö(ÊÓΪÈÏÊä)  | 
| Def_OverType_Kill, # »÷ɱ¶ÔÊÖ  | 
| Def_OverType_TimeOut, # PKʱ¼ä³¬Ê±  | 
| ) = range(4)  | 
|   | 
| # ¸±±¾Ïà¹Ø×Öµäkey  | 
| GameFBDict_FirstEnterID = "FBD_FirstEnterID" # µÚÒ»¸ö½øÈëµÄÍæ¼ÒID  | 
| GameFBDict_PlayerWinCnt = "FBD_PlayerWinCnt_%s" # Íæ¼ÒÒÑ»ñʤ´ÎÊý, ²ÎÊý[playerID]  | 
|   | 
| FBPDict_PVPDamage = "FBPD_PVPDamage" # Íæ¼ÒÉ˺¦Êä³ö  | 
| FBPDict_PVPDamUpdTick = "FBPD_PVPDamUpdTick" # ¸üÐÂÉ˺¦tick  | 
|   | 
| ## »ñµÃ¸±±¾ÅäÖà  | 
| #  @param None  | 
| #  @return ÅäÖÃÐÅÏ¢  | 
| def GetMergePKCfg():             | 
|     return ReadChConfig.GetEvalChConfig("MergePK_Cfg")    | 
|   | 
| ##¿ªÆô¸±±¾  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def OnOpenFB(tick):  | 
|     FBCommon.SetFBStep(FB_State_Open, tick)  | 
|     FBCommon.OpenOrCloseDoorEx(GetMergePKCfg()[Def_GateIDList], 1)  | 
|     return True  | 
|   | 
| ##ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param mapID µØÍ¼ID  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     return True  | 
|   | 
| ##Íæ¼Ò½øÈ븱±¾  | 
| # @param curPlayer:Íæ¼ÒʵÀý  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def DoEnterFB(curPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerVSRoomID = curPlayer.GetVsRoomId()  | 
|     factionID = curPlayer.GetFaction()  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|       | 
|     GameWorld.Log("DoEnterFB roomID=%s,playerVSRoomID=%s,factionID=%s"   | 
|                   % (roomID, playerVSRoomID, factionID), playerID)  | 
|       | 
|     mergePkCfg = GetMergePKCfg()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep == FB_State_Open:  | 
|         gameFB.SetGameFBDict(GameFBDict_FirstEnterID, playerID)  | 
|         FBCommon.SetFBStep(FB_State_Waiting, tick)  | 
|         GameWorld.Log("    µÚÒ»¸ö½øÈ룬ÉèÖø±±¾½øÈëµÈ´ý¶ÔÊֽ׶Σ¡roomID=%s" % (roomID), playerID)  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttFBAddTime, 0, mergePkCfg[Def_Time_MaxWait], True)  | 
|     elif fbStep == FB_State_Waiting:  | 
|         FBCommon.SetFBStep(FB_State_MapPrepare, tick)  | 
|         GameWorld.Log("    µÚ¶þ¸ö½øÈ룬ÉèÖø±±¾½øÈë×¼±¸½×¶Î£¡roomID=%s" % (roomID), playerID)  | 
|         totalPrepareTime = mergePkCfg[Def_Time_MapPrepare] + mergePkCfg[Def_Time_MapPrepareEff]  | 
|         FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttWaitStart, totalPrepareTime, 0, True)  | 
|     else:  | 
|         PlayerControl.PlayerLeaveFB(curPlayer)  | 
|         return  | 
|       | 
|     startPosX, startPosY = mergePkCfg[Def_Pos_Start][0 if factionID == ShareDefine.CampType_Justice else 1]  | 
|     curPlayer.ResetPos(startPosX, startPosY)  | 
|     return  | 
|   | 
| ##¸±±¾Íæ¼Ò½øÈëµã  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param mapID µØÍ¼ID  | 
| # @param lineId ·ÖÏßID  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ×ø±êÁбí(X,Y)  | 
| def OnGetFBEnterPos(curPlayer, mapID, lineId, tick):  | 
|     factionID = curPlayer.GetFaction()  | 
|     posIndex = 0 if factionID == ShareDefine.CampType_Justice else 1  | 
|     GameWorld.DebugLog("OnGetFBEnterPos factionID=%s,posIndex=%s" % (factionID, posIndex), curPlayer.GetPlayerID())  | 
|     return GetMergePKCfg()[Def_Pos_Enter][posIndex]  | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def DoExitFB(curPlayer, tick):  | 
|     # ½áËãʱ¼ä  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep == FB_State_FreeTime:  | 
|         # ÓÉÓÚ½áÊøºóÍæ¼ÒÊÇ·¢ËÍ·µ»ØÔ·þÎñÆ÷µÄ£¬¹ÊÔÚ¿ç·þÖÐÈÏΪÊǵôÏߣ¬¶ø²»ÊÇÖ÷¶¯Í˳ö¸±±¾£¬ËùÒÔ²»»á´¥·¢¼ì²é¹Ø±Õ¸±±¾Âß¼  | 
|         # ÕâÀï½øÐÐÊÖ¶¯¼ì²éÒ»´Î£¬·ÀÖ¹Íæ¼Ò¿ìËÙ½áÊøÕ½ºóºó¸±±¾²»»á¹Ø±Õ£¬µ¼ÖÂÒ»¶¨Ê±¼äÄÚ»áÕ¼Óøø±±¾·ÖÏß×ÊÔ´  | 
|         GameWorldProcess.OnPlayerLeaveMapCloseFB()  | 
|         return  | 
|       | 
|     # ×¼±¸¼°Õ½¶·½×¶Î£¬Íæ¼ÒÏÂÏߣ¬Ö±½ÓËãʧ°Ü£¬¶ÔÊÖ»ñʤ  | 
|     if fbStep not in [FB_State_MapPrepare, FB_State_MapPrepareEff, FB_State_Fight]:  | 
|         return  | 
|       | 
|     winner = None  | 
|     winnerID = 0  | 
|     loser = curPlayer  | 
|     exitPlayerID = curPlayer.GetPlayerID()  | 
|       | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in range(0, playerManager.GetPlayerCount()):  | 
|         player = playerManager.GetPlayerByIndex(i)  | 
|           | 
|         if player.GetID() == 0:  | 
|             continue  | 
|           | 
|         playerID = player.GetPlayerID()  | 
|         if playerID != loser.GetPlayerID():  | 
|             winner = player  | 
|             winnerID = playerID  | 
|             break  | 
|           | 
|     GameWorld.Log("Íæ¼ÒÔÚ×¼±¸orÕ½¶·½×¶ÎÏÂÏߣ¬Ö±½Óʧ°Ü£¬¶ÔÊÖ»ñʤ!exitPlayerID=%s,winnerID=%s"   | 
|                   % (exitPlayerID, winnerID))  | 
|     __DoMergePKOver(winner, loser, Def_OverType_PlayerExit, tick)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     GameWorld.Log("Íæ¼ÒÖ÷¶¯À뿪¸±±¾: roomID=%s" % roomID, curPlayer.GetPlayerID())  | 
|     return  | 
|   | 
|   | 
| ## »ñµÃ¸±±¾°ïÖúÐÅÏ¢  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò£¨±»Í¨Öª¶ÔÏó£©  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBHelp(curPlayer, tick):  | 
|     return  | 
|   | 
| ##---¸±±¾×ÜÂß¼¼ÆÊ±Æ÷---  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|       | 
|     if fbStep == FB_State_Waiting:  | 
|         __DoLogic_Waiting(tick)  | 
|     elif fbStep == FB_State_MapPrepare:  | 
|         __DoLogic_MapPrepare(tick)  | 
|     elif fbStep == FB_State_MapPrepareEff:  | 
|         __DoLogic_MapPrepareEff(tick)  | 
|     elif fbStep == FB_State_Fight:  | 
|         __DoLogic_MapFight(tick)  | 
|     elif fbStep == FB_State_Reborn:  | 
|         __DoLogic_Reborn(tick)  | 
|     elif fbStep == FB_State_FreeTime:  | 
|         __DoLogic_FreeTime(tick)  | 
|     else:  | 
|         pass  | 
|           | 
|     return  | 
|   | 
| ##µÈ´ýÍæ¼Ò½øÈë½×¶Î´¦Àí  | 
| def __DoLogic_Waiting(tick):  | 
|     __BackToMergePKPrepareArea(tick)  | 
|     maxWaitTime = GetMergePKCfg()[Def_Time_MaxWait]  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < maxWaitTime:  | 
|         return  | 
|       | 
|     # ¶ÔÊÖûÀ´£¬Ö±½Ó»ñʤ  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     winnerID = gameFB.GetGameFBDictByKey(GameFBDict_FirstEnterID)  | 
|     winner = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(winnerID)  | 
|     GameWorld.Log("¶ÔÊÖûÀ´£¬Ö±½Ó»ñʤ£¡roomID=%s,winnerID=%s" % (roomID, winnerID))  | 
|     __DoMergePKOver(winner, None, Def_OverType_LackPlayer, tick)  | 
|     return  | 
|   | 
| ##¸±±¾×¼±¸Ê±¼ä  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapPrepare(tick):  | 
|     __BackToMergePKPrepareArea(tick)  | 
|     mergePKCfg = GetMergePKCfg()  | 
|     mapPrepare = mergePKCfg[Def_Time_MapPrepare]  | 
|       | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < mapPrepare:  | 
|         return  | 
|     __SetFBStepToPrepareEff(tick)  | 
|     return  | 
|   | 
| def __SetFBStepToPrepareEff(tick):  | 
|     #Í¨ÖªÌØÐ§  | 
|     mergePKCfg = GetMergePKCfg()  | 
|     mapPrepareEff = mergePKCfg[Def_Time_MapPrepareEff]  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttAddUpTime, mapPrepareEff)  | 
|     FBCommon.SetFBStep(FB_State_MapPrepareEff, tick)  | 
|     FBCommon.OpenOrCloseDoorEx(mergePKCfg[Def_GateIDList], 1)  | 
|     return  | 
|   | 
|   | 
| ##¸±±¾×¼±¸Ê±¼ä£¬Í¨Öª¿Í»§¶Ëµ¹¼ÆÊ±  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapPrepareEff(tick):  | 
|     __BackToMergePKPrepareArea(tick)  | 
|     mergePKCfg = GetMergePKCfg()  | 
|     prepareEffTime = mergePKCfg[Def_Time_MapPrepareEff]  | 
|       | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < prepareEffTime:  | 
|         return  | 
|       | 
|     fightTime = mergePKCfg[Def_Time_Fight]  | 
|       | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in range(copyMapPlayerManager.GetPlayerCount()):  | 
|         curPlayer = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|           | 
|         if curPlayer == None or curPlayer.IsEmpty():  | 
|             continue  | 
|           | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, fightTime, True)  | 
|               | 
|     FBCommon.SetFBStep(FB_State_Fight, tick)  | 
|     FBCommon.OpenOrCloseDoorEx(mergePKCfg[Def_GateIDList], 0)  | 
|     return  | 
|   | 
| def __BackToMergePKPrepareArea(tick):  | 
|     ##¼ì²éÊÇ·ñÔÚ×¼±¸Çø    | 
|     gatePosList = GetMergePKCfg()[Def_GatePos]  | 
|     playManager = GameWorld.GetMapCopyPlayerManager()  | 
|       | 
|     #²»×¼Íæ¼Ò³¬¹ýÖ¸¶¨ÇøÓò  | 
|     for i in range(playManager.GetPlayerCount()):  | 
|         curPlayer = playManager.GetPlayerByIndex(i)  | 
|         # Ã»ÓÐÕâ¸öÍæ¼Ò  | 
|         if not curPlayer:  | 
|             continue  | 
|   | 
|         factionID = curPlayer.GetFaction()  | 
|         posIndex = 0 if factionID == ShareDefine.CampType_Justice else 1  | 
|         checkPosX, resetPos = gatePosList[posIndex]  | 
|         # ¼ì²éÍæ¼ÒµÄ×ø±ê  | 
|         curPosX = curPlayer.GetPosX()  | 
|         if posIndex == 0 and curPosX > checkPosX:  | 
|             GameWorld.ResetPlayerPos(curPlayer, resetPos[0], resetPos[1])  | 
|         if posIndex == 1 and curPosX < checkPosX:  | 
|             GameWorld.ResetPlayerPos(curPlayer, resetPos[0], resetPos[1])  | 
|               | 
|     return  | 
|   | 
| ##Õ½¶·½×¶Î  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×¼±¸Ê±¼ä  | 
| def __DoLogic_MapFight(tick):  | 
|     mergePKCfg = GetMergePKCfg()  | 
|     fightTime = mergePKCfg[Def_Time_Fight]  | 
|       | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fightTime:  | 
|         return  | 
|       | 
|     # Ê±¼äµ½»¹Ã»·Ö³öʤ¸º, ¸ù¾ÝÒÔϹæÔò¾ö¶¨Ê¤¸º  | 
|     # É˺¦Êä³ö > ÓÅÏȵ½´ïʱ¼ä > Ê£ÓàHP > playerID  | 
|     playerInfoList = []  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     #µØÍ¼Íæ¼Ò»î¶¯¿ªÊ¼Ê±µÄËæ»ú×ø±êµã  | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in range(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|           | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|           | 
|         playerID = player.GetPlayerID()  | 
|         pvpDamage = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamage)  | 
|         pvpDamTick = gameFB.GetPlayerGameFBDictByKey(playerID, FBPDict_PVPDamUpdTick)  | 
|         sortTick = tick - pvpDamTick  | 
|         playerInfoList.append([pvpDamage, sortTick, player.GetHP(), playerID, player])  | 
|         GameWorld.DebugLog("PK³¬Ê±: playerID=%s,pvpDamge=%s,pvpDamTick=%s,tick=%s,sortTick=%s"   | 
|                            % (playerID, pvpDamage, pvpDamTick, tick, sortTick))  | 
|           | 
|     playerInfoList.sort(reverse=True)  | 
|     winner = playerInfoList[0][-1] if len(playerInfoList) > 0 else None  | 
|     loser = playerInfoList[1][-1] if len(playerInfoList) > 1 else None  | 
|     GameWorld.Log("PK³¬Ê±, ½øÈë½áËã!playerInfoList=%s" % str(playerInfoList))  | 
|     __DoLogicAddPlayerWinCnt(winner, loser, Def_OverType_TimeOut, tick)  | 
|     return  | 
|   | 
| ##±ÈÈü¸´»î  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| def __DoLogic_Reborn(tick):  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < GetMergePKCfg()[Def_AutoRebornTime]:  | 
|         return  | 
|       | 
|     startPosList = GetMergePKCfg()[Def_Pos_Start]  | 
|     isFullHP = GetMergePKCfg()[Def_IsFullHP]  | 
|     copyMapPlayerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in range(copyMapPlayerManager.GetPlayerCount()):  | 
|         player = copyMapPlayerManager.GetPlayerByIndex(i)  | 
|           | 
|         if player == None or player.IsEmpty():  | 
|             continue  | 
|           | 
|         if player.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|             GameWorld.DebugLog("¸´»îÍæ¼Ò...", player.GetPlayerID())  | 
|             ChPlayer.PlayerRebornByType(player, ChConfig.rebornType_FBUseItem, tick)  | 
|               | 
|         factionID = player.GetFaction()  | 
|         posIndex = 0 if factionID == ShareDefine.CampType_Justice else 1  | 
|         posX, posY = startPosList[posIndex]  | 
|         player.ResetPos(posX, posY)  | 
|         # ÉèÖÃÂúѪ  | 
|         if isFullHP and player.GetHP() != player.GetMaxHP():  | 
|             player.SetHP(player.GetMaxHP())  | 
|               | 
|     # ½øÈëÌØÐ§×¼±¸µ¹¼ÆÊ±£¬¿ªÊ¼ÏÂÒ»¾Ö×¼±¸  | 
|     __SetFBStepToPrepareEff(tick)  | 
|     return   | 
|   | 
| def DecFreeRebornCount(curPlayer):  | 
|     # Ö±½Ó·µ»ØÃâ·Ñ¸´»î  | 
|     return True  | 
|   | 
| ##±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| # @param tick  Ê±ÖÓ  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ±ÈÈü½áÊøµÄ¿ÕÏÐʱ¼ä  | 
| def __DoLogic_FreeTime(tick):  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < GetMergePKCfg()[Def_Time_Leave]:  | 
|         return  | 
|       | 
|     #FBCommon.DoLogic_FBKickAllPlayer()  | 
|     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  | 
|   | 
| ##´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param defender ·ÀÊØÕß  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ²¼¶ûÖµ  | 
| # @remarks ´¦Àí¸±±¾ÖÐɱËÀÍæ¼ÒÂß¼  | 
| 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, defender, Def_OverType_Kill, tick)  | 
|     return True  | 
|   | 
| def __DoLogicAddPlayerWinCnt(winner, loser, overType, tick):  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|   | 
|     winnerID = 0 if not winner else winner.GetPlayerID()  | 
|     loserID = 0 if not loser else loser.GetPlayerID()  | 
|       | 
|     winnerWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % winnerID)  | 
|     updWinCnt = winnerWinCnt + 1  | 
|     gameFB.SetGameFBDict(GameFBDict_PlayerWinCnt % winnerID, updWinCnt)  | 
|       | 
|     isOver = (updWinCnt >= GetMergePKCfg()[Def_MaxWinCnt])  | 
|     if not isOver and loser:  | 
|         __NotifyFBOver(gameFB, winner, loser, isOver)  | 
|           | 
|         # ÖØÖÃÉ˺¦Êä³ö  | 
|         gameFB.SetPlayerGameFBDict(winnerID, FBPDict_PVPDamage, 0)  | 
|         gameFB.SetPlayerGameFBDict(winnerID, FBPDict_PVPDamUpdTick, tick)  | 
|         gameFB.SetPlayerGameFBDict(loserID, FBPDict_PVPDamage, 0)  | 
|         gameFB.SetPlayerGameFBDict(loserID, FBPDict_PVPDamUpdTick, tick)  | 
|           | 
|         GameWorld.DebugLog("    Î´´ïµ½×î´óʤ³¡£¬ÓжÔÊÖ£¬½øÈ븴»îµÈ´ý½×¶Î£¡", winnerID)  | 
|         FBCommon.SetFBStep(FB_State_Reborn, tick)  | 
|         return  | 
|       | 
|     # ÎÞ¶ÔÊÖ»òÒÑ´ïµ½×î´óʤ³¡Êý  | 
|     GameWorld.DebugLog("    ÒÑ´ïµ½×î´óʤ³¡£¬»ñµÃ×îÖÕʤÀû£¡", winnerID)  | 
|     __DoMergePKOver(winner, loser, overType, tick)  | 
|     return  | 
|   | 
| def __NotifyFBOver(gameFB, winner, loser, isOver):  | 
|     winnerID = 0 if not winner else winner.GetPlayerID()  | 
|     winnerAccID = "" if not winner else winner.GetAccID()  | 
|     loserID = 0 if not loser else loser.GetPlayerID()  | 
|     loserAccID = "" if not loser else loser.GetAccID()  | 
|       | 
|     winnerWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % winnerID)  | 
|     winnerDamage = gameFB.GetPlayerGameFBDictByKey(winnerID, FBPDict_PVPDamage)  | 
|     loserWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % loserID)  | 
|     loserDamage = gameFB.GetPlayerGameFBDictByKey(loserID, FBPDict_PVPDamage)  | 
|       | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     overDict = {"roomID":roomID, "winnerAccID":winnerAccID, "loserAccID":loserAccID,   | 
|                 "winnerWinCnt":winnerWinCnt, "loserWinCnt":loserWinCnt, "isOver":isOver,  | 
|                 "winnerDamage":winnerDamage, "loserDamage":loserDamage,   | 
|                 "winnerID":winnerID, "loserID":loserID}   | 
|     GameWorld.Log("µ¥¾Ö½áËã %s" % str(overDict), roomID)  | 
|     #֪ͨ¿Í»§¶ËÐÅÏ¢, ¿Í»§¶Ë¸ù¾ÝroomID×ÔÐнâÎöµ±Ç°µÄgroupType¼°battleIndex  | 
|     #µ¥¾Ö½áËãÓÉMapServerͬ²½£¬×îºóÒ»¾ä½áËãÓÉGameServerͬ²½  | 
|     if winner:  | 
|         FBCommon.Notify_FB_Over(winner, overDict)  | 
|     if loser:  | 
|         FBCommon.Notify_FB_Over(loser, overDict)  | 
|     return  | 
|   | 
| ## ¿ç·þPK½áÊø´¦Àí  | 
| def __DoMergePKOver(winner, loser, overType, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     mergePKCfg = GetMergePKCfg()  | 
|     winnerID = 0 if not winner else winner.GetPlayerID()  | 
|     loserID = 0 if not loser else loser.GetPlayerID()  | 
|   | 
|     winnerWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % winnerID)  | 
|     loserWinCnt = gameFB.GetGameFBDictByKey(GameFBDict_PlayerWinCnt % loserID)   | 
|       | 
|     #¸±±¾×´Ì¬½øÈë¹Ø±Õµ¹¼ÆÊ±  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttLeaveMap, mergePKCfg[Def_Time_Leave])  | 
|     FBCommon.SetFBStep(FB_State_FreeTime, tick)  | 
|       | 
|     #__NotifyFBOver(gameFB, winner, loser, 1)  | 
|   | 
|     #·¢ËÍÒ»ÌõÏûÏ¢µ½GameServer֪ͨPK¶ÔÕ½½áÊø  | 
|     roomID = GameWorld.GetGameWorld().GetPropertyID()  | 
|     sendMsg = str([roomID, winnerID, loserID, winnerWinCnt, loserWinCnt, ChEquip.GetPlayerEquipView(winner),   | 
|                    ChEquip.GetPlayerEquipView(loser), overType])  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'MergePKOver', sendMsg, len(sendMsg))  | 
|     GameWorld.Log("PK½áËãSendToGameServer: %s" % sendMsg)  | 
|     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):  | 
|     fbStep = GameWorld.GetGameFB().GetFBStep()  | 
|       | 
|     if fbStep != FB_State_Fight:  | 
|         GameWorld.DebugLog("·ÇÕ½¶·½×¶Î£¬²»¿É¹¥»÷£¡")  | 
|         return False  | 
|       | 
|     return curPlayer.GetFaction() != curTagPlayer.GetFaction()  | 
|   |