| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_BZZD  | 
| #  | 
| # @todo:°ÙÕ½Ö®µØ(¾Ñ鸱±¾)  | 
| # @author hxp  | 
| # @date 2016-3-20  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: °ÙÕ½Ö®µØ(¾Ñ鸱±¾)  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2017-06-23 16:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import FBCommon  | 
| import GameWorld  | 
| import IPY_GameWorld  | 
| import NPCCustomRefresh  | 
| import GameWorldProcess  | 
| import PlayerControl  | 
| import ShareDefine  | 
| import EventReport  | 
| import ChConfig  | 
| import IpyGameDataPY  | 
| import AttackCommon  | 
| import PyGameData  | 
| import NPCCommon  | 
| import GameObj  | 
| import PlayerSuccess  | 
| import PlayerBossReborn  | 
| import PlayerFairyCeremony  | 
| import ItemControler  | 
| import GameFuncComm  | 
| import SkillShell  | 
| import BuffSkill  | 
|   | 
| import random  | 
| import math  | 
|   | 
| #---¸±±¾ÅäÖöÔÓ¦keyÖµ---  | 
| (  | 
| Def_PrepareTime, # ¸±±¾×¼±¸Ê±¼ä(Ãë)  | 
| Def_FightTime, # ½øÐÐʱ¼ä(Ãë)  | 
| Def_LeaveTime, # Í˳öʱ¼ä(Ãë)  | 
| ) = range(3)  | 
|   | 
| #µ±Ç°¸±±¾µØÍ¼µÄ״̬  | 
| (  | 
| FB_Step_Open, # ¸±±¾¿ªÆô  | 
| FB_Step_Prepare, # ¸±±¾µÈ´ý  | 
| FB_Step_Fighting, # ¸±±¾½øÐÐÖÐ  | 
| FB_Step_Over, # ¸±±¾½áÊø  | 
| FB_Step_Close, # ¸±±¾¹Ø±Õ  | 
| ) = range(5)  | 
|   | 
| BZZD_LastCheckExpTick = 'BZZD_LastCheckExpTick'   # Éϴμì²é±£µ×½±Àøtick  | 
| BZZD_LastCheckTick = 'BZZD_LastCheckTick'   # Éϴμì²énpcË¢ÐÂʱ¼ä  | 
| #BZZD_KillCnt = 'BZZD_KillCnt'   # »÷ɱÊý  | 
| BZZD_WaveIndex = 'BZZD_WaveIndex'   # ²¨Êý  | 
|   | 
| BZZD_ReExp = 'BZZD_ReExp_%s' # ²Î¿¼¾Ñé, ²ÎÊý (npcLV)  | 
| BZZD_NPCMaxHP = 'BZZD_NPCMaxHP_%s_%s' # NPC×î´óÉúÃüÖµ, ²ÎÊý(npcID, enterLV)  | 
|   | 
| FBPlayerDict_EnterLV = 'FBPlayerDict_EnterLV'   # ½øÈ븱±¾Ê±µÄµÈ¼¶  | 
| FBPlayerDict_TotalExp = 'FBPlayerDict_TotalExp'   # »ñµÃµÄ×ܾÑé  | 
| FBPlayerDict_TotalExpPoint = 'FBPlayerDict_TotalExpPoint'   # »ñµÃµÄ×ܾÑéµã  | 
| FBPlayerDict_EncourageLV = 'FBPlayerDict_EncourageLV'   # ¹ÄÎèµÈ¼¶  | 
|   | 
| FirstEnterExpTimeMax = 99999 # µ±µ¥´Î²¹Ê±Âúʱ¼Ç¼µÄÒ»¸öÌØÊâÊýÖµ£¬·ÀÖ¹²ß»®µ÷Õûµ¥´ÎÕ½¶·Ê±³¤Ê±£¬ÀϺſÉÄÜ»á¶àÓಹ¾Ñé  | 
|   | 
| def GetBZZDNPCID(passSecond):  | 
|     ##µ±Ç°Ó¦¸ÃˢеÄNPCID  | 
|     curNpcid = 0  | 
|     curIndex = 0  | 
|     fairylandNPCList = IpyGameDataPY.GetFuncEvalCfg('FairylandNPC', 1)  | 
|     for i, info in enumerate(fairylandNPCList, 1):  | 
|         timeRange, npcid = info  | 
|         if timeRange[0] <= passSecond <= timeRange[1]:  | 
|             curNpcid = npcid  | 
|             curIndex = i  | 
|             break  | 
|     return curNpcid, curIndex  | 
|   | 
|   | 
| ## OnDay´¦Àí  | 
| #  @param curPlayer  | 
| #  @return None  | 
| def BZZDOnDay(curPlayer):  | 
| #    joinLineID = __GetPlayerFBLineID(curPlayer)  | 
| #    if joinLineID == None:  | 
| #        GameWorld.DebugLog("BZZDOnDay() level(%s) no enough" % curPlayer.GetLV())  | 
| #        return  | 
| #      | 
| #    hadEnterCnt = FBCommon.GetEnterFBCount(curPlayer, ChConfig.Def_FBMapID_BZZD)  | 
| #    maxEnterCnt = GetMaxEnterCnt(curPlayer)  | 
|     return  | 
|   | 
| def OnFBPlayerOnLogin(curPlayer):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerExpTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)  | 
|     if not playerExpTime:  | 
|         #GameWorld.DebugLog("»¹Ã»½øÈë¹ýÏɽçÃØ¾³£¬²»´¦Àí¾Ñ鲹ʱ£¡", playerID)  | 
|         return  | 
|       | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     mapID = FBCommon.GetRecordMapID(mapID)  | 
|     if mapID == ChConfig.Def_FBMapID_BZZD:  | 
|         GameWorld.DebugLog("ÏɽçÃØ¾³¸±±¾ÖУ¬²»´¦Àí¾Ñ鲹ʱ£¡", playerID)  | 
|         return  | 
|     fbCfg = FBCommon.GetFBLineStepTime(ChConfig.Def_FBMapID_BZZD)  | 
|     fightTime = fbCfg[Def_FightTime]  | 
|     giveTime = max(0, fightTime - playerExpTime)  | 
|     if not giveTime:  | 
|         #GameWorld.DebugLog("¾Ñ鲹ʱʱ¼äÒѳ¬¹ýµ¥´ÎÌôսʱ³¤£¬²»´¦Àí¾Ñ鲹ʱ£¡playerExpTime=%s" % playerExpTime, playerID)  | 
|         return  | 
|     expPerSecond = IpyGameDataPY.GetFuncCfg("XjmjFirstEnter", 2)  | 
|     giveExp = expPerSecond * giveTime  | 
|     PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, FirstEnterExpTimeMax)  | 
|     if giveExp:  | 
|         giveExp = PlayerControl.PlayerControl(curPlayer).AddExp(giveExp, ShareDefine.Def_ViewExpType_Sys)  | 
|         GameWorld.DebugLog("Íæ¼ÒÊ×´ÎÏɽçÃØ¾³¾Ñ鲹ʱ£º%sÃë,giveExp=%s" % (giveTime, giveExp), playerID)  | 
|           | 
|     return  | 
|   | 
| ## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineID Ïß·id  | 
| #  @param tick Ê±¼ä´Á  | 
| #  @return ²¼¶ûÖµ  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     return __CheckCanEnterBZZD(curPlayer, mapID, lineID)  | 
|   | 
|   | 
| ## ¼ì²é¿É·ñ½øÈë°ÙÕ½Ö®µØ  | 
| def __CheckCanEnterBZZD(curPlayer, mapID, lineID, enterCnt=1):  | 
|     return True  | 
|   | 
|   | 
| ## ½øÈë´«Ë굋  | 
| #  @param curPlayer  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineId ·ÖÏßID  | 
| #  @param tick  | 
| #  @return ×ø±êÁбí(X,Y)  | 
| def OnGetFBEnterPos(curPlayer, mapID, lineId, ipyEnterPosInfo, tick):  | 
|     if len(ipyEnterPosInfo) == 3:  | 
|         return ipyEnterPosInfo  | 
|     return ipyEnterPosInfo + [3]  | 
|   | 
|   | 
| ##²éѯÊÇ·ñ¿ÉÒÔ½øÈëµØÍ¼  | 
| # @param ask:ÇëÇó½á¹¹Ìå(IPY_BMChangeMapAsk)  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return IPY_GameWorld.cme Ã¶¾Ù  | 
| def OnChangeMapAsk(ask, tick):  | 
|     return IPY_GameWorld.cmeAccept  | 
|   | 
|   | 
| ## ½ø¸±±¾  | 
| #  @param curPlayer  | 
| #  @param tick  | 
| #  @return None  | 
| def DoEnterFB(curPlayer, tick):  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     playerLV = curPlayer.GetLV()  | 
|     curCopyMapID = GameWorld.GetGameWorld().GetCopyMapID()  | 
|     teamID = curPlayer.GetTeamID()  | 
|     GameWorld.Log("DoEnterFB...playerCopyMapID=%s,curCopyMapID=%s,playerLV=%s,teamID=%s"   | 
|                   % (curPlayer.GetCopyMapID(), curCopyMapID, playerLV, teamID), playerID)  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     hadDelTicket = FBCommon.GetHadDelTicket(curPlayer)  | 
|     if not hadDelTicket:  | 
|         mapID = GameWorld.GetGameWorld().GetMapID()  | 
|         delResult = FBCommon.DelFBEnterTicket(curPlayer, mapID)  | 
|         isOK = delResult[0]  | 
|         #hasBind = delResult[1]  | 
|         if not isOK:  | 
|             PlayerControl.PlayerLeaveFB(curPlayer)  | 
|             return  | 
|         FBCommon.SetHadDelTicket(curPlayer)  | 
|         FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_BZZD)  | 
|         PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_XJMJ, 1)  | 
|         PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_XJMJ, 1)  | 
|         FBCommon.UpdateFBEnterTick(curPlayer)  | 
|         gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_EnterLV, playerLV)  | 
|         PyGameData.g_bzzdPlayerKillNPCCntDict.pop(playerID, 0)  | 
|           | 
|         logType = FBCommon.GetFBJoinType(curPlayer, False)  | 
|         EventReport.WriteEvent_FB(curPlayer, ChConfig.Def_FBMapID_BZZD, 0, ChConfig.CME_Log_Start, logType)  | 
|     fbPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)  | 
|     isTeamEnter = (teamID and fbPlayerCnt > 1)  | 
|     if not isTeamEnter:  | 
|         CheckHurtBuff(curPlayer, tick)  | 
|     showState = GameWorld.GetDictValueByBit(curPlayer, ChConfig.Def_Player_Dict_GuideState, ChConfig.GuideState_BZZDShow)  | 
|     if not showState:  | 
|         if not isTeamEnter:  | 
|             FBCommon.SendFBEncourageInfo(curPlayer, 0)  | 
|             GameWorld.Log("Ê״ε¥È˽øÈë¸Ã¸±±¾£¬ÐèÒªµÈǰ¶Ë²¥Í긱±¾³¡¾°Òýµ¼Ðã²ÅÕý³£½øÈë×¼±¸½×¶Î!", playerID)  | 
|             return  | 
|         else:  | 
|             GameWorld.Log("¶ÓÎ鷽ʽ½øÈë¸Ã¸±±¾£¬²»²¥·Å¸±±¾³¡¾°Òýµ¼Ðã!", playerID)  | 
|               | 
|     fbStep = gameFB.GetFBStep()  | 
|     if fbStep < FB_Step_Prepare:  | 
|         FBCommon.SetFBStep(FB_Step_Prepare, tick)  | 
|           | 
|     if fbStep <= FB_Step_Prepare:  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         notify_tick = FBCommon.GetFBLineStepTime(mapID)[Def_PrepareTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttAddUpTime, 0, max(notify_tick, 0), True)  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)  | 
|           | 
|     elif fbStep == FB_Step_Fighting:  | 
|         mapID = GameWorld.GetMap().GetMapID()  | 
|         notify_tick = FBCommon.GetFBLineStepTime(mapID)[Def_FightTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|         curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, max(notify_tick, 0), True)  | 
|       | 
|     # ÉϹÄÎèbuff  | 
|     encourageLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EncourageLV)  | 
|     if encourageLV > 0:  | 
|         FBCommon.AddFbEncourageBuff(curPlayer, FBPlayerDict_EncourageLV, tick)  | 
|     else:  | 
|         FBCommon.SendFBEncourageInfo(curPlayer, encourageLV)  | 
|     DoFBHelp(curPlayer, tick)  | 
|       | 
|     isFirstEnter = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)  | 
|     # Ã»ÓÐÊ״νøÈë¾Ñéʱ¼ä¼Ç¼£¬¿ÉÊÓΪÊ״νøÈë  | 
|     if not isFirstEnter:  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, 1)  | 
|         __GiveFirstEnterPrize(curPlayer)  | 
|           | 
|     return  | 
|   | 
| def __GiveFirstEnterPrize(curPlayer):  | 
|     XjmjFirstEnterPrize = IpyGameDataPY.GetFuncEvalCfg("XjmjFirstEnter", 1)  | 
|     if not XjmjFirstEnterPrize:  | 
|         return  | 
|     silverMoney, goldPaper, itemID = XjmjFirstEnterPrize  | 
|     if silverMoney:  | 
|         PlayerControl.GiveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Silver_Money, silverMoney)  | 
|     if goldPaper:  | 
|         PlayerControl.GiveMoney(curPlayer, IPY_GameWorld.TYPE_Price_Gold_Paper, goldPaper)  | 
|     if itemID:  | 
|         ItemControler.GivePlayerItem(curPlayer, itemID, 1, 1, [IPY_GameWorld.rptItem])  | 
|     GameWorld.DebugLog("Ê״νøÈë¸ø½±Àø£ºsilverMoney=%s,goldPaper=%s,itemID=%s"   | 
|                        % (silverMoney, goldPaper, itemID), curPlayer.GetPlayerID())  | 
|     return  | 
|   | 
| def CheckHurtBuff(curPlayer, tick, isAdd=True):  | 
|     #ÈËÎïµÈ¼¶µÍÓÚÊÀ½çµÈ¼¶X¼¶£¬µ¥ÈËÌôÕ½ÏɽçÃܾ³»ñµÃÉ˺¦BUFF¼Ó³É  | 
|     if not GameFuncComm.GetFuncCanUse(curPlayer, ShareDefine.GameFuncID_WorldLV):  | 
|         return  | 
|     playerID = curPlayer.GetID()  | 
|     enterLV = GameWorld.GetGameFB().GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnterLV)  | 
|     if enterLV < GameFuncComm.GetFuncLimitLV(ShareDefine.GameFuncID_WorldLV):  | 
|         return  | 
|     curLV = curPlayer.GetLV()  | 
|     worldlv = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_WorldAverageLv)  | 
|     buffID = IpyGameDataPY.GetFuncCfg('XjmjAddHarm', 2)  | 
|     lvRange = IpyGameDataPY.GetFuncCfg('XjmjAddHarm')  | 
|     if isAdd and worldlv - curLV >=lvRange:  | 
|         curSkill = GameWorld.GetGameData().GetSkillBySkillID(buffID)  | 
|         SkillShell.__DoLogic_AddBuff(curPlayer, curPlayer, curSkill, False, tick, 0, 0)  | 
|     if not isAdd and worldlv - curLV < lvRange:  | 
|         BuffSkill.DelBuffBySkillID(curPlayer, buffID, tick)  | 
|     return  | 
|   | 
| ## ¿Í»§¶Ë·¢ËÍ¿ªÊ¼¸±±¾  | 
| def OnClientStartFB(curPlayer, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     fbStep = gameFB.GetFBStep()  | 
|     if fbStep >= FB_Step_Prepare:  | 
|         GameWorld.ErrLog("ǰ¶ËÇëÇóÕýʽ¿ªÊ¼¸±±¾, µ«¸±±¾ÒѾ¿ªÊ¼ÁË£¬²»¿ÉÖØ¸´¿ªÊ¼!", curPlayer.GetPlayerID())  | 
|         return  | 
|       | 
|     GameWorld.DebugLog("ǰ¶Ë³¡¾°ÐãÒѲ¥·ÅÍê±Ï£¬ÇëÇóÕýʽ¿ªÊ¼¸±±¾!", curPlayer.GetPlayerID())  | 
|     FBCommon.SetFBStep(FB_Step_Prepare, tick)  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     notify_tick = FBCommon.GetFBLineStepTime(mapID)[Def_PrepareTime] * 1000 - (tick - GameWorld.GetGameFB().GetFBStepTick())  | 
|     curPlayer.Sync_TimeTick(IPY_GameWorld.tttAddUpTime, 0, max(notify_tick, 0), True)  | 
|     curPlayer.Sync_TimeTick(IPY_GameWorld.tttWaitStart, 0, max(notify_tick, 0), True)  | 
|     DoFBHelp(curPlayer, tick)  | 
|       | 
|     isFirstEnter = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)  | 
|     # Ã»ÓÐÊ״νøÈë¾Ñéʱ¼ä¼Ç¼£¬¿ÉÊÓΪÊ״νøÈë  | 
|     if not isFirstEnter:  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, 1)  | 
|         __GiveFirstEnterPrize(curPlayer)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÍ˳ö¸±±¾  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| def DoExitFB(curPlayer, tick):  | 
|     # Çå³ý¹ÄÎèbuff  | 
|     FBCommon.ClearEncourageBuff(curPlayer, tick)  | 
|     buffID = IpyGameDataPY.GetFuncCfg('XjmjAddHarm', 2)  | 
|     BuffSkill.DelBuffBySkillID(curPlayer, buffID, tick)  | 
|     FBCommon.UpdFBLineNPCStrengthenLV(curPlayer.GetPlayerID(), True)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÖ÷¶¯À뿪¸±±¾.  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ·µ»ØÖµÎÞÒâÒå  | 
| def DoPlayerLeaveFB(curPlayer, tick):  | 
|     return  | 
|   | 
| def OnPlayerLVUp(curPlayer):  | 
|     CheckHurtBuff(curPlayer, GameWorld.GetGameWorld().GetTick(), False)  | 
|     FBCommon.UpdFBLineNPCStrengthenLV(curPlayer.GetPlayerID(), False)  | 
|     return  | 
|   | 
| ## »ñµÃ¸±±¾°ïÖúÐÅÏ¢  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò£¨±»Í¨Öª¶ÔÏó£©  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBHelp(curPlayer, tick):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     playerID = curPlayer.GetID()  | 
|       | 
|     # »ñµÃ¸±±¾ÐÅÏ¢  | 
|   | 
|      | 
|     #killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)  | 
|     killNPCCnt = int(PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0))  | 
|     passCnt = gameFB.GetGameFBDictByKey(BZZD_WaveIndex)  | 
|     passAllCnt = len(IpyGameDataPY.GetFuncEvalCfg('FairylandNPC'))  | 
|     exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)  | 
|     expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)  | 
|        | 
|     #¸±±¾°ïÖú  | 
|     helpDict = {FBCommon.Help_npcTotal:killNPCCnt, FBCommon.Help_exp:exp, FBCommon.Help_expPoint:expPoint, FBCommon.Help_wheel:passCnt, 'passAllCnt':passAllCnt}  | 
|     GameWorld.DebugLog("DoFBHelp %s" % str(helpDict))  | 
|     FBCommon.Notify_FBHelp(curPlayer, helpDict)  | 
|     return  | 
|   | 
|   | 
| ##---¸±±¾×ÜÂß¼¼ÆÊ±Æ÷---  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     fbStep = GameWorld.GetGameFB().GetFBStep()  | 
|       | 
|     # ¸±±¾×¼±¸  | 
|     if fbStep == FB_Step_Prepare:  | 
|         __DoLogic_FB_Prepare(tick)      | 
|     # ¸±±¾½øÐÐÖÐ  | 
|     elif fbStep == FB_Step_Fighting:  | 
|         __DoLogic_FB_Fighting(tick)  | 
|     # ¸±±¾½áÊø  | 
|     elif fbStep == FB_Step_Over:  | 
|         __DoLogic_FB_Over(tick)  | 
|       | 
|     return  | 
|   | 
| ## ¸±±¾×¼±¸Âß¼  | 
| #  @param tick:ʱ¼ä´Á  | 
| #  @return ÎÞÒâÒå  | 
| def __DoLogic_FB_Prepare(tick):  | 
|     #gameFB = GameWorld.GetGameFB()  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     fbCfg = FBCommon.GetFBLineStepTime(mapID)  | 
|     # ¼ä¸ôδµ½  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbCfg[Def_PrepareTime] * 1000:  | 
|         return  | 
|       | 
|     # ÉèÖÿªÊ¼Ë¢¹Ö  | 
|     CheckNPCRefresh(tick)  | 
|   | 
|       | 
|     # ¸±±¾¿ªÊ¼  | 
|   | 
|     FBCommon.SetFBStep(FB_Step_Fighting, tick)  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttTowerTake, fbCfg[Def_FightTime] * 1000)  | 
|       | 
|     return  | 
|   | 
| def CheckNPCRefresh(tick):  | 
|     #npcˢмì²é  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     lastCheckTick = gameFB.GetGameFBDictByKey(BZZD_LastCheckTick)  | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     heroCnt = playerManager.GetPlayerCount()  | 
|     checkCD = eval(IpyGameDataPY.GetFuncCompileCfg('FairylandNPC', 2))  | 
|       | 
|     if lastCheckTick and tick - lastCheckTick < checkCD:  | 
|         return  | 
|     gameFB.SetGameFBDict(BZZD_LastCheckTick, tick)  | 
|     passSecond = (tick - GameWorld.GetGameFB().GetFBStepTick())/1000  | 
|     npcID, waveIndex = GetBZZDNPCID(passSecond)  | 
|     if not npcID:  | 
|         return  | 
|     if gameFB.GetGameFBDictByKey(BZZD_WaveIndex) != waveIndex:  | 
|         gameFB.SetGameFBDict(BZZD_WaveIndex, waveIndex)  | 
|         for i in range(playerManager.GetPlayerCount()):  | 
|             curPlayer = playerManager.GetPlayerByIndex(i)  | 
|             DoFBHelp(curPlayer, tick)  | 
|               | 
|     rMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint')  | 
|     maxCnt = IpyGameDataPY.GetFuncCfg('FairylandPoint',2)  | 
|     firstRMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint',3)  | 
|     allRmark = rMarkList+firstRMarkList  | 
|     npcCntDict = {mark:0 for mark in allRmark} #±êʶµã¶ÔÓ¦ÊýÁ¿  | 
|     npcCnt = 0  | 
|     gameNPC = GameWorld.GetNPCManager()  | 
|     for i in range(0, gameNPC.GetCustomNPCRefreshCount()):  | 
|         npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)  | 
|         npcCnt += npcRefresh.GetCount()  | 
|         rmark = npcRefresh.GetRefreshMark()  | 
|         npcCntDict[rmark] = npcCntDict.get(rmark, 0)+npcRefresh.GetCount()  | 
|       | 
|     if not lastCheckTick:  | 
|         needAddCnt = IpyGameDataPY.GetFuncCfg('FairylandNPC', 3)  | 
|     else:  | 
|         needAddCnt = eval(IpyGameDataPY.GetFuncCompileCfg('FairylandNPCCnt'))  | 
|   | 
|     if not needAddCnt:  | 
|         return  | 
|       | 
|     markCntList = sorted(npcCntDict.iteritems(), key=lambda asd:asd[1])  | 
|     #GameWorld.Log('11111111111111111markCntList=%s'%markCntList)  | 
|     hasRefreshCnt = 0  | 
|     for rMark, curCnt in markCntList:  | 
|         if hasRefreshCnt >=needAddCnt:  | 
|             break  | 
|         cnt = min(maxCnt, needAddCnt-hasRefreshCnt)  | 
|         hasRefreshCnt +=cnt  | 
|         curMaxCnt = curCnt+cnt  | 
|         NPCCustomRefresh.SetNPCRefresh(rMark, [(npcID, cnt)], curMaxCnt, cnt)  | 
|     NPCCustomRefresh.ProcessAllNPCRefresh(tick) # Á¢¼´³ö·¢Ò»´Î±êʶµãˢР | 
|     return  | 
|   | 
| def CheckFirstEnterExp(tick, isOver=False):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     if not isOver:  | 
|         lastCheckExpTick = gameFB.GetGameFBDictByKey(BZZD_LastCheckExpTick)  | 
|         if not lastCheckExpTick:  | 
|             gameFB.SetGameFBDict(BZZD_LastCheckExpTick, tick)  | 
|             return  | 
|         if tick - lastCheckExpTick < 5000:  | 
|             return  | 
|     gameFB.SetGameFBDict(BZZD_LastCheckExpTick, tick) # Õâ¸öÈ«¾ÖtickÖ»ÊÇ´¦Àí¶à¾ÃÖ´ÐÐÒ»´Î¶øÒÑ£¬²»²ÎÓëÆäËûÂß¼  | 
|       | 
|     fightTime = int(math.ceil((tick - GameWorld.GetGameFB().GetFBStepTick()) / 1000.0)) # ÒѾս¶·Ê±³¤£¬Ãë  | 
|     expPerSecond = IpyGameDataPY.GetFuncCfg("XjmjFirstEnter", 2)  | 
|     minTotalExp = expPerSecond * fightTime # ÀíÂÛ±£µ××îÉÙ¾Ñé  | 
|       | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     playerCount = playerManager.GetPlayerCount()  | 
|     for i in xrange(playerCount):  | 
|         curPlayer = playerManager.GetPlayerByIndex(i)  | 
|         if not curPlayer:  | 
|             continue  | 
|         playerID = curPlayer.GetPlayerID()  | 
|         playerExpTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_FirstEnterExpTime)  | 
|         if playerExpTime >= fightTime:  | 
|             #GameWorld.DebugLog("ÒѾ´¦ÀíÍê±£µ×¾Ñéʱ¼ä£¬²»ÔÙ´¦Àí!", playerID)  | 
|             continue  | 
|           | 
|         updExpTime = FirstEnterExpTimeMax if isOver else fightTime  | 
|         PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_FirstEnterExpTime, updExpTime)  | 
|           | 
|         exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)  | 
|         expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)  | 
|         playerTotalExp = expPoint * ChConfig.Def_PerPointValue + exp  | 
|         giveExp = max(0, minTotalExp - playerTotalExp)  | 
|         if giveExp > 0:  | 
|             giveExp = PlayerControl.PlayerControl(curPlayer).AddExp(giveExp, ShareDefine.Def_ViewExpType_Sys)  | 
|             __RecordAddExp(curPlayer, giveExp, True)  | 
|               | 
|         GameWorld.DebugLog("±£µ×¾Ñé: updExpTime=%s,minTotalExp=%s,playerTotalExp=%s,giveExp=%s"   | 
|                            % (updExpTime, minTotalExp, playerTotalExp, giveExp), playerID)  | 
|     return  | 
|   | 
| ## ¸±±¾½øÐÐÖÐ  | 
| #  @param tick:ʱ¼ä´Á  | 
| #  @return ÎÞÒâÒå  | 
| def __DoLogic_FB_Fighting(tick):  | 
|     #gameFB = GameWorld.GetGameFB()  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     fbCfg = FBCommon.GetFBLineStepTime(mapID)  | 
|     # ¼ä¸ôδµ½  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbCfg[Def_FightTime] * 1000:  | 
|         CheckNPCRefresh(tick)  | 
|         CheckFirstEnterExp(tick)  | 
|         return  | 
|       | 
|     __DoBZZDOver()  | 
|     return  | 
|   | 
|           | 
| ##¸±±¾¹Ø±ÕÖÐ  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾¹Ø±ÕÖÐ  | 
| def __DoLogic_FB_Over(tick):  | 
|   | 
|     #gameFB = GameWorld.GetGameFB()  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     fbCfg = FBCommon.GetFBLineStepTime(mapID)  | 
|     # ¼ä¸ôδµ½  | 
|     if tick - GameWorld.GetGameFB().GetFBStepTick() < fbCfg[Def_LeaveTime] * 1000:  | 
|         return  | 
|       | 
|     #¸±±¾¹Ø±Õ  | 
|     GameWorldProcess.CloseFB(tick)  | 
|     FBCommon.SetFBStep(FB_Step_Close, 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 OnGetNPCExp(curPlayer, curNPC):  | 
|     if not curPlayer:  | 
|         return 0  | 
|     #²ÎÊý  | 
|     #baseExp     »ù´¡Öµ  | 
|     #expMulti    ÏɽçÃØ¾³¾ÑéЧÂÊ  | 
|     #hurtValue   É˺¦Öµ  | 
|     #npcMaxHP    ¹ÖÎïѪÁ¿, Íæ¼Ò½øÈ븱±¾Ê±µÄµÈ¼¶¶ÔÓ¦¹ÖÎï³É³¤ÑªÁ¿  | 
|     #reExp       µÈ¼¶¾ÑéЧÂÊ, È¡¸±±¾NPCµÈ¼¶  | 
|     #playerCnt   ¶ÓÔ±ÈËÊý  | 
|     playerID = curPlayer.GetPlayerID()  | 
|     npcLV = max(curNPC.GetCurLV(), curNPC.GetLV())  | 
|     npcID = curNPC.GetNPCID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     reExp = gameFB.GetGameFBDictByKey(BZZD_ReExp % npcLV)  | 
|     if not reExp:  | 
|         lvIpyData = PlayerControl.GetPlayerLVIpyData(npcLV)  | 
|         reExp = 0 if not lvIpyData else lvIpyData.GetReExp()  | 
|         gameFB.SetGameFBDict(BZZD_ReExp % npcLV, reExp)  | 
|         GameWorld.DebugLog("³õʼ»¯²ÎÊý: npcID=%s,npcLV=%s,reExp=%s" % (npcID, npcLV, reExp), playerID)  | 
|           | 
|     playerCnt = max(1, gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt))  | 
|     enterLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnterLV)  | 
|     npcMaxHP = gameFB.GetGameFBDictByKey(BZZD_NPCMaxHP % (npcID, enterLV))  | 
|     if not npcMaxHP:  | 
|         enterLVAttrDict = NPCCommon.GetNPCStrengthenAttrDict(npcID, enterLV)  | 
|         npcMaxHP = enterLVAttrDict.get("MaxHP", 0)  | 
|         gameFB.SetGameFBDict(BZZD_NPCMaxHP % (npcID, enterLV), npcMaxHP)  | 
|         GameWorld.DebugLog("³õʼ»¯²ÎÊý: npcID=%s,enterLV=%s,npcMaxHP=%s" % (npcID, enterLV, npcMaxHP), playerID)  | 
|         if not npcMaxHP:  | 
|             GameWorld.ErrLog("ÎÞ·¨»ñµÃNPC×î´óÉúÃüÖµ,npcID=%s,enterLV=%s" % (npcID, enterLV), playerID)  | 
|             return 0  | 
|           | 
|     baseExp = curNPC.GetExp()  | 
|     expMulti = IpyGameDataPY.GetFuncCfg("XjmjMonsterExp", 2)  | 
|     curNPCMaxHP = GameObj.GetMaxHP(curNPC)  | 
|     teamPlayerHurtValue = AttackCommon.GetTeamPlayerHurtValue(curPlayer, curNPC)  | 
|     hurtValue = npcMaxHP if not curPlayer.GetTeamID() else teamPlayerHurtValue  | 
|     #GameWorld.DebugLog("»÷ɱNPC: npcID=%s,baseExp=%s,expMulti=%s,hurtValue=%s,npcMaxHP=%s,curNPCMaxHP=%s,playerCnt=%s"   | 
|     #                   % (npcID, baseExp, expMulti, hurtValue, npcMaxHP, curNPCMaxHP, playerCnt), playerID)  | 
|       | 
|     addExp = eval(IpyGameDataPY.GetFuncCompileCfg("XjmjMonsterExp"))  | 
|     #GameWorld.DebugLog("    addExp=%s" % (addExp), playerID)  | 
|     if addExp <= 0:  | 
|         GameWorld.ErrLog("¾Ñ鼯ËãÒì³£:  npcID=%s,npcLV=%s,reExp=%s,baseExp=%s,expMulti=%s,hurtValue=%s,npcMaxHP=%s,curNPCMaxHP=%s,playerCnt=%s"   | 
|                          % (npcID, npcLV, reExp, baseExp, expMulti, hurtValue, npcMaxHP, curNPCMaxHP, playerCnt), playerID)  | 
|           | 
|     #Àۼƻ÷ɱÊý  | 
|     curHurtValue = curNPCMaxHP if not curPlayer.GetTeamID() else teamPlayerHurtValue  | 
|     addKillCnt = curHurtValue / float(curNPCMaxHP)  | 
|     PyGameData.g_bzzdPlayerKillNPCCntDict[playerID] = PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0) + addKillCnt  | 
|     #GameWorld.DebugLog("    Ôö¼ÓÍæ¼Òɱ¹ÖÊý: %s / %s = %s, %s" % (curHurtValue, curNPCMaxHP, addKillCnt, PyGameData.g_bzzdPlayerKillNPCCntDict), playerID)  | 
|       | 
|     DoFBHelp(curPlayer, GameWorld.GetGameWorld().GetTick())  | 
|     return addExp  | 
|   | 
| ## »ñµÃ¾Ñé  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param addExp »ñµÃµÄ¾Ñé  | 
| #  @param expViewType ¾ÑéÀàÐÍ  | 
| #  @return True or False  | 
| def OnGetExp(curPlayer, addExp, expViewType):  | 
|       | 
|     if expViewType != ShareDefine.Def_ViewExpType_KillNPC:  | 
|         return  | 
|       | 
|     __RecordAddExp(curPlayer, addExp)  | 
|     return  | 
|   | 
| def __RecordAddExp(curPlayer, addExp, isSys=False):  | 
|     playerID = curPlayer.GetID()   | 
|     gameFB = GameWorld.GetGameFB()  | 
|     exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)  | 
|     expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)  | 
|     totalExp = expPoint * ChConfig.Def_PerPointValue + exp  | 
|     updTotalExp = totalExp + addExp  | 
|     updExp = updTotalExp % ChConfig.Def_PerPointValue  | 
|     updExpPoint = updTotalExp / ChConfig.Def_PerPointValue  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_TotalExp, updExp)  | 
|     gameFB.SetPlayerGameFBDict(playerID, FBPlayerDict_TotalExpPoint, updExpPoint)  | 
|       | 
|     GameWorld.DebugLog("OnGetExp() totalExp=%s,addExp=%s,updTotalExp=%s,isSys=%s"   | 
|                        % (totalExp, addExp, updTotalExp, isSys), playerID)  | 
|     return  | 
|   | 
| ### Ö´Ðи±±¾É±¹ÖÂß¼  | 
| ##  @param curPlayer É±¹ÖµÄÈË  | 
| ##  @param curNPC ±»É±µÄ¹Ö  | 
| ##  @param tick µ±Ç°Ê±¼ä  | 
| ##  @return None  | 
| #def DoFB_DropOwner(curPlayer, curNPC):  | 
| #    playerID = curPlayer.GetID()   | 
| #    gameFB = GameWorld.GetGameFB()  | 
| #    killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)  | 
| #    gameFB.SetPlayerGameFBDict(playerID, BZZD_KillCnt, killNPCCnt + 1)  | 
| #      | 
| #    DoFBHelp(curPlayer, GameWorld.GetGameWorld().GetTick())  | 
| #    return  | 
|   | 
| #¹ØÏµÓÐ3²ã£¬ÎÞ-ÓѺÃ-µÐÈË  | 
| ##ÅжÏÊÇ·ñ¿ÉÊÍ·Å(Ôö/¼õ)¼¼ÄÜ»òÆÕ¹¥  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param curTagPlayer Ä¿±êÍæ¼ÒʵÀý  | 
| # @return ²¼¶ûÖµ  | 
| def CheckPlayersRelation_IsNone(curPlayer, curTagPlayer):  | 
|     #PlayerControl.NotifyCode(curPlayer, "PK_lhs_272921")  | 
|     return True  | 
|   | 
| ## ¸±±¾½áÊø´¦Àí  | 
| def __DoBZZDOver():  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     CheckFirstEnterExp(tick, True) # ½áËãÇ°Ç¿ÖÆ´¦ÀíÒ»´Î  | 
|       | 
|     playerManager = GameWorld.GetMapCopyPlayerManager()  | 
|     playerCount = playerManager.GetPlayerCount()  | 
|     if not playerCount:  | 
|         GameWorldProcess.CloseFB(tick)  | 
|         return  | 
|     mapID = GameWorld.GetMap().GetMapID()  | 
|     fbCfg = FBCommon.GetFBLineStepTime(mapID)  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     costTime = tick - gameFB.GetFBStepTick()  | 
|       | 
|     for i in xrange(playerCount):  | 
|         curPlayer = playerManager.GetPlayerByIndex(i)  | 
|         if not curPlayer:  | 
|             continue  | 
|         playerID = curPlayer.GetPlayerID()  | 
|           | 
|         # ¼Ç¼×î¸ß×ܾÑé  | 
|         exp = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExp)  | 
|         expPoint = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_TotalExpPoint)  | 
|         totalExp = expPoint * ChConfig.Def_PerPointValue + exp  | 
|           | 
|         expRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_TotalFightExp)  | 
|         expPointRecord = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_BZZD_TotalFightExpPoint)  | 
|         totalExpRecord = expPointRecord * ChConfig.Def_PerPointValue + expRecord  | 
|         upPer = 0 #ÌáÉý±ÈÀý  | 
|         if totalExp > totalExpRecord:#³¬¹ý¾É¼Ç¼  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_TotalFightExp, exp)  | 
|             PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_BZZD_TotalFightExpPoint, expPoint)  | 
|             upPer = (totalExp - totalExpRecord)*100/totalExpRecord if totalExpRecord else 0  | 
|             #µ¥³¡×ܾÑé³É¾Í  | 
|             PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_XJMJGetExp, 1, [expPoint])  | 
|               | 
|         #killNPCCnt = gameFB.GetPlayerGameFBDictByKey(playerID, BZZD_KillCnt)  | 
|         killNPCCnt = int(PyGameData.g_bzzdPlayerKillNPCCntDict.get(playerID, 0))  | 
|           | 
|         # Í¨Öª½á¹û  | 
|         enterLV = gameFB.GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnterLV)  | 
|         __SendBZZDOverInfo(curPlayer, {FBCommon.Over_enterLV:enterLV,FBCommon.Over_exp:exp, FBCommon.Over_expPoint:expPoint,FBCommon.Over_costTime:costTime, FBCommon.Over_npcTotal:killNPCCnt, 'upPer':upPer})  | 
|       | 
|     # ½øÈëÀ뿪½×¶Î  | 
|     FBCommon.SetFBStep(FB_Step_Over, tick)  | 
|     FBCommon.Sync_Player_TimeTick(IPY_GameWorld.tttLeaveMap, fbCfg[Def_LeaveTime] * 1000)  | 
|       | 
|     rMarkList = IpyGameDataPY.GetFuncEvalCfg('FairylandPoint')  | 
|     for rMark in rMarkList:  | 
|         NPCCustomRefresh.CloseNPCRefresh(rMark, tick)  | 
|     return  | 
|   | 
| ## ·¢ËÍÌôÕ½½á¹ûÐÅÏ¢£¬  | 
| def __SendBZZDOverInfo(curPlayer, overDict):  | 
|     overDict[FBCommon.Over_isPass] = 1 #ĬÈÏͨ¹Ø  | 
|     overDict[FBCommon.Over_dataMapID] = ChConfig.Def_FBMapID_BZZD  | 
|     GameWorld.DebugLog("__SendBZZDOverInfo overDict=%s" % (str(overDict)), curPlayer.GetPlayerID())  | 
|     FBCommon.Notify_FB_Over(curPlayer, overDict)  | 
|     return  | 
|   | 
|   | 
| ## ¸±±¾ÐÐΪ  | 
| #  @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   | 
|       | 
|     return  | 
|   |