| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #---------------------------------------------------------------------  | 
| #  | 
| #---------------------------------------------------------------------  | 
| ##@package PlayerTeam  | 
| # @todo: ×é¶ÓÂß¼´¦Àí  | 
| #  | 
| # @author: panwei  | 
| # @date 2010-4-28  | 
| # @version 1.3  | 
| #  | 
| # @note:   | 
| #---------------------------------------------------------------------  | 
| # @change: "2013-04-17 20:35" Alee buff±ä¸üË¢ÐÂЧ¹ûÔÙËãÊôÐÔ£¬É¾³ýÎåÐÐ  | 
| # @change: "2015-08-24 11:00" xdh Ôö¼Ó×é¶Ó³É¾Í  | 
| # @change: "2016-11-23 19:30" hxp ½øÍ˶ÓÎéʱͬ²½±ä¸üboss×î´ó³ðºÞ¹éÊôbuff  | 
| #------------------------------------------------------------------------------   | 
| #"""Version = 2016-11-23 19:30"""  | 
| #------------------------------------------------------------------------------  | 
| import BuffSkill  | 
| import GameWorld  | 
| import PlayerControl  | 
| import FBLogic  | 
| import ChConfig  | 
| import SkillCommon  | 
| import IPY_GameWorld  | 
| import DataRecordPack  | 
| #import PlayerTruck  | 
| import ShareDefine  | 
| import SkillShell  | 
| import PlayerSuccess  | 
| import PyGameData  | 
| import PlayerVip  | 
| #---------------------------------------------------------------------  | 
|   | 
| #// B9 04 Ð޸ĶÓÎéÏà¹ØÉóºË״̬ #tagCMChangeTeamCheckState  | 
| #  | 
| #struct    tagCMChangeTeamCheckState  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        JoinReqCheck; //Èë¶ÓÉêÇëÊÇ·ñÐèÒªÉóºË, 0·ñ1ÊÇ, Ä¬ÈÏ·ñ, ¼´×Ô¶¯½ÓÊÜ  | 
| #    BYTE        InviteCheck; //×é¶ÓÑûÇëÊÇ·ñÐèÒªÉóºË, 0·ñ1ÊÇ, Ä¬ÈÏ·ñ, ¼´×Ô¶¯½ÓÊÜ  | 
| #};  | 
| def OnChangeTeamCheckState(index, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     joinReqCheck = clientData.JoinReqCheck  | 
|     inviteCheck = clientData.InviteCheck  | 
|     checkState = joinReqCheck * 10 + inviteCheck  | 
|     PlayerControl.SetTeamCheckState(curPlayer, checkState)  | 
|     GameWorld.DebugLog("Ð޸ĶÓÎéÏà¹ØÉóºË״̬: Èë¶ÓÉêÇëÊÇ·ñÐèÒªÉóºË=%s,×é¶ÓÑûÇëÊÇ·ñÐèÒªÉóºË=%s,checkState=%s"   | 
|                        % (joinReqCheck, checkState, checkState), curPlayer.GetPlayerID())  | 
|     return  | 
|   | 
| def NotifyPosInfoToPlayer(curPlayer, tick):  | 
|     ## °ÑλÖÃÐÅϢ֪ͨ¸øÕâ¸öÍæ¼Ò  | 
|     #===============================================================================================  | 
|     # team = curPlayer.GetTeam()  | 
|     # if team == None:  | 
|     #    return  | 
|     #   | 
|     # team.SyncMemberPos(curPlayer)  | 
|     #===============================================================================================  | 
|     return  | 
|   | 
| def PlayerLoginSetTeam(curPlayer, tick):  | 
|     ## Íæ¼ÒµÇ¼·þÎñÆ÷ÉèÖöÓÎé   | 
|     #Íæ¼Ò¸ÕµÇ¼, Ê²Ã´Ò²²»×ö, µÈ´ýGameServerË¢ÐÂ×Ô¼º  | 
|     return  | 
|   | 
| ## ÓÎÏ··þÎñÆ÷ˢжÓÎé(·â°ü²ÎÊý)  | 
| #  @param index Íæ¼ÒË÷Òý  | 
| #  @param tick µ±Ç°Ê±¼ä   | 
| #  @return None or True  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GameServer_OnTeam(index, tick):  | 
|     '''·ÏÆú¸ÃÂß¼£¬ÓÉ0502¡¢0503·â°ü½áºÏ´¦Àí  | 
|     ·ÏÆúÔÒò£º  | 
|     ÒòΪµ±Íæ¼ÒÓжÓÎéʱ£¬¼ÓÈë±ðÈ˵ĶÓÎ飬´Ëʱ¸ÃÍæ¼ÒÐèÒªÏÈÍ˳ö¶ÓÎ飨OnTeamͬ²½£©£¬ÔÙ¼ÓÈë¶ÓÎ飨0502ͬ²½£©  | 
|     ¶øµØÍ¼»áÏÈÊÕµ½0502°ü£¬µ¼ÖµØÍ¼¶ÓÎé¹ÜÀí³öÏÖÒì³££¬ËùÒÔÔÝʱ·ÏÆúOnTeam  | 
|     '''  | 
|     return  | 
|   | 
| #// 05 03 Íæ¼ÒÀ뿪¶ÓÎé #tagGMPlayerLeaveTeam  | 
| #  | 
| #struct    tagGMPlayerLeaveTeam  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        PlayerID;  | 
| #    DWORD        CopyMapID;  | 
| #    DWORD        TeamID;  | 
| #};  | 
| def GameServer_PlayerLeaveTeam(curPackData, tick):  | 
|     playerID = curPackData.PlayerID  | 
|     copyMapID = curPackData.CopyMapID # ÕâÀï²»ÒÀÀµÍæ¼ÒÀ´È¡copyMapID£¬·ÀÖ¹ÕÒ²»µ½Íæ¼Òµ¼ÖÂÎÞ·¨Õý³£¹ÜÀí·ÖÏß¶ÓÎé  | 
|     leaveTeamID = curPackData.TeamID  | 
|     GameWorld.DebugLog("GameServer_PlayerLeaveTeam playerID=%s,copyMapID=%s,leaveTeamID=%s"   | 
|                        % (playerID, copyMapID, leaveTeamID), playerID)  | 
|     __OnPlayerLeaveTeam(copyMapID, playerID, leaveTeamID, tick)  | 
|     return  | 
|   | 
| #// 05 02 ¶ÓÎéÐÅϢˢР#tagGMTeamInfo  | 
| #  | 
| #struct    tagGMTeamMemInfo  | 
| #{  | 
| #    DWORD        PlayerID; //¶ÓÔ±ID  | 
| #    DWORD        MapID; //ËùÔÚµØÍ¼  | 
| #    BYTE        VIPLV; //ÓÐЧVIPµÈ¼¶£¬0´ú±íÎÞVIP»òÒѹýÆÚ  | 
| #};  | 
| #  | 
| #struct    tagGMTeamInfo  | 
| #{  | 
| #    tagHead        Head;  | 
| #    DWORD        PlayerID;  | 
| #    DWORD        TeamID;  | 
| #    BYTE        TeamLV;  | 
| #    BYTE        MemCnt;  | 
| #    tagGMTeamMemInfo    MemInfoList[MemCnt];  | 
| #};  | 
| def GameServer_TeamInfo(curPackData, tick):  | 
|     playerID = curPackData.PlayerID  | 
|     teamID = curPackData.TeamID  | 
|     teamLV = curPackData.TeamLV  | 
|     dataDict = {"playerID":playerID, "teamLV":teamLV}  | 
|       | 
|     GameWorld.DebugLog("GameServer_TeamInfo playerID=%s,teamID=%s,teamLV=%s" % (playerID, teamID, teamLV), playerID)  | 
|     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|     if not curPlayer or curPlayer.IsEmpty():  | 
|         DR_Team("TeamInfo", teamID, dataDict, "curPlayer is None or empty")  | 
|         return  | 
|       | 
|     playerTeamID = curPlayer.GetTeamID()  | 
|     # ÇÐͼʱGameServerÍæ¼ÒÎÞ¶ÓÎéʱ»áͬ²½teamIDΪ0£¬ÕâÀï½øÒ»²½´¦Àí£¬·ÀÖ¹µØÍ¼Íæ¼ÒÔÚijЩÒì³£Çé¿öÏÂteamIDÓëGameServer²»Í¬²½  | 
|     if teamID == 0:  | 
|         if playerTeamID:  | 
|             __OnPlayerLeaveTeam(curPlayer.GetCopyMapID(), playerID, playerTeamID, tick)  | 
|         return  | 
|       | 
|     RefreshPlayerTeamID(curPlayer, teamID, teamLV, tick)  | 
|       | 
|     sameMapMemCount = 0 # Í¬µØÍ¼¶ÓÔ±Êý  | 
|     sameMapVIPLV = 0 # Í¬µØÍ¼VIP¼Ó³ÉµÈ¼¶  | 
|     mapID = curPlayer.GetMapID()  | 
|     teamVIPBuffIpyData = PlayerVip.GetVipPrivilegeData(ChConfig.VIPPrivilege_TeamVIPBuff)  | 
|     # ´¦Àí¶ÓÎéÈËÊýÓ°ÏìµÄÄÚÈÝ£¨¶ÓÎé¾Ñé¼Ó³É¡¢VIPbuffµÈ£©  | 
|     for memInfo in curPackData.MemInfoList:  | 
|         #memPlayerID = memInfo.PlayerID  | 
|         #GameWorld.DebugLog("    MemInfo memPlayerID=%s,MapID=%s,VIPLV=%s" % (memPlayerID, memInfo.MapID, memInfo.VIPLV))  | 
|         if mapID != memInfo.MapID:  | 
|             continue  | 
|           | 
|         # VIPbuff  | 
|         if teamVIPBuffIpyData and hasattr(teamVIPBuffIpyData, "GetVIP%d" % memInfo.VIPLV) \  | 
|             and getattr(teamVIPBuffIpyData, "GetVIP%d" % memInfo.VIPLV)():  | 
|             sameMapVIPLV += 1  | 
|               | 
|         # Í¬µØÍ¼ÈËÊý  | 
|         sameMapMemCount += 1  | 
|           | 
|     teamExpRate = max(0, (sameMapMemCount - 1) * 1000) # Ã¿¶à1¸öͬµØÍ¼¶ÓÔ±Ôö¼Ó 10%  | 
|     UpdTeamExpRate(curPlayer, teamExpRate)  | 
|       | 
|     __RefreshTeamVIPBuff(curPlayer, sameMapVIPLV, tick)  | 
|     return  | 
|   | 
| def __RefreshTeamVIPBuff(curPlayer, sameMapVIPLV, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     findBuff, buffManager, buffType, findSkill = SkillCommon.FindBuffByID(curPlayer, ChConfig.Def_SkillID_TeamVIPBuff)  | 
|     isAddTeamVIPBuff = False  | 
|     if not findBuff and sameMapVIPLV:  | 
|         isAddTeamVIPBuff = True  | 
|         #GameWorld.DebugLog("ûÓжÓÎéVIPbuff£¬¿ÉÒÔÌí¼Ó", playerID)  | 
|     if findBuff and sameMapVIPLV:  | 
|         buffLV = findBuff.GetSkill().GetSkillLV()  | 
|         if buffLV != sameMapVIPLV:  | 
|             isAddTeamVIPBuff = True  | 
|         #    GameWorld.DebugLog("ÓжÓÎéVIPbuff, µ«µÈ¼¶²»Ò»Ñù, ¿ÉÒÔÌí¼Ó!buffLV=%s,sameMapVIPLV=%s" % (buffLV, sameMapVIPLV), playerID)  | 
|         #else:  | 
|         #    GameWorld.DebugLog("ÓжÓÎéVIPbuff, µ«µÈ¼¶Ò»Ñù, ²»¿ÉÌí¼Ó!buffLV=%s,sameMapVIPLV=%s" % (buffLV, sameMapVIPLV), playerID)  | 
|           | 
|     GameWorld.DebugLog("    Í¬µØÍ¼¶ÓԱͳ¼Æ: sameMapVIPLV=%s,isAddTeamVIPBuff=%s" % (sameMapVIPLV, isAddTeamVIPBuff), playerID)  | 
|     if (findBuff and not sameMapVIPLV) or isAddTeamVIPBuff:  | 
|         __DelTeamVIPBuff(curPlayer, tick)  | 
|         #GameWorld.DebugLog("__DelTeamVIPBuff", playerID)  | 
|           | 
|     if isAddTeamVIPBuff:  | 
|         isOK = SkillCommon.AddBuffBySkillType(curPlayer, ChConfig.Def_SkillID_TeamVIPBuff, tick, sameMapVIPLV)  | 
|         GameWorld.DebugLog("__AddTeamVIPBuff sameMapVIPLV=%s,isOK=%s" % (sameMapVIPLV, isOK), playerID)  | 
|     return  | 
|   | 
| def RefreshTeamVIPBuff_OnNoTeam(curPlayer, tick):  | 
|     ## Ë¢Ð¶ÓÎéVIPbuff£¬×¢Òâ¸Ãº¯ÊýÖ»ÄÜÎÞ¶ÓÎéʱ´¥·¢  | 
|     sameMapVIPLV = 0  | 
|     playerVIPLV = curPlayer.GetVIPLv()  | 
|     teamVIPBuffIpyData = PlayerVip.GetVipPrivilegeData(ChConfig.VIPPrivilege_TeamVIPBuff)  | 
|     if teamVIPBuffIpyData and hasattr(teamVIPBuffIpyData, "GetVIP%d" % playerVIPLV) \  | 
|         and getattr(teamVIPBuffIpyData, "GetVIP%d" % playerVIPLV)():  | 
|         sameMapVIPLV += 1  | 
|     __RefreshTeamVIPBuff(curPlayer, sameMapVIPLV, tick)  | 
|     return  | 
|   | 
| ## Ë¢ÐÂÍæ¼Ò¶ÓÎéID   | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param teamID ¶ÓÎéID  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def RefreshPlayerTeamID(curPlayer, teamID, teamLV, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerTeamID = curPlayer.GetTeamID()  | 
|     playerCopyMapID = curPlayer.GetCopyMapID()  | 
|     playerTeamLV = curPlayer.GetTeamLV()  | 
|     GameWorld.DebugLog("Ë¢ÐÂÍæ¼Ò¶ÓÎéÐÅÏ¢: playerTeamID=%s,playerCopyMapID=%s,teamID=%s,teamLV=%s"   | 
|                        % (playerTeamID, playerCopyMapID, teamID, teamLV), playerID)  | 
|     curTeam = curPlayer.GetTeam()  | 
|     curPlayer.SetTeamID(teamID)  | 
|     curPlayer.SetTeamLV(teamLV)  | 
|       | 
|     dataDict = {"playerID":playerID, "playerTeamID":playerTeamID, "playerCopyMapID":playerCopyMapID,   | 
|                 "playerTeamLV":playerTeamLV, "teamLV":teamLV}  | 
|     #--------------ÊÀ½ç·þÎñÆ÷×é¶Ó±íÖÐÎÞ¶ÓÎé  | 
|     if not teamID:  | 
|         # ÕâÀï²»ÔÙ´¦ÀíÀ뿪¶ÓÎé  | 
|         return  | 
|       | 
|     #--------------ÊÀ½ç·þÎñÆ÷×é¶Ó±íÖÐÓжÓÎé  | 
|       | 
|     # £¡£¡£¡¶ÓÎé¹ÜÀíÆ÷ÔÚ·ÖÏßÄڵĠ ÐèÒª»ñÈ¡·ÖÏߵĶÓÎé¹ÜÀíÆ÷£¬²»È»¶ÓÎé¶¼ÊÇÔÚ1Ïß´´½¨  | 
|     curGameWorld = IPY_GameWorld.IPY_GameWorld(playerCopyMapID)  | 
|     curMapTeam = curGameWorld.GetTeamManager().FindTeam(teamID)  | 
|       | 
|     if curMapTeam == None:  | 
|         #GameWorld.DebugLog("    µØÍ¼ÎÞ´ËID¶ÓÎ飬´´½¨¶ÓÎ飡teamID=%s" % teamID, playerID)  | 
|         curMapTeam = curGameWorld.GetTeamManager().CreateTeam(teamID)  | 
|         if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtTeam:  | 
|             curPlayer.SetCurrentFBProperty(teamID)  | 
|         #curMapTeam.SetTeamType(recvPack.GetTeamType())  | 
|         DR_Team("RefreshPlayerTeamID_Create", teamID, dataDict)  | 
|               | 
|     if playerTeamID != teamID or not curTeam:  | 
|         isNewTeam = playerTeamID != teamID # ÇеØÍ¼/ÉÏÏßʱteamID¿ÉÄܲ»±ä£¬µ«ÊÇteamΪNone  | 
|         #GameWorld.DebugLog("    Íæ¼Òµ±Ç°ÎÞ¶ÓÎé,´¦ÀíÍæ¼Ò½ø¶Ó£¡isNewTeam=%s" % isNewTeam, playerID)  | 
|         __OnEnterTeam(curPlayer, curMapTeam, isNewTeam, tick, dataDict)  | 
|     else:  | 
|         dataDict["MemberCount"] = 0 if not curMapTeam else curMapTeam.GetMemberCount()  | 
|         DR_Team("RefreshPlayerTeamID_Update", teamID, dataDict)  | 
|           | 
|     return  | 
|   | 
| ## ½øÈë¶ÓÎé  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def __OnEnterTeam(curPlayer, curMapTeam, isNewTeam, tick, dataDict):  | 
|     teamID = curMapTeam.GetTeamID()  | 
|     memCount = curMapTeam.GetMemberCount()  | 
|     if memCount >= ShareDefine.Def_Team_MaxPlayerCount:  | 
|         GameWorld.ErrLog("¶ÓÎéÈËÊýÒÑÂú£¬Íæ¼ÒÈë¶Óʧ°Ü!teamID=%s,memCount=%s" % (teamID, memCount), curPlayer.GetPlayerID())  | 
|         DR_Team("RefreshPlayerTeamID_EnterError", teamID, dataDict, "memCount(%s) >= %s" % (memCount, ShareDefine.Def_Team_MaxPlayerCount))  | 
|         return  | 
|       | 
|     #¸æËßGameServer×Ô¼ºµÄ¸±±¾×´Ì¬  | 
|     if GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtTeam:  | 
|         curPlayer.GameServer_TeamEnterFB(1)  | 
|           | 
|     curPlayer.SetTeam(curMapTeam)  | 
|     curPlayer.SetTeamID(teamID)  | 
|     curMapTeam.AddMember(curPlayer)  | 
|     dataDict["MemberCount"] = curMapTeam.GetMemberCount()  | 
|     DR_Team("RefreshPlayerTeamID_Enter", teamID, dataDict)  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     teamPlayerIDList = PyGameData.g_teamPlayerDict.get(teamID, [])  | 
|     if playerID not in teamPlayerIDList:  | 
|         teamPlayerIDList.append(playerID)  | 
|         PyGameData.g_teamPlayerDict[teamID] = teamPlayerIDList  | 
|         GameWorld.DebugLog("Íæ¼Ò¼ÓÈë¶ÓÎé: teamID=%s,playerID=%s,%s" % (teamID, playerID, PyGameData.g_teamPlayerDict))  | 
|           | 
|     #¸Ä±äïÚ³µÉíÉϼǼµÄÖ÷ÈËÐÅÏ¢  | 
|     #PlayerTruck.ChangeTruckNoteInfo(curPlayer)  | 
|       | 
|     #ÒÔÏÂΪ½øÈëÒ»¸öеĶÓÎé¶îÍâ´¦Àí  | 
|     if not isNewTeam:  | 
|         return  | 
|     return  | 
|    | 
| def __OnPlayerLeaveTeam(copyMapID, playerID, leaveTeamID, tick):  | 
|     GameWorld.DebugLog("__OnPlayerLeaveTeam copyMapID=%s, playerID=%s, leaveTeamID=%s" % (copyMapID, playerID, leaveTeamID))  | 
|           | 
|     # £¡£¡£¡¶ÓÎé¹ÜÀíÆ÷ÔÚ·ÖÏßÄڵĠ ÐèÒª»ñÈ¡·ÖÏߵĶÓÎé¹ÜÀíÆ÷  | 
|     curGameWorld = IPY_GameWorld.IPY_GameWorld(copyMapID)  | 
|     curMapTeam = curGameWorld.GetTeamManager().FindTeam(leaveTeamID)  | 
|     if curMapTeam:  | 
|         #Íæ¼ÒÍÑÀë¶ÓÎé  | 
|         curMapTeam.DeleteMember(playerID)  | 
|         #¾É¶ÓÎéÎÞÈË,ɾ³ý¾É¶ÓÎé  | 
|         if curMapTeam.GetMemberCount() == 0:  | 
|             curGameWorld.GetTeamManager().DeleteTeam(leaveTeamID)  | 
|               | 
|     __DelPlayerIDFromTeamPlayer(playerID, False)  | 
|       | 
|     dataDict = {"playerID":playerID, "copyMapID":copyMapID}  | 
|     ### =========================== ÒÔÏÂÂß¼ÊÇÍæ¼Ò´æÔÚʱ²ÅÐèÒª´¦ÀíµÄ =================================  | 
|     curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)  | 
|     if not curPlayer or curPlayer.IsEmpty():  | 
|         DR_Team("PlayerLeaveTeam", leaveTeamID, dataDict, "curPlayer is None or empty")  | 
|         return  | 
|       | 
|     playerTeamID = curPlayer.GetTeamID()  | 
|     playerCopyMapID = curPlayer.GetCopyMapID()  | 
|     curGameWorld = IPY_GameWorld.IPY_GameWorld(playerCopyMapID)  | 
|       | 
|     dataDict.update({"playerTeamID":playerTeamID, "playerCopyMapID":playerCopyMapID})  | 
|     DR_Team("PlayerLeaveTeam", leaveTeamID, dataDict)  | 
|       | 
|     # ´¦ÀíÍæ¼ÒÀë¶Ó  | 
|     if playerTeamID == leaveTeamID:  | 
|         curPlayer.SetTeam(None)  | 
|         curPlayer.SetTeamID(0)  | 
|         curPlayer.SetTeamLV(0)  | 
|           | 
|         #×Ô¼ºÀ뿪¶ÓÎé, É¾³ý×Ô¼ºµÄbuff  | 
|         __CleanTeamEffect(curPlayer, tick)  | 
|           | 
|         #¸±±¾ÖУ¬Èç¹ûÖ»ÓÐÒ»¸öÍæ¼Ò£¬Õâ¸öÍæ¼ÒÀ뿪×é¶Ó£¬ÉèÖø±±¾IDΪ0  | 
|         if curGameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1 and GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.tmtTeam:  | 
|             curPlayer.SetCurrentFBProperty(0)  | 
|               | 
|     RefreshTeamVIPBuff_OnNoTeam(curPlayer, tick)  | 
|     return  | 
|   | 
| ## Çå³ý×é¶Óbuff  | 
| #  @param   | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.         | 
| def __CleanTeamEffect(curPlayer, tick):  | 
|     UpdTeamExpRate(curPlayer, 0)  | 
|     #__DelTeamVIPBuff(curPlayer, tick) # ¸ÄΪÎÞ×é¶ÓģʽÏÂÒ²ÓÐÓã¬ËùÒÔÕâÀï²»Çå³ý  | 
|     BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick) # Í˶ÓÇå³ý¹éÊôbuff  | 
|     return  | 
|   | 
| def __DelTeamVIPBuff(curPlayer, tick):  | 
|     if BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_TeamVIPBuff, tick):  | 
|           | 
|         #ͳһˢÐÂ״̬  | 
|         playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|         playerControl.RefreshPlayerAttrByBuff()  | 
|     return  | 
|   | 
|   | 
| def UpdTeamExpRate(curPlayer, updExpRate):  | 
|     # ¸üжÓÎé¾Ñé±¶ÂÊ¼Ó³É  | 
|     if updExpRate == curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_TeamExpRate):  | 
|         return  | 
|     curPlayer.SetDict(ChConfig.Def_PlayerKey_TeamExpRate, updExpRate)  | 
|     #GameWorld.DebugLog("UpdTeamExpRate updExpRate=%s" % updExpRate, curPlayer.GetPlayerID())  | 
|     PlayerControl.Sync_ExpRateChange(curPlayer)  | 
|     return  | 
|   | 
| def TeamPlayerLeaveMap(curPlayer, tick, isDisconnect):  | 
|     ## ×é¶ÓÍæ¼ÒÀ뿪µØÍ¼/ÏÂÏßÂß¼  | 
|       | 
|     curTeam = curPlayer.GetTeam()  | 
|       | 
|     if curTeam == None:  | 
|         #ÎÞ¶ÓÎéÍæ¼Ò,²»´¦Àí  | 
|         return  | 
|       | 
|     GameWorld.DebugLog("¶ÓÎé³ÉÔ±À뿪µØÍ¼: temaID=%s,isDisconnect=%s,copyMapID=%s" % (curTeam.GetTeamID(), isDisconnect, curPlayer.GetCopyMapID()), curPlayer.GetPlayerID())  | 
|     __CleanTeamEffect(curPlayer, tick)  | 
|     #É趨µ±Ç°Íæ¼Ò¶ÓÎéΪNone, ·ñÔòÔÚÍæ¼Ò״̬ˢеÄʱºò, ¿ÉÄÜÈ¡µ½ÂÒÖ¸Õë  | 
|     curPlayer.SetTeam(None)  | 
|     #ÏÂÏßµÄʱºò²»ÄܰÑTeamIDÉèÖÃΪ0, ·ñÔòÍæ¼ÒÉÏÏß¾ÍÕÒ²»µ½¶ÓÎéÁË  | 
|     #curPlayer.SetTeamID(0)  | 
|       | 
|     teamID = curTeam.GetTeamID()  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     dataDict = {"playerID":playerID, "isDisconnect":isDisconnect, "playerCopyMapID":curPlayer.GetCopyMapID()}  | 
|     #Èç¹û¶ÓÎéÎÞÈË,MapServerÖÐɾ³ý¶ÓÎé  | 
|     if curTeam.GetMemberCount() <= 1:  | 
|         GameWorld.GetTeamManager().DeleteTeam(teamID)  | 
|         dataDict["MemberCount"] = 0  | 
|         dataDict["DeleteTeam"] = 1  | 
|     else:  | 
|         #Èç¹û¶ÓÎ黹ÓÐÆäËûÈË,À뿪¶ÓÎé  | 
|         curTeam.DeleteMember(playerID)  | 
|         dataDict["MemberCount"] = curTeam.GetMemberCount()  | 
|         #GameWorld.Log("Íæ¼ÒÏÂÏß %d, ´Ó¶ÓÎé %d ÖÐɾ³ýÍæ¼Ò"%(curPlayer.GetPlayerID(), curTeam.GetTeamID()))  | 
|     DR_Team("PlayerLeaveMap", teamID, dataDict)  | 
|           | 
|     if not isDisconnect:  | 
|         __DelPlayerIDFromTeamPlayer(playerID, True)  | 
|     return True  | 
|   | 
| def __DelPlayerIDFromTeamPlayer(playerID, isleaveMap):  | 
|     for teamID, teamPlayerIDList in PyGameData.g_teamPlayerDict.items():  | 
|         if playerID not in teamPlayerIDList:  | 
|             continue  | 
|         teamPlayerIDList.remove(playerID)  | 
|         GameWorld.DebugLog("Íæ¼ÒÀ뿪¶ÓÎé!isleaveMap=%s,teamID=%s,playerID=%s" % (isleaveMap, teamID, playerID))  | 
|         if not teamPlayerIDList:  | 
|             PyGameData.g_teamPlayerDict.pop(teamID)  | 
|             GameWorld.DebugLog("    µØÍ¼¶ÓÎéûÈËÁË£¬É¾³ý¶ÓÎ飡teamID=%s" % (teamID))  | 
|         GameWorld.DebugLog("    PyGameData.g_teamPlayerDict=%s" % (PyGameData.g_teamPlayerDict))  | 
|     return  | 
|   | 
| def GetMapTeamPlayerIDList(teamID):  | 
|     # µØÍ¼¶ÓÎéÍæ¼ÒIDÁÐ±í£¬º¬ÀëÏßÍæ¼Ò£¬Èç¹ûËùÓжÓÔ±¶¼ÀëÏߣ¬´ËʱµØÍ¼µÄTeamÊDz»´æÔڵ쬵«ÊÇÀëÏß±£»¤Ê±¼äÄڵĶÓÔ±Íæ¼ÒID»¹ÊÇ»áÔÚ´ËÁбíÖÐ  | 
|     return PyGameData.g_teamPlayerDict.get(teamID, [])  | 
|   | 
| def OnCheckTeamPlayerDisconnectTimeout(tick):  | 
|     ## ¼ì²é¶ÓÎéÍæ¼Ò, Ã¿·ÖÖÓ¼ì²éÒ»´Î  | 
|       | 
|     #GameWorld.DebugLog("¼ì²é¶ÓÎéÍæ¼ÒÀëÏß³¬Ê±Çé¿ö: PyGameData.g_teamPlayerDict=%s" % PyGameData.g_teamPlayerDict)  | 
|     isTimeout = False  | 
|     for teamID, teamPlayerIDList in PyGameData.g_teamPlayerDict.items():  | 
|         timeoutPlayerIDList = []  | 
|         for playerID in teamPlayerIDList:  | 
|             leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)  | 
|             if not leaveTick:  | 
|                 continue  | 
|             # ³¬¹ýÀëÏß±£»¤  | 
|             if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:  | 
|                 timeoutPlayerIDList.append(playerID)  | 
|                 GameWorld.DebugLog("    ÒƳýÀëÏß±£»¤µÄ¶ÓÔ±: teamID=%s,leaveTick=%s,tick=%s,playerID=%s" % (teamID, leaveTick, tick, playerID))  | 
|                 isTimeout = True  | 
|                   | 
|         for timeoutPlayerID in timeoutPlayerIDList:  | 
|             teamPlayerIDList.remove(timeoutPlayerID)  | 
|               | 
|         if not teamPlayerIDList:  | 
|             PyGameData.g_teamPlayerDict.pop(teamID)  | 
|             GameWorld.DebugLog("    ¶ÓÎéÒÑûÓб£»¤ÖеĶÓÔ±, É¾³ý¶ÓÎé¼Ç¼!teamID=%s" % teamID)  | 
|               | 
|     if isTimeout:  | 
|         GameWorld.DebugLog("    PyGameData.g_teamPlayerDict=%s" % PyGameData.g_teamPlayerDict)  | 
|     return  | 
|   | 
| ## À뿪¸±±¾£¨gameµ÷Óã©  | 
| #  @param index Íæ¼ÒË÷Òý  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def GameServer_LeaveFB(index, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)  | 
|     FBLogic.GameServer_LeaveFB(curPlayer, tick)  | 
|     return  | 
|   | 
| def DR_Team(eventName, teamID, dataDict, info=""):  | 
|     drDict = {"EventName":eventName, "TeamID":teamID, "Info":info}  | 
|     drDict.update(dataDict)  | 
|     DataRecordPack.SendEventPack("Team_%s" % GameWorld.GetMap().GetMapID(), drDict)  | 
|     return  | 
|   |