| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_SealDemon  | 
| #  | 
| # @todo:·âħ̳  | 
| # @author xdh  | 
| # @date 2017-11-09  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ·âħ̳  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2017-11-09 14:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import FBCommon  | 
| import GameWorld  | 
| import IPY_GameWorld  | 
| import GameWorldProcess  | 
| import IpyGameDataPY  | 
| import ChConfig  | 
| import PyGameData  | 
| import PlayerControl  | 
| import NPCCommon  | 
| import ItemCommon  | 
| import ChPyNetSendPack  | 
| import ShareDefine  | 
| import EventShell  | 
| import NPCCustomRefresh  | 
| import PlayerSuccess  | 
| import PlayerActivity  | 
| import NetPackCommon  | 
| import PlayerVip  | 
| import PlayerMagicWeapon  | 
| import PlayerBossReborn  | 
| import PlayerFairyCeremony  | 
| import PlayerNewFairyCeremony  | 
| import PlayerWeekParty  | 
| import PlayerActLogin  | 
| import EventReport  | 
|   | 
| FBDict_StartTick = 'FBDict_StartTick%s' #¿ªÊ¼Ê±¼ä  | 
| FBDict_Speed = 'FBDict_Speed%s' #µôѪËÙ¶È /s  | 
| FBDict_RemainHP = 'FBDict_RemainHP%s' #Ê£Óàʱ¼ä  | 
| FBPlayerDict_EncourageLV = 'FBPlayerDict_EncourageLV'   # ¹ÄÎèµÈ¼¶  | 
| FBDict_IsOver = 'FBDict_IsOver' #ÊÇ·ñÒѽáËã, ½áËãʱµÄtick  | 
|   | 
| FBPlayerDict_Rank = "FBPlayerDict_Rank" # Íæ¼ÒÅÅÃû  | 
|   | 
| g_npcHurtDict = {}  | 
|   | 
|   | 
| def OnFBPlayerOnLogin(curPlayer):  | 
|     if not GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_VersionFix, ChConfig.Def_VerFix_FMTDouble):  | 
|         GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_VersionFix, ChConfig.Def_VerFix_FMTDouble, 1)  | 
|         needViplv = IpyGameDataPY.GetFuncCfg('DemonJarSpecial')  | 
|         if curPlayer.GetVIPLv() >= needViplv:  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FMTOldDouble, 1)  | 
|             GameWorld.DebugLog('1.3°æ±¾Ç°¿ÉÒÔË«±¶ÌôÕ½')  | 
|     NotifyFMTDouble(curPlayer)  | 
|     return  | 
|   | 
|   | 
| ## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineID Ïß·id  | 
| #  @param tick Ê±¼ä´Á  | 
| #  @return ²¼¶ûÖµ  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     IsDouble = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FMTDouble)  | 
|     newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine')  | 
|     if IsDouble and lineID not in newbielineList:  | 
|         enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)  | 
|         maxCnt = FBCommon.GetEnterFBMaxCnt(curPlayer, mapID)  | 
|         if enterCnt + 2 > maxCnt:  | 
|             return False  | 
|     return True  | 
|   | 
|   | 
| ##¸±±¾Íæ¼Ò½øÈëµã  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param mapID µØÍ¼ID  | 
| # @param lineId ·ÖÏßID  | 
| # @param ipyEnterPosInfo ¹¦ÄÜÏß·IPYÅäÖÃ×ø±êÐÅÏ¢  | 
| # @param tick Ê±¼ä´Á  | 
| # @return posX, posY, Ëæ»ú°ë¾¶(¿ÉÑ¡)  | 
| def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):  | 
|     return ipyEnterPosInfo  | 
|   | 
| ### ²éѯµØÍ¼ÊÇ·ñ¿ªÆô  | 
| ##  @param tick Ê±¼ä´Á  | 
| ##  @return ²¼¶ûÖµ  | 
| #def OnCanOpen(tick):  | 
| #    return True  | 
|   | 
| ##²éѯÊÇ·ñ¿ÉÒÔ½øÈëµØÍ¼  | 
| # @param ask:ÇëÇó½á¹¹Ìå(IPY_BMChangeMapAsk)  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return IPY_GameWorld.cme Ã¶¾Ù  | 
| def OnChangeMapAsk(ask, tick):  | 
|     return IPY_GameWorld.cmeAccept  | 
|   | 
| ##¿ªÆô¸±±¾  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks ¿ªÆô¸±±¾  | 
| def OnOpenFB(tick):  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if mapID == ChConfig.Def_FBMapID_SealDemonEx:  | 
|         return  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     bossID = CurFBLineBOSSID(lineID)  | 
|     key = ShareDefine.Def_Notify_WorldKey_GameWorldBossReborn % bossID  | 
|     GameWorld.GetGameWorld().SetGameWorldDict(key, 1)  | 
|     GameWorld.DebugLog('    Ë¢BOSSbossID=%s' % bossID)  | 
|       | 
|       | 
|     refreshIDList = FBCommon.GetFBLineRefreshNPC(ChConfig.Def_FBMapID_SealDemon, lineID)  | 
|     if refreshIDList:  | 
|         for refreshID in refreshIDList:  | 
|             NPCCustomRefresh.SetNPCRefreshByID(refreshID)  | 
|       | 
|       | 
|     return  | 
|   | 
| ## ½ø¸±±¾  | 
| #  @param curPlayer  | 
| #  @param tick  | 
| #  @return None  | 
| def DoEnterFB(curPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if mapID == ChConfig.Def_FBMapID_SealDemonEx:  | 
|         lineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqFBFuncLine)  | 
|         FBCommon.SetFBPropertyMark(lineID)  | 
|     else:  | 
|         lineID = GameWorld.GetGameWorld().GetPropertyID() - 1      | 
|       | 
|     playerCnt = GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount()  | 
|     GameWorld.DebugLog("DoEnterFB...playerCnt=%s,lineID=%s" % (playerCnt, lineID), playerID)  | 
|       | 
|     if lineID < 0:  | 
|         PlayerControl.PlayerLeaveFB(curPlayer)  | 
|         return  | 
|     hadDelTicket = FBCommon.GetHadDelTicket(curPlayer)  | 
|     if not hadDelTicket:  | 
|         FBCommon.SetHadDelTicket(curPlayer)  | 
|         PyGameData.g_fbPickUpItemDict.pop(playerID, 0)  | 
|         if playerCnt == 1:  | 
|             posX, posY = IpyGameDataPY.GetFuncEvalCfg('SealDemonFirstPos')  | 
|             GameWorld.ResetPlayerPos(curPlayer, posX, posY)  | 
|         EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_SealDemon, 0, ChConfig.CME_Log_Start)  | 
|         newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine')  | 
|         if lineID not in newbielineList:  | 
|             pass  | 
| #            FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_SealDemon)  | 
| #            # Ã¿Èջ  | 
| #            PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_SealDemon)  | 
|         else:  | 
|             hasEnter = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, False, [ChConfig.Def_FBMapID_SealDemon])  | 
|             if hasEnter:  | 
|                 GameWorld.DebugLog("    ÒѽøÈë¹ý¸ÃÐÂÊÖÏß· %s" % lineID, playerID)  | 
|                 PlayerControl.PlayerLeaveFB(curPlayer)  | 
|                 return  | 
|         UpdateHurtInfo(curPlayer, 0, True)  | 
|       | 
|     UpdateHPReduceSpeed(tick)          | 
|     gameFB = GameWorld.GetGameFB()  | 
|     # ÉϹÄÎèbuff  | 
|     encourageLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EncourageLV)  | 
|     if encourageLV > 0:  | 
|         FBCommon.AddFbEncourageBuff(curPlayer, FBPlayerDict_EncourageLV, tick)  | 
|     else:  | 
|         FBCommon.SendFBEncourageInfo(curPlayer, encourageLV)  | 
|           | 
|     #DoFBHelp(curPlayer, tick)  | 
|     return  | 
|   | 
| ##¹Ø±Õ¸±±¾  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks   | 
| def OnCloseFB(tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     lineID = gameWorld.GetPropertyID() - 1  | 
|     gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, 0)  | 
|     gameWorld.SetGameWorldDict(FBDict_Speed % lineID, 0)  | 
|     gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, 0)  | 
|       | 
|     gameWorld.SetPropertyID(0)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def DoExitFB(curPlayer, tick):  | 
|     global g_npcHurtDict  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     # Çå³ý¹ÄÎèbuff  | 
|     FBCommon.ClearEncourageBuff(curPlayer, tick)  | 
|     #×îºóÒ»ÈË  | 
|     if gameWorld.GetMapCopyPlayerManager().GetPlayerCount() == 1:  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         if mapID != ChConfig.Def_FBMapID_SealDemonEx:#µ¥È˵IJ»¹Ü  | 
|             lineID = gameWorld.GetPropertyID() - 1  | 
|             PyGameData.g_sealDemonPlayerHurtDict[lineID] = {}  | 
|             g_npcHurtDict[lineID] = {}  | 
|             gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, 0)  | 
|             GameWorld.GetGameFB().ClearGameFBDict()  | 
|             GameWorldProcess.CloseFB(tick)  | 
|             return  | 
|           | 
|     UpdateHPReduceSpeed(tick, True)  | 
|       | 
|     return  | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     FBCommon.SetHadDelTicket(curPlayer, 0)  | 
|     #Ö÷¶¯Í˳öµÄÈ¥µôÅÅÐаñÐÅÏ¢  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     playerHurtDict = PyGameData.g_sealDemonPlayerHurtDict.get(lineID, {})  | 
|     playerHurtDict.pop(curPlayer.GetPlayerID(), 0)  | 
|     PyGameData.g_sealDemonPlayerHurtDict[lineID] = playerHurtDict  | 
|     return  | 
|   | 
| ##Íæ¼ÒÇл»µØÍ¼  | 
| def DoPlayerChangeMapLogic(curPlayer):  | 
|     FBCommon.SetHadDelTicket(curPlayer, 0)  | 
|     return  | 
|   | 
| ## ÊÇ·ñ¸±±¾¸´»î  | 
| #  @param None  | 
| #  @return ÊÇ·ñ¸±±¾¸´»î  | 
| def OnPlayerReborn():  | 
|     return True  | 
|   | 
|   | 
| ## »ñµÃ¸±±¾°ïÖúÐÅÏ¢  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò£¨±»Í¨Öª¶ÔÏó£©  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBHelp(curPlayer, tick):  | 
|     #É˺¦ÅÅÐÐÐÅÏ¢  | 
|     hurtInfo = []  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     playerHurtList = PyGameData.g_sealDemonPlayerHurtDict.get(lineID, {}).items()  | 
|     npcHurtList = g_npcHurtDict.get(lineID, {}).items()  | 
|       | 
|     syncHurtList = (playerHurtList + npcHurtList)[:5]  | 
|     syncHurtList.sort(key=lambda asd:asd[1][1], reverse=True)  | 
|           | 
|     for i, info in enumerate(syncHurtList, 1):  | 
|         playerName, hurt = info[1]  | 
|         hurtDict = {}  | 
|         hurtDict["rank"] = i  | 
|         hurtDict["playerName"] = playerName  | 
|         hurtDict["hurt"] = hurt % ChConfig.Def_PerPointValue  | 
|         hurtDict["hurtEx"] = hurt / ChConfig.Def_PerPointValue  | 
|         hurtInfo.append(hurtDict)  | 
|     myRank = __GetSelfHurtRank(curPlayer)  | 
|     if myRank and myRank > 5:  | 
|         hurtDict = {}  | 
|         hurtDict["rank"] = myRank  | 
|         info = playerHurtList[myRank - 1]  | 
|         playerName, hurt = info[1]  | 
|         hurtDict["playerName"] = playerName  | 
|         hurtDict["hurt"] = hurt % ChConfig.Def_PerPointValue  | 
|         hurtDict["hurtEx"] = hurt / ChConfig.Def_PerPointValue  | 
|         hurtInfo.append(hurtDict)  | 
|       | 
|     curSpeed = GameWorld.GetGameWorld().GetGameWorldDictByKey(FBDict_Speed % lineID)   | 
|     remainHP = GetBossRemainHP(lineID, tick)  | 
|     totalHP = __GetBossTotalHP()  | 
|     hpReduceSpeed = curSpeed * 10000 / totalHP if totalHP else 0  | 
|     remainHPPer = min(1000000, remainHP * 1000000 / totalHP) if totalHP else 0  | 
|     fbHelpDict = {FBCommon.Help_lineID:lineID, "hurtInfo":hurtInfo, 'hpReduceSpeed':hpReduceSpeed, 'remainHPPer':remainHPPer}  | 
|     GameWorld.DebugLog("DoFBHelp: %s" % fbHelpDict, curPlayer.GetPlayerID())  | 
|     FBCommon.Notify_FBHelp(curPlayer, fbHelpDict)  | 
|     return  | 
|   | 
| def __GetSelfHurtRank(curPlayer):  | 
|     #»ñÈ¡×Ô¼ºµÄÅÅÃû  | 
|     playerName = curPlayer.GetName()  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     playerHurtList = __GetSortHurtList(lineID)  | 
|     myRank = 0  | 
|     for i, info in enumerate(playerHurtList):  | 
|         if playerName == info[1][0]:  | 
|             myRank = i + 1  | 
|             break  | 
|     return myRank  | 
|   | 
| ## ¸±±¾ÐÐΪ  | 
| #  @param curPlayer Íæ¼Ò  | 
| #  @param actionType ÐÐΪÀàÐÍ  | 
| #  @param actionInfo ÐÐΪÐÅÏ¢  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBAction(curPlayer, actionType, actionInfo, tick):  | 
|     if actionType == 0:  | 
|         FBCommon.FbEncourageBuff(curPlayer, FBPlayerDict_EncourageLV, actionInfo, tick)  | 
|     return  | 
|   | 
|   | 
|   | 
| ## Íæ¼Ò¶ÔNPCÔì³ÉÉ˺¦  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param curNPC   | 
| #  @param hurtHP   | 
| #  @return None  | 
| def DoFB_Player_HurtNPC(curPlayer, curNPC, hurtHP):  | 
|     UpdateHurtInfo(curPlayer, hurtHP)  | 
|     return  | 
| #  | 
| def UpdateHurtInfo(curPlayer, hurtHP, isAdd=False):  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if mapID == ChConfig.Def_FBMapID_SealDemonEx:  | 
|         return  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|       | 
|     playerName = curPlayer.GetName()   | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerHurtDict = PyGameData.g_sealDemonPlayerHurtDict.get(lineID, {})  | 
|     if playerID not in playerHurtDict:  | 
|         if not isAdd:  | 
|             return  | 
|         playerHurtDict[playerID] = [playerName, hurtHP]  | 
|     else:  | 
|         playerHurtDict[playerID][1] += hurtHP  | 
|     PyGameData.g_sealDemonPlayerHurtDict[lineID] = playerHurtDict  | 
|     return  | 
|   | 
| ## Íæ¼Ò¶ÔNPCÔì³ÉÉ˺¦  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param curNPC   | 
| #  @param hurtHP   | 
| #  @return None  | 
| def DoFB_NPC_HurtNPC(curNPC, tagNPC, hurtHP):  | 
|     global g_npcHurtDict  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     npcID = curNPC.GetNPCID()  | 
|     guardNPCIDList = __GetGuardNPCIDList(lineID)  | 
|       | 
|     if npcID not in guardNPCIDList:  | 
|         return  | 
|     npcHurtDict = g_npcHurtDict.get(lineID, {})  | 
|     if npcID not in npcHurtDict:  | 
|         npcName = curNPC.GetName().decode(ShareDefine.Def_Game_Character_Encoding).encode(GameWorld.GetCharacterEncoding())  | 
|         npcHurtDict[npcID] = [npcName, hurtHP]  | 
|     else:  | 
|         npcHurtDict[npcID][1] += hurtHP  | 
|     g_npcHurtDict[lineID] = npcHurtDict  | 
|     return  | 
|   | 
| def __GetGuardNPCIDList(lineID):  | 
|     guardNPCIDList = []  | 
|     refreshIDList = FBCommon.GetFBLineRefreshNPC(ChConfig.Def_FBMapID_SealDemon, lineID)  | 
|     if refreshIDList:  | 
|         for refreshID in refreshIDList:  | 
|             ipyData = IpyGameDataPY.GetIpyGameData("NPCCustomRefresh", refreshID)  | 
|             if not ipyData:  | 
|                 continue  | 
|             npcID = ipyData.GetRefreshNPCID()  | 
|             guardNPCIDList.append(npcID)  | 
|     return guardNPCIDList  | 
|   | 
| ##---¸±±¾×ÜÂß¼¼ÆÊ±Æ÷---  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     overTick = gameFB.GetGameFBDictByKey(FBDict_IsOver)  | 
|     # ½áËã20ÃëºóÇ¿ÖÆ¹Ø±Õ¸±±¾, ·ÀÖ¹Íæ¼Ò²»¼ñ¶«Î÷µ¼Ö²»½áË㣬ǿ¹ØºóµØ°åÉϵĶ«Î÷»áÓʼþ·¢·Å¸øÍæ¼Ò  | 
|     if overTick and tick - overTick >= ChConfig.Def_FBPickupItemTime:  | 
|         GameWorld.Log("Ç¿ÖÆÌß³öÍæ¼Ò¹Ø±Õ¸±±¾: overTick=%s,tick=%s" % (overTick, tick))  | 
|         FBCommon.DoLogic_FBKickAllPlayer()  | 
|         return  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if mapID == ChConfig.Def_FBMapID_SealDemonEx:  | 
|         return  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     if lineID <0:  | 
|         return  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)  | 
|     if not startTick:  | 
|         return  | 
|     FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 5000)  | 
|     __CheckBossHP(tick)  | 
|       | 
|       | 
|     return  | 
|   | 
| def __CheckBossHP(tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     isOver = gameFB.GetGameFBDictByKey(FBDict_IsOver)  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine')  | 
|     isNewbieLine = lineID in newbielineList  | 
|     if not isOver and GetBossRemainHP(lineID, tick) == 0:  | 
|         guardNPCIDList = __GetGuardNPCIDList(lineID)  | 
|         bossID = CurFBLineBOSSID(lineID)  | 
|         curBoss = GameWorld.FindNPCByNPCID(bossID)  | 
|         dropPosX, dropPosY = 0, 0  | 
|         if curBoss:  | 
|             dropPosX, dropPosY = curBoss.GetPosX(), curBoss.GetPosY()  | 
|           | 
|         #½áÊø ÉèÖÃBOSSËÀÍö  | 
|         FBCommon.ClearFBNPC(guardNPCIDList)  | 
|         FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)  | 
|         GameWorld.DebugLog('½áÊø ÉèÖÃBOSSËÀÍö lineID=%s' % lineID)  | 
|         playerHurtList = __GetSortHurtList(lineID)  | 
|         if not isNewbieLine:  | 
|             if playerHurtList:  | 
|                 killerName, hurtValue = playerHurtList[0][1]  | 
|                 NPCCommon.GameServer_KillGameWorldBoss(bossID, killerName, hurtValue)  | 
|                   | 
|             NPCCommon.GameServe_GameWorldBossState(bossID, 0)  | 
|               | 
|         __DoLogicSealDemonOver(1, tick, dropPosX, dropPosY)  | 
|         gameFB.SetGameFBDict(FBDict_IsOver, tick)  | 
|           | 
|     return  | 
|   | 
| def __GetSortHurtList(lineID):  | 
|     playerHurtDict = PyGameData.g_sealDemonPlayerHurtDict.get(lineID, {})  | 
|     playerHurtList = sorted(playerHurtDict.iteritems(), key=lambda asd:asd[1][1], reverse=True)  | 
|     return playerHurtList  | 
|   | 
| def __DoLogicSealDemonOver(isPass, tick, dropPosX, dropPosY):  | 
|     #½áËã  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     leaveTick = FBCommon.GetFBLineStepTime(mapID, lineID) * 1000  | 
|     playerHurtList = __GetSortHurtList(lineID)  | 
|     playerManager = GameWorld.GetPlayerManager()  | 
|     for rank, hurtInfo in enumerate(playerHurtList, 1):  | 
|         playerID = hurtInfo[0]  | 
|         curPlayer = playerManager.FindPlayerByID(playerID)  | 
|           | 
|         if curPlayer:  | 
|             gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_Rank, rank)  | 
|             if not dropPosX or not dropPosY:  | 
|                 dropPosX, dropPosY = curPlayer.GetPosX(), curPlayer.GetPosY()  | 
|             prizeItemList = GiveSealDemonAward(curPlayer, lineID, rank, dropItemMapInfo=[dropPosX, dropPosY, True])  | 
|             if not prizeItemList:  | 
|                 # Ã»ÓеôÂäʱֱ½Ó֪ͨ½áË㣬·ÀÖ¹¿¨¸±±¾  | 
|                 curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)  | 
|                 overDict = {FBCommon.Over_rank:rank, FBCommon.Over_itemInfo:prizeItemList}  | 
|                 FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_SealDemon, lineID, isPass, overDict)  | 
|             else:  | 
|                 curPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)  | 
|         else:  | 
|             leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)  | 
|             if not leaveTick:  | 
|                 continue  | 
|             if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:  | 
|                 #ÀëÏß³¬¹ý3·ÖÖӵIJ»¸ø½±Àø  | 
|                 continue  | 
|             msgStr = str([playerID, lineID, rank])  | 
|             GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'SealDemonOver', msgStr, len(msgStr))  | 
|     return  | 
|   | 
| def GiveSealDemonAward(curPlayer, lineID, rank, isMail=False, isClientSend=False, dropItemMapInfo=[]):  | 
|     newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine')  | 
|     isNewbieLine = lineID in newbielineList  | 
|     prizeMultiple = 1  | 
|     addCnt = 1  | 
|     if isNewbieLine:  | 
|         hasEnter = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, False, [ChConfig.Def_FBMapID_SealDemon])  | 
|         if hasEnter:  | 
|             #ÒѸø¹ý  | 
|             return {}  | 
|     elif isClientSend:  | 
|         return {}  | 
|     else:  | 
|         prizeMultiple = 2 if rank == 1 else 1 # µÚÒ»ÃûÖ´ÐÐË«±¶µôÂä½±Àø£¬ÆäËûÒ»´Î  | 
|         isDouble = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FMTDouble)  | 
|         if isDouble:  | 
|             addCnt = 2  | 
|     equipList = []  | 
|     prizeItemDict ={}  | 
|     bossID = CurFBLineBOSSID(lineID)  | 
|     #for _ in xrange(addCnt):  | 
|     jsonItemList, totalExp, totalMoney = NPCCommon.GiveKillNPCDropPrize(curPlayer, ChConfig.Def_FBMapID_SealDemon, {bossID:addCnt},   | 
|                                                                         mailTypeKey="SealDemonMail", isMail=isMail, prizeMultiple=prizeMultiple,   | 
|                                                                         dropItemMapInfo=dropItemMapInfo)  | 
|     for jsonItem in jsonItemList:  | 
|         if 'UserData' in jsonItem:  | 
|             equipList.append(jsonItem)  | 
|         else:  | 
|             itemID, itemCnt = jsonItem['ItemID'], jsonItem.get('Count',1)  | 
|             prizeItemDict[itemID] = prizeItemDict.get(itemID,0)+itemCnt  | 
|       | 
|     GameWorld.DebugLog("·âħ̳½áËã½±Àø: lineID=%s,bossID=%s,rank=%s,totalExp=%s,totalMoney=%s,jsonItemList=%s"   | 
|                        % (lineID, bossID, rank, totalExp, totalMoney, jsonItemList), curPlayer.GetPlayerID())  | 
|       | 
|     prizeItemList = equipList + FBCommon.GetJsonItemList(prizeItemDict.items())  | 
|     #===============================================================================================  | 
|     # if not isMail:  | 
|     #    for itemDict in prizeItemList:  | 
|     #        itemID = itemDict["ItemID"]  | 
|     #        itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)  | 
|     #        if not itemData:  | 
|     #            continue  | 
|     #        userData = itemDict.get("UserData", '')  | 
|     #        equipInfo = [itemData.GetEquipPlace(), ItemCommon.GetItemClassLV(itemData), itemData.GetItemColor(),   | 
|     #                 itemData.GetItemQuality(), userData]  | 
|     #        mapID = ChConfig.Def_FBMapID_SealDemon  | 
|     #        NPCCommon.SendGameServerGoodItemRecord(mapID, bossID, curPlayer.GetName(),   | 
|     #                                               curPlayer.GetPlayerID(), itemID, equipInfo)  | 
|     #===============================================================================================  | 
|       | 
|       | 
|     if rank == 1:  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_FMTFirst, addCnt)  | 
|     PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_SealDemon, addCnt)  | 
|   | 
|     #»÷É±ÌØ¶¨NPC³É¾Í  | 
|     PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, addCnt, [bossID])  | 
|   | 
|     #ÐÂÊÖÏß·µÄ¸üнøÈ¥¼Ç¼  | 
|     newbielineList = IpyGameDataPY.GetFuncEvalCfg('SealDemonNewbieLine')  | 
|     GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, 1, False, [ChConfig.Def_FBMapID_SealDemon])  | 
|     if lineID in newbielineList:  | 
|         FBCommon.Sync_FBPlayerFBInfoData(curPlayer, ChConfig.Def_FBMapID_SealDemon) # Í¬²½ÐÅÏ¢  | 
|     else:  | 
|         FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_SealDemon, addCnt)  | 
|       | 
|       | 
|     # Ã¿Èջ  | 
|     PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_SealDemon, addCnt)  | 
|     EventShell.EventRespons_FBEvent(curPlayer, "sealdemon_%s" % (lineID+1))  | 
|     EventShell.EventRespons_FBEvent(curPlayer, "sealdemon_0")  | 
|     #ÈÎÎñ  | 
|     if rank == 1 and lineID >= 4:  | 
|         EventShell.EventRespons_SealDemon(curPlayer)  | 
|       | 
|     PlayerMagicWeapon.SetMWPrivilegeData(curPlayer, ChConfig.MWPrivilege_SealDemonAddAttr, addCnt, True)  | 
|     PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_FMT, addCnt)  | 
|     PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_FMT, addCnt)  | 
|     PlayerNewFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_FMT, addCnt)  | 
|     PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_FMT, addCnt)  | 
|     PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_FMT, addCnt)  | 
|     return prizeItemList  | 
|   | 
| def OnPickUpItem(curPlayer, curItem, tick):  | 
|     mapItemType = curItem.GetType()  | 
|     if mapItemType == ChConfig.Def_ItemType_Money:  | 
|         return  | 
|     playerID = curPlayer.GetID()  | 
|     isEquip = ItemCommon.CheckItemIsEquip(curItem)  | 
|     jsonItem = ItemCommon.GetJsonItem(curItem)  | 
|     if playerID in PyGameData.g_fbPickUpItemDict:  | 
|         if isEquip:  | 
|             PyGameData.g_fbPickUpItemDict[playerID].append(jsonItem)  | 
|         else:  | 
|             isIn = False  | 
|             for itemInfo in PyGameData.g_fbPickUpItemDict[playerID]:  | 
|                 if itemInfo["ItemID"] == jsonItem["ItemID"] and itemInfo.get("IsBind") == jsonItem.get("IsBind"):  | 
|                     itemInfo["Count"] = itemInfo.get("Count", 1)+ jsonItem.get("Count", 1)  | 
|                     isIn = True  | 
|                     break  | 
|             if not isIn:  | 
|                 PyGameData.g_fbPickUpItemDict[playerID].append(jsonItem)  | 
|     else:  | 
|         PyGameData.g_fbPickUpItemDict[playerID] = [jsonItem]  | 
|       | 
|     playerItemCount = 0  | 
|     mapItemManager = GameWorld.GetMapItemManager()  | 
|     for index in xrange(mapItemManager.GetMapItemCount()):  | 
|         mapItem = mapItemManager.GetMapItemByIndex(index)  | 
|         if not mapItem or mapItem.IsEmpty():  | 
|             continue  | 
|           | 
|         # »¹ÓÐÊôÓÚ×Ô¼ºµÄ¶«Î÷û¼ñ²»Í¨Öª½áÊø  | 
|         if mapItem.GetOwnerID() == curPlayer.GetPlayerID():  | 
|             playerItemCount += 1  | 
|           | 
|     isItemAllPickUp = (playerItemCount <= 1)  | 
|     if not isItemAllPickUp:  | 
|         return  | 
|       | 
|     isPass = 1  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     leaveTick = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_SealDemon, lineID) * 1000  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     rank = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_Rank)  | 
|       | 
|     jsonItemList = PyGameData.g_fbPickUpItemDict.get(playerID, [])  | 
|     curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)  | 
|     overDict = {FBCommon.Over_rank:rank, FBCommon.Over_itemInfo:jsonItemList}  | 
|     FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_SealDemon, lineID, isPass, overDict)  | 
|     return  | 
|   | 
| def OnClientEndFB(curPlayer, mapID, lineID, dataList):  | 
|     #¿Í»§¶Ë¸±±¾·¢ËͽáÊø  | 
|     GameWorld.DebugLog('·âħ̳ ¿Í»§¶Ë¸±±¾·¢ËͽáÊømapID=%s,lineID=%s,dataList=%s' % (mapID,lineID,dataList), curPlayer.GetPlayerID())  | 
|     rank, hurt = dataList[:2]  | 
|     prizeItemList = GiveSealDemonAward(curPlayer, lineID, rank, False, True, [curPlayer.GetPosX(), curPlayer.GetPosY(), True])  | 
|     if rank == 1:  | 
|         bossID = CurFBLineBOSSID(lineID)  | 
|         NPCCommon.GameServer_KillGameWorldBoss(bossID, curPlayer.GetName(), hurt, False)  | 
|       | 
|     if not prizeItemList:  | 
|         leaveTick = FBCommon.GetFBLineStepTime(mapID, lineID) * 1000  | 
|         GameWorld.Log("ûÓн±Àø£¬Ö±½Ó֪ͨǰ¶Ë½áËã!mapID=%s,lineID=%s" % (mapID, lineID), curPlayer.GetPlayerID())  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, leaveTick, True)  | 
|         overDict = {FBCommon.Over_rank:rank, FBCommon.Over_itemInfo:prizeItemList}  | 
|         FBCommon.NotifyFBOver(curPlayer, ChConfig.Def_FBMapID_SealDemon, lineID, 1, overDict)  | 
|         return  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     gameFB.SetGameFBDict(FBDict_IsOver, tick)  | 
|     gameFB.SetPlayerGameFBDict(curPlayer.GetPlayerID(), FBPlayerDict_Rank, rank)  | 
|     curPlayer.Sync_TimeTick(ChConfig.tttPickupItem, 0, ChConfig.Def_FBPickupItemTime, True)  | 
|     return  | 
|   | 
|   | 
| def UpdateHPReduceSpeed(tick, isExit=False):  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if mapID == ChConfig.Def_FBMapID_SealDemonEx:  | 
|         return  | 
|     playerCnt = GameWorld.GetGameWorld().GetMapCopyPlayerManager().GetPlayerCount()  | 
|     playerCnt = playerCnt - 1 if isExit else playerCnt  | 
|     if playerCnt <=0:  | 
|         return  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     if lineID < 0:  | 
|         return  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)  | 
|     lastSpeed = gameWorld.GetGameWorldDictByKey(FBDict_Speed % lineID)  | 
|     remainHP = gameWorld.GetGameWorldDictByKey(FBDict_RemainHP % lineID)  | 
|     curSpeed = int(min(1 + 0.08 * (playerCnt - 1), 1.8) * 1000)  | 
|     if not startTick:  | 
|         startTick = tick   | 
|         lastSpeed = curSpeed  | 
|         remainHP = __GetBossTotalHP()  | 
|     remainHP = max(0, int((remainHP - (tick - startTick) / 1000.0 * lastSpeed)))  | 
|     gameWorld.SetGameWorldDict(FBDict_StartTick % lineID, tick)  | 
|     gameWorld.SetGameWorldDict(FBDict_Speed % lineID, curSpeed)  | 
|     gameWorld.SetGameWorldDict(FBDict_RemainHP % lineID, remainHP)  | 
|     GameWorld.DebugLog('    curSpeed=%s, remainHP=%s, passTime=%s, lastSpeed=%s' % (curSpeed, remainHP, tick - startTick, lastSpeed))  | 
|     FBCommon.NotifyCopyMapPlayerFBHelp(tick, DoFBHelp, 0)  | 
|     return  | 
|   | 
| def __GetBossTotalHP():  | 
|     lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     bossID = CurFBLineBOSSID(lineID)  | 
|     ipyData = IpyGameDataPY.GetIpyGameData('SealDemon', bossID)  | 
|     if not ipyData:  | 
|         return 0  | 
|     return ipyData.GetKillTime() * 1000  | 
|   | 
| def GetBossRemainHP(lineID, tick):  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|       | 
|     startTick = gameWorld.GetGameWorldDictByKey(FBDict_StartTick % lineID)  | 
|     lastSpeed = gameWorld.GetGameWorldDictByKey(FBDict_Speed % lineID)   | 
|     remainHP = gameWorld.GetGameWorldDictByKey(FBDict_RemainHP % lineID)  | 
|     if not startTick:  | 
|         startTick = tick  | 
|         remainHP = __GetBossTotalHP()  | 
|     else:  | 
|         remainHP = max(0, int((remainHP - (tick - startTick) / 1000.0 * lastSpeed)))  | 
|     return remainHP  | 
|   | 
| def GetBossRemainHPPer(lineID, tick):  | 
|     remainHP = GetBossRemainHP(lineID, tick)  | 
|     totalHP = __GetBossTotalHP()  | 
|     if not totalHP:  | 
|         return 0  | 
|     return remainHP * 100 / totalHP  | 
|   | 
| def CurFBLineBOSSID(lineID= -1):  | 
|     #¸Ã·ÖÏßË¢µÄBOSSID  | 
|     if lineID == -1:  | 
|         lineID = GameWorld.GetGameWorld().GetPropertyID() - 1  | 
|     if lineID == -1:  | 
|         return 0  | 
|     ipyData = IpyGameDataPY.GetIpyGameDataByCondition('SealDemon', {'LineID':lineID})  | 
|     if not ipyData:  | 
|         return 0  | 
|     bossID = ipyData.GetNPCID()  | 
|     return bossID  | 
|   | 
| ##Íæ¼ÒËÀÍö.  | 
| # @param curPlayer:ËÀÍöµÄÍæ¼Ò   | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| def DoPlayerDead(curPlayer):  | 
|     return  | 
|   | 
|   | 
| #// B1 03 ÉèÖ÷âħ̳¶à±¶»÷ɱ #tagCMSetFMTDouble  | 
| #  | 
| #struct    tagCMSetFMTDouble  | 
| #{  | 
| #    tagHead        Head;  | 
| #    BYTE        IsDouble;        //ÊÇ·ñË«±¶  | 
| #};  | 
| def SetFMTDouble(playerIndex, clientData, tick):  | 
|     curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(playerIndex)  | 
|     if GameWorld.GetMap().GetMapID() == ChConfig.Def_FBMapID_SealDemon:  | 
|         return  | 
|     if not curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FMTOldDouble) and not PlayerVip.GetPrivilegeValue(curPlayer, ChConfig.VIPPrivilege_FMTDouble):  | 
|         return  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FMTDouble, clientData.IsDouble)  | 
|     NotifyFMTDouble(curPlayer)  | 
|     return  | 
|   | 
| def NotifyFMTDouble(curPlayer):  | 
|     packData = ChPyNetSendPack.tagMCFMTDoubleState()  | 
|     packData.IsDouble = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FMTDouble)  | 
|     packData.OldDouble = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FMTOldDouble)  | 
|     NetPackCommon.SendFakePack(curPlayer, packData)  | 
|     return  | 
|   |