| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_QueenRelics  | 
| #  | 
| # @todo:æ´»ÊÒż£  | 
| # @author hxp  | 
| # @date 2017-12-17  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: æ´»ÊÒż£  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2017-12-17 15:00"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import IPY_GameWorld  | 
| import GameWorldProcess  | 
| import NPCCustomRefresh  | 
| import PlayerControl  | 
| import ItemControler  | 
| import ItemCommon  | 
| import GameWorld  | 
| import FBCommon  | 
| import ChConfig  | 
| import GameMap  | 
| import BuffSkill  | 
| import PlayerSuccess  | 
| import ShareDefine  | 
| import EventShell  | 
| import EventReport  | 
| import ChPlayer  | 
| import FBHelpBattle  | 
| import IpyGameDataPY  | 
| import PlayerWeekParty  | 
| import PlayerActLogin  | 
|   | 
|   | 
| #½×¶Îʱ¼ä  | 
| (  | 
| Def_PrepareTime, # ¸±±¾×¼±¸Ê±¼ä(Ãë)  | 
| Def_FightTime, # ½øÐÐʱ¼ä(Ãë)  | 
| Def_LeaveTime, # Í˳öʱ¼ä(Ãë)  | 
| ) = range(3)  | 
|   | 
| #µ±Ç°¸±±¾µØÍ¼µÄ״̬  | 
| (  | 
| FB_Step_CallHelp, # ÖúÕ½ÕÙ»½  | 
| FB_Step_Prepare, # ¸±±¾µÈ´ý  | 
| FB_Step_Fighting, # ¸±±¾½øÐÐÖÐ  | 
| FB_Step_Over, # ¸±±¾½áÊø  | 
| FB_Step_Close, # ¸±±¾¹Ø±Õ  | 
| ) = range(5)  | 
|   | 
| FBKey_RefreshStep = 'RefreshStep' # Ë¢¹Ö½×¶ÎÊý, ´Ó1¿ªÊ¼   | 
| FBKey_IsLastRefreshStep = 'SetGameFBDict' # ÊÇ·ñ×îºóÒ»²¨Ë¢¹Ö  | 
| FBKey_NextLineID = 'NextLineID' # ¿ÉÒÔÌôÕ½ÏÂÒ»¹ØµÄlineID, ´óÓÚ0´ú±í¿ÉÒÔ¼ÌÐøÌôÕ½  | 
|   | 
| FBKey_NeedKillNPCNum = 'NeedKillNPCNum '  # ÐèÒª»÷ɱ²Å¿É¹ý¹ØµÄNPCIDÊý, ¼´±àºÅkey¸öÊý  | 
| FBKey_NeedKillNPCID = 'NeedKillNPCID_%s'  # ÐèÒª»÷ɱ²Å¿É¹ý¹ØµÄNPCID, ²ÎÊý(±àºÅ)  | 
| FBKey_NeedKillNPCCount = 'NeedKillNPCCount_%s'  # ÐèÒª»÷ɱ²Å¿É¹ý¹ØµÄNPCID¸öÊý, ²ÎÊý(NPCID)  | 
| FBKey_KillNPCCount = 'KillNPCCount_%s'  # µ±Ç°½×¶ÎÒÑ»÷ɱ¹ÖÎïÊý, ²ÎÊý(NPCID)  | 
|   | 
| FBPKey_IsInFBOnDay = "IsInFBOnDay" # Íæ¼ÒÊÇ·ñ¸±±¾ÖйýÌì  | 
| FBPKey_RewardLine = "RewardLine" # Íæ¼ÒÒѾ½áËãµ½µÄ½±ÀøÌìÊý, ¼Ç¼ֵʱҪ+1  | 
|   | 
| def OnFBPlayerOnDay(curPlayer):  | 
|       | 
|     mapID = FBCommon.GetRecordMapID(curPlayer.GetMapID())  | 
|     if mapID != ChConfig.Def_FBMapID_QueenRelics:  | 
|         return  | 
|       | 
|     # ÉèÖÃÔÚ¸±±¾ÖйýÌì  | 
|     GameWorld.GetGameFB().SetPlayerGameFBDict(curPlayer.GetPlayerID(), FBPKey_IsInFBOnDay, 1)  | 
|     GameWorld.DebugLog("ÉèÖÃæ´»ÊÌôÕ½ÖйýÌ죡", curPlayer.GetPlayerID())   | 
|     return  | 
|   | 
| ## ÊÇ·ñ¿É½øÈë  | 
| #  @param curPlayer  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineId ·ÖÏßID  | 
| #  @param tick  | 
| #  @return ÊÇ·ñ¿É½øÈë  | 
| def OnEnterFBEvent(curPlayer, mapID, lineId, tick):  | 
|     if not lineId:  | 
|         return True  | 
|       | 
|     preLineID = lineId - 1 # ÉÏÒ»²ã  | 
|     mapID = FBCommon.GetRecordMapID(mapID)  | 
|     maxGrade = len(FBCommon.GetFBLineGrade(mapID, lineId))  | 
|     preLineGrade = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, preLineID, False, [mapID])  | 
|     canEnter = preLineGrade >= maxGrade  | 
|     if not canEnter:  | 
|         GameWorld.DebugLog("ÉÏÒ»²ã·Ç×î´óÆÀ¼¶¹ý¹Ø£¬ÎÞ·¨ÌôÕ½ÏÂÒ»²ã£¡lineID=%s,preLineID=%s,preLineGrade=%s,maxGrade=%s"   | 
|                            % (lineId, preLineID, preLineGrade, maxGrade), curPlayer.GetPlayerID())  | 
|         return False  | 
|     #ÅжÏÕ½Á¦ÊÇ·ñÂú×ã±¾²ãÒªÇó  | 
|     helpIpyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", mapID, lineId)  | 
|     if helpIpyData:  | 
|         if curPlayer.GetFightPower() < helpIpyData.GetFightPowerMin():  | 
|             GameWorld.DebugLog("Õ½Á¦²»×ã%s£¬ÎÞ·¨ÌôÕ½±¾²ã£¡lineID=%s" % (helpIpyData.GetFightPowerMin(), lineId), curPlayer.GetPlayerID())  | 
|             return False  | 
|     return True  | 
|   | 
| ## ½øÈë´«Ë굋  | 
| #  @param curPlayer  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineId ·ÖÏßID  | 
| #  @param tick  | 
| #  @return ×ø±êÁбí(X,Y)  | 
| def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):  | 
|     return ipyEnterPosInfo  | 
|   | 
| ## ÊÇ·ñ¿ÉÒÔ½øÈë  | 
| #  @param ask ÇëÇóÐÅÏ¢  | 
| #  @param tick  | 
| #  @return »Ø¸´ÊÇ·ñͨ¹ýÇëÇó  | 
| def OnChangeMapAsk(ask, tick):  | 
|     return IPY_GameWorld.cmeAccept  | 
|   | 
| ## »Ø³Ç¸´»îΪ¸±±¾Öи´»î  | 
| def OnPlayerReborn():  | 
|     return True  | 
|   | 
| ## ÖØÖø±±¾¸´»îÍæ¼Ò×ø±êµã  | 
| def OnResetFBRebornPlacePos(curPlayer, rebornPlace, tick):  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     enterX, enterY = __GetQueenRelicsLinePos(mapID, lineID)  | 
|     curPlayer.ResetPos(enterX, enterY)  | 
|     return  | 
|   | 
| ## ÕÙ»½ÖúÕ½Íê³É  | 
| def OnCallHelpBattleOK(curPlayer, tick):  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     DoQueenRelicsLinePrepare(curPlayer, lineID, tick)  | 
|     return  | 
|   | 
| ## ½ø¸±±¾  | 
| #  @param curPlayer  | 
| #  @param tick  | 
| #  @return None  | 
| def DoEnterFB(curPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     GameWorld.DebugLog("DoEnterFB...", playerID)  | 
|   | 
|     gameFB = GameWorld.GetGameFB()  | 
|       | 
|     if not FBCommon.GetHadDelTicket(curPlayer):  | 
|         if not FBCommon.DelFBEnterTicket(curPlayer, GameWorld.GetGameWorld().GetMapID())[0]:  | 
|             PlayerControl.PlayerLeaveFB(curPlayer)  | 
|             GameWorld.ErrLog("½øÈ븱±¾¿Û³ýÃÅÆ±Ê§°Ü£¡", curPlayer.GetPlayerID())  | 
|             return 0  | 
|         FBCommon.SetHadDelTicket(curPlayer)  | 
|           | 
|     mapID = ChConfig.Def_FBMapID_QueenRelics  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     reqLineID = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_ReqFBFuncLine)  | 
|       | 
|     fbStep = gameFB.GetFBStep()  | 
|     if fbStep == FB_Step_CallHelp:  | 
|         FBCommon.SetFBPropertyMark(reqLineID, curPlayer)  | 
|         lineID = reqLineID  | 
|         FBHelpBattle.SendGameServer_RefreshHelpBattlePlayer(curPlayer, mapID, lineID)  | 
|         return  | 
|       | 
|     if reqLineID > lineID:  | 
|         FBCommon.SetFBPropertyMark(reqLineID, curPlayer)  | 
|         lineID = reqLineID  | 
|         DoQueenRelicsLinePrepare(curPlayer, lineID, tick)  | 
|     else:  | 
|         fbLineTime = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|         if fbStep == FB_Step_Prepare:  | 
|             notify_tick = fbLineTime[Def_PrepareTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|             curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)  | 
|               | 
|         elif fbStep == FB_Step_Fighting:  | 
|             notify_tick = fbLineTime[Def_FightTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|             curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)  | 
|             FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(GameWorld.GetGameWorld().GetMapID(), lineID), curPlayer)  | 
|               | 
|     DoFBHelp(curPlayer, tick)  | 
|     return  | 
|   | 
| def DoQueenRelicsLinePrepare(curPlayer, lineID, tick):  | 
|     # ÒòΪ¸Ã¸±±¾Ö§³Ö¶à³¡¾°£¬ËùÒÔ¸±±¾°æ±¾ºÅ²»ÄÜÒÔµ¥³¡¾°ÎªÖ÷£¬ÐèÒªÒÔÍæ¼ÒΪÖ÷£¬Íæ¼Ò±¾´ÎÌôÕ½µÄ°æ±¾ºÅ´ø×Å×ß  | 
|     GameWorld.DebugLog("¹¦ÄÜÏß¿ªÊ¼£¬½øÈë×¼±¸½×¶Î; lineID=%s" % (lineID), curPlayer.GetPlayerID())  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     gameFB.SetGameFBDict(FBKey_RefreshStep, 0)  | 
|     gameFB.SetGameFBDict(FBKey_IsLastRefreshStep, 0)  | 
|     gameFB.SetGameFBDict(FBKey_NextLineID, 0)  | 
|     gameFB.SetGameFBDict(ChConfig.Def_FB_Grade, 0)  | 
|       | 
|     FBCommon.SetFBPropertyMark(lineID, curPlayer)  | 
|     FBCommon.SetFBStep(FB_Step_Prepare, tick)  | 
|     __RefreshQueenRelicsNPC(True, False, tick, curPlayer)  | 
|     fbLineTime = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|     curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, fbLineTime[Def_PrepareTime] * 1000, True)  | 
|     EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_QueenRelics, lineID, ChConfig.CME_Log_Start)  | 
|       | 
|     helpIpyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|     if helpIpyData:  | 
|         gameFB.SetGameFBDict(ChConfig.FBPD_HelpBattleFBBaseHurt, helpIpyData.GetRobotBaseHurt())  | 
|         gameFB.SetGameFBDict(ChConfig.FBPD_HelpBattleFBFightPower, helpIpyData.GetFightPowerMin())  | 
|         GameWorld.DebugLog("    ¸üи±±¾ÖúÕ½»úÆ÷ÈË»ù´¡É˺¦: lineID=%s,RobotBaseHurt=%s,fbFightPower=%s"   | 
|                            % (lineID, helpIpyData.GetRobotBaseHurt(), helpIpyData.GetFightPowerMin()))  | 
|     return  | 
|   | 
| ##¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|       | 
|     fbStep = GameWorld.GetGameFB().GetFBStep()  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     fbLineTime = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|       | 
|     # ¸±±¾×¼±¸  | 
|     if fbStep == FB_Step_Prepare:  | 
|         __DoLogic_FB_Prepare(tick, fbLineTime)      | 
|     # ¸±±¾½øÐÐÖÐ  | 
|     elif fbStep == FB_Step_Fighting:  | 
|         FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(GameWorld.GetGameWorld().GetMapID(), lineID))  | 
|         __DoLogic_FB_Fighting(tick, fbLineTime)  | 
|     # ¸±±¾½áÊø  | 
|     elif fbStep == FB_Step_Over:  | 
|         __DoLogic_FB_Over(tick, fbLineTime)  | 
|           | 
|     return  | 
|   | 
| ## ¸±±¾×¼±¸Âß¼  | 
| #  @param tick:ʱ¼ä´Á  | 
| #  @return ÎÞÒâÒå  | 
| def __DoLogic_FB_Prepare(tick, fbLineTime):  | 
|     # ¼ä¸ôδµ½  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbLineTime[Def_PrepareTime] * 1000:  | 
|         return  | 
|       | 
|     # ¸±±¾¿ªÊ¼  | 
|     __RefreshQueenRelicsNPC(False, True, tick)  | 
|     FBCommon.SetFBStep(FB_Step_Fighting, tick)  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttTowerTake, fbLineTime[Def_FightTime] * 1000)  | 
|     return  | 
|   | 
| ## ¸±±¾½øÐÐÖÐ  | 
| #  @param tick:ʱ¼ä´Á  | 
| #  @return ÎÞÒâÒå  | 
| def __DoLogic_FB_Fighting(tick, fbLineTime):  | 
|     # ¼ä¸ôδµ½  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbLineTime[Def_FightTime] * 1000:  | 
|         return  | 
|       | 
|     __DoQueenRelicsOver(False, tick)  | 
|     return  | 
|   | 
| ##¸±±¾¹Ø±ÕÖÐ  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾¹Ø±ÕÖÐ  | 
| def __DoLogic_FB_Over(tick, fbLineTime):  | 
|     # ¼ä¸ôδµ½  | 
|     # ·þÎñ¶ËÇ¿ÖÆ½áÊø¸±±¾Ê±¼äÊʵ±ÑÓ³¤20Ã룬Ìṩһ¶¨µÄʱ¼ä¸ø¶ÓÎé³ÉÔ±ÇÐÏÂÒ»¹ØÓà  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < (fbLineTime[Def_LeaveTime] * 1000 + 20000):  | 
|         return  | 
|       | 
|     #¸±±¾¹Ø±Õ  | 
|     GameWorldProcess.CloseFB(tick)  | 
|     FBCommon.SetFBStep(FB_Step_Close, tick)  | 
|     return  | 
|   | 
| def __RefreshQueenRelicsNPC(isNextStep, isRefreshNow, tick, notifyPlayer=None):  | 
|     ## Ë¢Ð½׶εĹÖÎï  | 
|       | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     refreshNPCCfg = FBCommon.GetFBLineRefreshNPC(ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|     # [{µÚÒ»²¨Ë¢¹Ö¹æÔòID:¹ý¹ØÊÇ·ñÐèÒª»÷ɱ, ...}, {µÚ¶þ²¨Ë¢¹Ö¹æÔòID:¹ý¹ØÊÇ·ñÐèÒª»÷ɱ, ...}, ...]  | 
|     if not refreshNPCCfg:  | 
|         GameWorld.ErrLog("ûÓÐÅäÖÃË¢¹ÖÐÅÏ¢!lineID=%s" % lineID)  | 
|         return  | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     step = gameFB.GetGameFBDictByKey(FBKey_RefreshStep)  | 
|     if isNextStep:  | 
|         step += 1  | 
|     maxStep = len(refreshNPCCfg)  | 
|     if step > maxStep:  | 
|         GameWorld.DebugLog("³¬¹ý×î´óË¢¹Ö½×¶Î!step=%s,maxStep=%s" % (step, maxStep))  | 
|         return  | 
|     refreshIDDict = refreshNPCCfg[step - 1]  | 
|       | 
|     needKillNPCDict = {}  | 
|     for refreshID, needKill in refreshIDDict.items():  | 
|         if not needKill:  | 
|             continue  | 
|         npcCountList = NPCCustomRefresh.GetNPCRefreshCountList(refreshID)  | 
|         if not npcCountList:  | 
|             return  | 
|         for npcID, count in npcCountList:  | 
|             needKillNPCDict[npcID] = needKillNPCDict.get(npcID, 0) + count  | 
|               | 
|     if not needKillNPCDict:  | 
|         GameWorld.ErrLog("ûÓÐÐèÒª»÷ɱ²Å¿É¹ý¹ØµÄNPCÅäÖÃ!lineID=%s,step=%s" % (lineID, step))  | 
|         return  | 
|       | 
|     isLastStep = int(step == maxStep)  | 
|     gameFB.SetGameFBDict(FBKey_RefreshStep, step)  | 
|     gameFB.SetGameFBDict(FBKey_IsLastRefreshStep, isLastStep)  | 
|       | 
|     # ¸üÐÂÉèÖùý¹ØÐèÒª»÷ɱµÄNPCÐÅÏ¢  | 
|     needKillNPCIDList = needKillNPCDict.keys()  | 
|     needKillNum = len(needKillNPCIDList)  | 
|     gameFB.SetGameFBDict(FBKey_NeedKillNPCNum, needKillNum)  | 
|     for i, npcID in enumerate(needKillNPCIDList):  | 
|         gameFB.SetGameFBDict(FBKey_NeedKillNPCID % i, npcID)  | 
|         gameFB.SetGameFBDict(FBKey_NeedKillNPCCount % npcID, needKillNPCDict[npcID])  | 
|           | 
|     if isNextStep:  | 
|         GameWorld.DebugLog("Ë¢¹Ö×¼±¸: step=%s,isLastStep=%s,refreshIDDict=%s,needKillNPCDict=%s"   | 
|                            % (step, isLastStep, refreshIDDict, needKillNPCDict))  | 
|           | 
|     # Ë¢¹Ö  | 
|     if isRefreshNow:  | 
|         GameWorld.DebugLog("ˢйÖÎï: step=%s,isLastStep=%s,refreshIDDict=%s,needKillNPCDict=%s"   | 
|                            % (step, isLastStep, refreshIDDict, needKillNPCDict))  | 
|         for refreshID in refreshIDDict.keys():  | 
|             NPCCustomRefresh.SetNPCRefreshByID(refreshID)  | 
|           | 
|     if notifyPlayer:  | 
|         DoFBHelp(notifyPlayer, tick)  | 
|         return  | 
|           | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     for i in range(playerManager.GetPlayerCount()):  | 
|         curPlayer = playerManager.GetPlayerByIndex(i)  | 
|         if not curPlayer:  | 
|             continue  | 
|         DoFBHelp(curPlayer, tick)  | 
|           | 
|     return  | 
|   | 
| ## ¸±±¾Ê±¼äµ½¹Ø±Õ  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnCloseFB(tick):  | 
|     return  | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| def DoExitFB(curPlayer, tick):  | 
|     return  | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     # É¾³ýµ¥²ãÓÐЧµÄbuff, ÊÈѪµ¤  | 
|     BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_QueenRelicsItemBuff, tick)  | 
|   | 
|     return  | 
|   | 
| ##¸±±¾°ïÖúÐÅÏ¢  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ÓÃÓÚ֪ͨÕóÓª±È·ÖÌõ  | 
| def DoFBHelp(curPlayer, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     step = gameFB.GetGameFBDictByKey(FBKey_RefreshStep)  | 
|     grade = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|       | 
|     npcDict = {}  | 
|     needNum = gameFB.GetGameFBDictByKey(FBKey_NeedKillNPCNum)  | 
|     for i in xrange(needNum):  | 
|         npcID = gameFB.GetGameFBDictByKey(FBKey_NeedKillNPCID % i)  | 
|         killCount = gameFB.GetGameFBDictByKey(FBKey_KillNPCCount % npcID)  | 
|         npcDict[npcID] = killCount  | 
|           | 
|     fbHelpDict = {FBCommon.Help_lineID:lineID, FBCommon.Help_grade:grade,  | 
|                   FBCommon.Help_npc:FBCommon.GetJsonNPCKillList(npcDict)}  | 
|     if step:  | 
|         fbHelpDict[FBCommon.Help_step] = step  | 
|           | 
|     FBCommon.NotifyFBHelp(curPlayer, lineID, fbHelpDict)  | 
|     return  | 
|   | 
| def DoFB_Npc_KillNPC(attacker, curNPC, tick):  | 
|     __FBNPCOnKilled(curNPC, tick)  | 
|     return  | 
|   | 
| ##Íæ¼ÒɱËÀNPC  | 
| # @param curPlayer:Íæ¼ÒʵÀý  | 
| # @param curNPC:µ±Ç°±»É±ËÀµÄNPC  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| # @remarks Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| def DoFB_Player_KillNPC(curPlayer, curNPC, tick):  | 
|     __FBNPCOnKilled(curNPC, tick)  | 
|     return  | 
|   | 
| def __FBNPCOnKilled(curNPC, tick):  | 
|     curNPCID = curNPC.GetNPCID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     killNPCCount = gameFB.GetGameFBDictByKey(FBKey_KillNPCCount % curNPCID) + 1  | 
|     gameFB.SetGameFBDict(FBKey_KillNPCCount % curNPCID, killNPCCount)  | 
|       | 
|     # ÅжÏÐèÒª»÷ɱ²Å¿É¹ý¹ØµÄNPCÊÇ·ñ¶¼ÒÑ»÷ɱ  | 
|     isNeedKillNPCID = False  | 
|     isAllKill = True  | 
|     needNum = gameFB.GetGameFBDictByKey(FBKey_NeedKillNPCNum)  | 
|     for i in xrange(needNum):  | 
|         npcID = gameFB.GetGameFBDictByKey(FBKey_NeedKillNPCID % i)  | 
|         if curNPCID == npcID:  | 
|             isNeedKillNPCID = True  | 
|               | 
|         if isAllKill:  | 
|             needKillCount = gameFB.GetGameFBDictByKey(FBKey_NeedKillNPCCount % npcID)  | 
|             killCount = gameFB.GetGameFBDictByKey(FBKey_KillNPCCount % npcID)  | 
|             if killCount < needKillCount:  | 
|                 isAllKill = False  | 
|                   | 
|     if not isAllKill:  | 
|         if isNeedKillNPCID:  | 
|             playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|             for index in xrange(playerManager.GetPlayerCount()):  | 
|                 player = playerManager.GetPlayerByIndex(index)  | 
|                 if player:  | 
|                     DoFBHelp(player, tick)  | 
|         return  | 
|       | 
|     if gameFB.GetGameFBDictByKey(FBKey_IsLastRefreshStep):  | 
|         if isNeedKillNPCID:  | 
|             GameWorld.DebugLog("ËùÓйÖÎïÒÑ»÷ɱ£¡¹ý¹Ø£¡")  | 
|             __DoQueenRelicsOver(True, tick)  | 
|     else:  | 
|         __RefreshQueenRelicsNPC(True, True, tick)  | 
|     return  | 
|   | 
| ## ¼ì²éÊÇ·ñ¿É¹¥»÷£¬ Ö÷Åж¨²»¿É¹¥»÷µÄÇé¿ö£¬ÆäËûÂß¼ÓÉÍâ²ã¾ö¶¨  | 
| #  @param attacker ¹¥»÷·½  | 
| #  @param defender ·ÀÊØ·½  | 
| #  @return bool  | 
| def CheckCanAttackTagObjInFB(attacker, defender):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     if gameFB.GetFBStep() != FB_Step_Fighting:  | 
|         return False  | 
|     return True  | 
|   | 
| def __DoQueenRelicsOver(isPass, tick):  | 
|     # Õ½¶·³¬Ê±  | 
|     if GameWorld.GetGameFB().GetFBStep() == FB_Step_Over:  | 
|         GameWorld.DebugLog("ÒѾ½áËã¹ý£¡²»Öظ´½áËã!")  | 
|         return  | 
|     costTime = tick - GameWorld.GetGameFB().GetFBStepTick()  | 
|     NPCCustomRefresh.CloseFBCustomRefresh(tick) # ÏȹرÕÔÙÇå¹Ö  | 
|       | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     lineID = FBCommon.GetFBPropertyMark()  | 
|     dataMapID = FBCommon.GetRecordMapID(mapID)  | 
|     FBCommon.UpdateFBGrade(tick, FBCommon.GetFBLineGrade(mapID, lineID)) # ½áËãÇ°Ç¿ÖÆË¢ÐÂÒ»´ÎÆÀ¼¶  | 
|     grade = GameWorld.GetGameFB().GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|       | 
|     FBCommon.SetFBStep(FB_Step_Over, tick) # Ðè·ÅÔÚÆÀ¼¶Ë¢ÐºóÉèÖà  | 
|       | 
|     fbLineTime = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_QueenRelics, lineID)  | 
|     rewardRateList = FBCommon.GetFBGradeRewardRateList(mapID)  | 
|     maxGrade = len(rewardRateList)  | 
|     curPlayer = FBCommon.GetCurSingleFBPlayer()  | 
|     if not curPlayer:  | 
|         return  | 
|     nextLineID = 0  | 
|     # ×î¸ßÆÀ¼¶¹ý¹Ø£¬¿ÉÌôÕ½ÏÂÒ»¹Ø  | 
|     if isPass and grade >= maxGrade:  | 
|         nextLineIpyData = FBCommon.GetFBLineIpyData(mapID, lineID + 1, False)  | 
|         nextLineID = 0 if not nextLineIpyData else (lineID + 1) # ÕÒ²»µ½ÏëÏÂÒ»²ãÊý¾Ý´ú±íͨ¹Ø  | 
|         if nextLineID:  | 
|             helpIpyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", mapID, nextLineID)  | 
|             if helpIpyData and curPlayer.GetFightPower() < helpIpyData.GetFightPowerMin():  | 
|                 nextLineID = 0 #Õ½Á¦²»×㣬Ôò²»¿ÉÌôÕ½ÏÂÒ»¹Ø  | 
|                   | 
|               | 
|       | 
|     gameFB = GameWorld.GetGameFB()  | 
|     gameFB.SetGameFBDict(FBKey_NextLineID, nextLineID)  | 
|     GameWorld.DebugLog("¿ªÊ¼¹ý¹Ø½áËã: lineID=%s,grade=%s,isPass=%s,nextLineID=%s" % (lineID, grade, isPass, nextLineID))  | 
|       | 
| #    playerManager = GameWorld.GetMapCopyPlayerManager()  | 
| #    for index in xrange(playerManager.GetPlayerCount()):  | 
| #        curPlayer = playerManager.GetPlayerByIndex(index)  | 
| #        if not curPlayer:  | 
| #            continue  | 
|     DoFBHelp(curPlayer, tick)  | 
|       | 
|     playerID = curPlayer.GetPlayerID()  | 
|     rewardLine = lineID #gameFB.GetPlayerGameFBDictByKey(playerID, FBPKey_RewardLine) ¸Ä³ÉÖ»¸ø±¾²ã½±Àø  | 
|     needSyncFBData = False  | 
|     overDict = {}  | 
|     if isPass:  | 
|         overDict = {FBCommon.Over_costTime:costTime, FBCommon.Over_grade:grade}  | 
|         curGrade = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, False, [dataMapID])  | 
|         if curGrade < grade:  | 
|             GameWorld.DebugLog("    ¸üйý¹ØÆÀ¼¶: dataMapID=%s,lineID=%s,curGrade=%s,rewardGrade=%s"   | 
|                                % (dataMapID, lineID, curGrade, grade), curPlayer.GetPlayerID())  | 
|             GameWorld.SetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_PlayerFBStar_MapId, lineID, grade, False, [dataMapID])  | 
|             needSyncFBData = True  | 
|             if grade >= maxGrade: #Ê×´ÎS¼¶½±Àø  | 
|                 lineReward = FBCommon.GetFBLineReward(dataMapID, lineID)  | 
|                 firstrewardItemList = [[itemID,itemCnt,0] for itemID,itemCnt in lineReward[0]]  | 
|                 ItemControler.GivePlayerItemOrMail(curPlayer, firstrewardItemList, 'QueenRelicsMail', event=["QueenRelics", False, {}])  | 
|                 overDict[FBCommon.Over_firstPassItem] = FBCommon.GetJsonItemList(firstrewardItemList)  | 
|           | 
|               | 
|         if not nextLineID:#ûÓÐÏÂÒ»²ãÔò¸ø½±Àø£¡£¡  | 
|             rewardRet = __GivePlayerQueenRelicsReward(curPlayer, dataMapID, rewardLine - 1, lineID, grade, maxGrade, rewardRateList)  | 
|             if rewardRet:  | 
|                 startRewardLineID, rewardItemList = rewardRet  | 
|                 overDict.update({FBCommon.Over_itemInfo:FBCommon.GetJsonItemList(rewardItemList),   | 
|                                  "startRewardLineID":startRewardLineID})  | 
|         if lineID+1 > curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_FBHistoryMaxLine % dataMapID):  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FBHistoryMaxLine % dataMapID, lineID+1)  | 
|         #³É¾Í  | 
|         if grade >= maxGrade:  | 
|             PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_QueenRelics, 1, [lineID+1])  | 
|           | 
|         EventShell.EventRespons_PassQueenRelecs(curPlayer, lineID, grade)  | 
|         #ÈÎÎñ  | 
|         EventShell.EventRespons_FBEvent(curPlayer, "queenrelics_pass")  | 
|       | 
|     # ¼Ç¼½áËãµ½µÄÏß·²ã£¬¼Ç¼ֵ+1  | 
|     updRewardLine = lineID + 1  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPKey_RewardLine, updRewardLine)  | 
|       | 
|     if isPass and not nextLineID:  | 
|         isInFBOnDay = gameFB.GetPlayerGameFBDictByKey(playerID, FBPKey_IsInFBOnDay)  | 
|         if not isInFBOnDay:  | 
|             GameWorld.DebugLog("Ê״νáËã½±Àø£¬Ôö¼ÓÌôÕ½´ÎÊý£¡", playerID)  | 
|             needSyncFBData = False  | 
|             FBCommon.AddEnterFBCount(curPlayer, dataMapID)  | 
|         else:  | 
|             GameWorld.DebugLog("¸±±¾ÖйýÌ죬²»Ôö¼ÓÌôÕ½´ÎÊý£¡", playerID)  | 
|         PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_QueenRelicsEx, 1)  | 
|         PlayerWeekParty.AddWeekPartyActionCnt(curPlayer, ChConfig.Def_WPAct_QueenRelices, 1)  | 
|         PlayerActLogin.AddLoginAwardActionCnt(curPlayer, ChConfig.Def_LoginAct_QueenRelices, 1)  | 
|     # ²»¿ÉÔÙÌôÕ½ÏÂÒ»¹ØÁË  | 
|     if not nextLineID:  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, fbLineTime[Def_LeaveTime] * 1000, True)  | 
|     else:  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttFBAddTime, 0, fbLineTime[Def_LeaveTime] * 1000, True)  | 
|         GameWorld.DebugLog("    ¿É½øÈëÏÂÒ»¹Ø: updRewardLine=%s,nextLineID=%s" % (updRewardLine, nextLineID), playerID)  | 
|           | 
|     if needSyncFBData:  | 
|         FBCommon.Sync_FBPlayerFBInfoData(curPlayer, dataMapID) # Í¬²½ÐÅÏ¢  | 
|           | 
|     FBCommon.NotifyFBOver(curPlayer, dataMapID, lineID, isPass, overDict)  | 
|     return  | 
|   | 
| def __GivePlayerQueenRelicsReward(curPlayer, dataMapID, rewardLineID, curLineID, passGrade, maxGrade, rewardRateList):  | 
|     ## ¸øÍæ¼Ò¹ý¹Ø½±Àø  | 
|       | 
|     totalItemCountDict = {}  | 
|     # Ò»°ãÊDz»¿ÉÄÜ£¬ÕâÀï×ö¸öÀíÂÛÊýÖµ·À·¶  | 
|     if rewardLineID >= curLineID:  | 
|         GameWorld.ErrLog("Íæ¼ÒÖØ¸´½áËãæ´»Ê¹ý¹Ø½±Àø£¡rewardLineID=%s >= curLineID=%s" % (rewardLineID, curLineID), curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     startRewardLineID = rewardLineID + 1  | 
|   | 
|     # Í³¼Æ½±Àø£¬±¾¹Ø¿¨Ö®Ç°µÄ¶¼¸ø×î¸ß¼¶½±Àø, µ±Ç°²ãÒÔ±¾´ÎÆÀ¼¶Îª×¼  | 
|     for giveLineID in xrange(startRewardLineID, curLineID + 1):  | 
|           | 
|         rewardGrade = maxGrade if giveLineID < curLineID else passGrade  | 
|                       | 
|         lineReward = FBCommon.GetFBLineReward(dataMapID, giveLineID)  | 
|         rewardItemList = lineReward[1]  | 
|         rewardRateIndex = 0 if rewardGrade >= maxGrade else maxGrade - rewardGrade  | 
|         if rewardRateIndex < 0 or rewardRateIndex >= len(rewardRateList):  | 
|             GameWorld.ErrLog("    ÆÀ¼¶¶ÔÓ¦½±Àø±ÈÀýË÷ÒýÒì³£: giveLineID=%s,rewardGrade=%s,rewardRateList=%s,maxGrade=%s,rewardRateIndex=%s"   | 
|                              % (giveLineID, rewardGrade, rewardRateList, maxGrade, rewardRateIndex), curPlayer.GetPlayerID())  | 
|             continue  | 
|         rewardRate = rewardRateList[rewardRateIndex]  | 
|           | 
|         if rewardRate < 100:  | 
|             giveItemList = []  | 
|             for itemID, itemCount in rewardItemList:  | 
|                 rewardCount = max(1, int(round(itemCount * rewardRate / 100.0))) # È·±£ÖÁÉÙ1¸ö  | 
|                 giveItemList.append([itemID, rewardCount])  | 
|         else:  | 
|             giveItemList = rewardItemList  | 
|               | 
|         GameWorld.DebugLog("    ¸ø¹Ø¿¨½±Àø: giveLineID=%s,rewardGrade=%s,rewardRateList=%s,rewardRate=%s,giveItemList=%s"   | 
|                            % (giveLineID, rewardGrade, rewardRateList, rewardRate, giveItemList), curPlayer.GetPlayerID())  | 
|           | 
|   | 
|         for itemID, itemCount in giveItemList:  | 
|             totalItemCountDict[itemID] = totalItemCountDict.get(itemID, 0) + itemCount  | 
|           | 
|       | 
|     # ¸ø½±Àø  | 
|     rewardItemList = []  | 
|     for itemID, itemCount in totalItemCountDict.items():  | 
|         rewardItemList.append([itemID, itemCount, 0])  | 
|       | 
|     needSpace = len(rewardItemList)  | 
|     emptySpace = ItemCommon.GetItemPackSpace(curPlayer, IPY_GameWorld.rptItem, needSpace)  | 
|     if emptySpace < needSpace:  | 
|         PlayerControl.SendMailByKey("QueenRelicsMail", [curPlayer.GetPlayerID()], rewardItemList)  | 
|     else:  | 
|         for itemID, itemCount, isBind in rewardItemList:  | 
|             ItemControler.GivePlayerItem(curPlayer, itemID, itemCount, 0, [IPY_GameWorld.rptItem], event=["QueenRelics", False, {}])  | 
|               | 
|     GameWorld.DebugLog("    ×ܽ±Àø£ºrewardItemList=%s" % (rewardItemList), curPlayer.GetPlayerID())  | 
|     return startRewardLineID, rewardItemList  | 
|   | 
|   | 
| ## ¸±±¾ÐÐΪ  | 
| #  @param curPlayer Íæ¼Ò  | 
| #  @param actionType ÐÐΪÀàÐÍ  | 
| #  @param actionInfo ÐÐΪÐÅÏ¢  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBAction(curPlayer, actionType, actionInfo, tick):  | 
|     if actionType != FBCommon.Def_FbActionChangeLine:  | 
|         return  | 
|     toLineID = actionInfo  | 
|     curLineID = FBCommon.GetFBPropertyMark()  | 
|     GameWorld.DebugLog("DoFBAction actionType=%s, toLineID=%s, curLineID=%s" % (actionType, actionInfo, curLineID), curPlayer.GetPlayerID())  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     if curLineID == toLineID:  | 
|         toPosX, toPosY = __GetQueenRelicsLinePos(mapID, toLineID)  | 
|         PlayerControl.PlayerResetWorldPosFBLineID(curPlayer, mapID, toPosX, toPosY, toLineID)  | 
|         GameWorld.DebugLog("ÒѾÊǵ±Ç°¹¦ÄÜÏß·, Çл»µ½¸Ã¹¦ÄÜÏßÂ·×ø±ê: toPosX=%s,toPosY=%s,toLineID=%s"   | 
|                            % (toPosX, toPosY, toLineID), curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     fbStep = GameWorld.GetGameFB().GetFBStep()  | 
|     if fbStep != FB_Step_Over:  | 
|         GameWorld.DebugLog("·Ç½áÊø×´Ì¬!fbStep=%s" % fbStep)  | 
|         return  | 
|     if toLineID != curLineID + 1:  | 
|         GameWorld.DebugLog("Ö»ÄܽøÈëÏÂÒ»¹Ø, curLineID=%s,toLineID=%s" % (curLineID, toLineID))  | 
|         return  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     grade = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_Grade)  | 
|     maxGrade = len(FBCommon.GetFBLineGrade(mapID, curLineID))  | 
|     if grade < maxGrade:  | 
|         GameWorld.DebugLog("·Ç×î´óÆÀ¼¶¹ý¹Ø£¬ÎÞ·¨ÌôÕ½ÏÂÒ»²ã£¡curLineID=%s,grade=%s,maxGrade=%s"   | 
|                            % (curLineID, grade, maxGrade), curPlayer.GetPlayerID())  | 
|         return  | 
|     toLineIpyData = FBCommon.GetFBLineIpyData(mapID, toLineID, False)  | 
|     if not toLineIpyData:  | 
|         GameWorld.ErrLog("ûÓÐÄ¿±ê¹¦ÄÜÏß·£¡toLineID=%s" % toLineID)  | 
|         return  | 
|     #ÅжÏÕ½Á¦ÊÇ·ñÂú×ã±¾²ãÒªÇó  | 
|     helpIpyData = IpyGameDataPY.GetIpyGameData("FBHelpBattle", mapID, toLineID)  | 
|     if helpIpyData:  | 
|         if curPlayer.GetFightPower() < helpIpyData.GetFightPowerMin():  | 
|             GameWorld.DebugLog("Õ½Á¦²»×ã%s£¬ÎÞ·¨ÌôÕ½ÏÂÒ»²ã£¡toLineID=%s" % (helpIpyData.GetFightPowerMin(), toLineID), curPlayer.GetPlayerID())  | 
|             return  | 
|       | 
|     if curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:  | 
|         GameWorld.Log("½øÈëÏÂÒ»²ãÊ±Íæ¼ÒÊÇËÀÍö״̬£¬Ïȸ´»î!", curPlayer.GetPlayerID())  | 
|         ChPlayer.PlayerRebornByType(curPlayer, ChConfig.rebornType_System, tick)  | 
|           | 
|     toPosX, toPosY = __GetQueenRelicsLinePos(mapID, toLineID, toLineIpyData)  | 
|     PlayerControl.PlayerResetWorldPosFBLineID(curPlayer, mapID, toPosX, toPosY, toLineID)  | 
|       | 
|     # É¾³ýµ¥²ãÓÐЧµÄbuff, ÊÈѪµ¤  | 
|     if BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_QueenRelicsItemBuff, tick):  | 
|         playerControl = PlayerControl.PlayerControl(curPlayer)  | 
|         playerControl.RefreshPlayerAttrByBuff()  | 
|     return  | 
|   | 
| def __GetQueenRelicsLinePos(mapID, lineID, toLineIpyData=None):  | 
|     posInfo = FBCommon.GetFBLineEnterPosInfo(mapID, lineID, toLineIpyData)  | 
|     enterX, enterY, dist = posInfo  | 
|     posPoint = GameMap.GetEmptyPlaceInArea(enterX, enterY, dist)  | 
|     return posPoint.GetPosX(), posPoint.GetPosY()  | 
|   | 
|   |