| #!/usr/bin/python  | 
| # -*- coding: GBK -*-  | 
| #-------------------------------------------------------------------------------  | 
| #  | 
| ##@package GameWorldLogic.FBProcess.GameLogic_Dogz  | 
| #  | 
| # @todo:ÉñÊÞµØ½ç  | 
| # @author xdh  | 
| # @date 2018-08-17  | 
| # @version 1.0  | 
| #  | 
| # ÏêϸÃèÊö: ÉñÊÞµØ½ç  | 
| #  | 
| #-------------------------------------------------------------------------------  | 
| #"""Version = 2018-08-17 16:30"""  | 
| #-------------------------------------------------------------------------------  | 
|   | 
| import GameWorld  | 
| import IpyGameDataPY  | 
| import IPY_GameWorld  | 
| import ShareDefine  | 
| import NPCCustomRefresh  | 
| import SkillCommon  | 
| import GameObj  | 
| import time  | 
| import random  | 
| import ChConfig  | 
|   | 
|   | 
| #{(±êʶµã):[npcid,µ¥¸öµãÊýÁ¿,ˢмä¸ôÃë, Ã¿´ÎË¢ÐÂÖ»Êý, µÚÒ»´ÎË¢ÐÂÖ»Êý, ×ܸöÊýÉÏÏÞ]}  | 
| #{(101,102,103):[20302001,1,'20', 2, 10,30]}  | 
| (  | 
| Def_NPCID,  | 
| Def_MaxCnt,  | 
| Def_TimeFormula,  | 
| Def_RefreshCnt,  | 
| Def_FirstRefreshCnt,  | 
| Def_TotalLimit,  | 
| ) = range(6)  | 
|   | 
| Map_Dogzfb_LastRefreshTime = "Dogzfb_LastRefreshTime%s"  # Ë¢ÐÂʱ¼ä ²ÎÊýnpcid  | 
| Map_Dogzfb_NextNeedTime = "NextNeedTime%s"  # Ï´ÎË¢ÐÂÐèҪʱ¼ä ²ÎÊýnpcid  | 
| Map_Dogzfb_LastCheckTick = "LastCheckTick"  # Éϴμì²éʱ¼ä  | 
| Map_Dogzfb_NPCRemainCnt = 'NPCRemainCnt_%s'   # NPCÊ£ÓàÊýÁ¿  | 
| Map_Dogzfb_CollectLostHPTick = 'CollectLostHPTick'   # ²É¼¯µôѪTick  | 
| Map_Dogzfb_CollectLostHPCnt = 'CollectLostHPCnt'   # ²É¼¯µôѪ´ÎÊý  | 
|   | 
| ## ÊÇ·ñÄܹ»Í¨¹ý»î¶¯²éѯ½øÈë  | 
| #  @param curPlayer Íæ¼ÒʵÀý  | 
| #  @param mapID µØÍ¼ID  | 
| #  @param lineID Ïß·id  | 
| #  @param tick Ê±¼ä´Á  | 
| #  @return ²¼¶ûÖµ  | 
| def OnEnterFBEvent(curPlayer, mapID, lineID, tick):  | 
|     return True  | 
|   | 
|   | 
| ## ²éѯµØÍ¼ÊÇ·ñ¿ªÆô  | 
| #  @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 curPlayer  | 
| #  @param tick  | 
| #  @return None  | 
| def DoEnterFB(curPlayer, tick):  | 
|   | 
|     return  | 
|   | 
|   | 
|   | 
| ### ÊÇ·ñ¸±±¾¸´»î  | 
| ##  @param None  | 
| ##  @return ÊÇ·ñ¸±±¾¸´»î  | 
| #def OnPlayerReborn():  | 
| #    return False  | 
|   | 
|   | 
| ## »ñµÃ¸±±¾°ïÖúÐÅÏ¢  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò£¨±»Í¨Öª¶ÔÏó£©  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBHelp(curPlayer, tick, isEnter=False):  | 
|   | 
|     return  | 
|   | 
|   | 
| ## ¸±±¾ÐÐΪ  | 
| #  @param curPlayer Íæ¼Ò  | 
| #  @param actionType ÐÐΪÀàÐÍ  | 
| #  @param actionInfo ÐÐΪÐÅÏ¢  | 
| #  @param tick µ±Ç°Ê±¼ä  | 
| #  @return None  | 
| def DoFBAction(curPlayer, actionType, actionInfo, tick):  | 
|       | 
|     return  | 
|   | 
| ## ¿ªÊ¼²É¼¯  | 
| #  @param curPlayer µ±Ç°Íæ¼Ò  | 
| #  @param curNPC µ±Ç°NPC  | 
| #  @return None or False  | 
| #  @remarks º¯ÊýÏêϸ˵Ã÷.  | 
| def OnBeginCollect(curPlayer, curNPC):  | 
|     playerID = curPlayer.GetID()  | 
|     tick = GameWorld.GetGameWorld().GetTick()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     gameFB.SetPlayerGameFBDict(playerID, Map_Dogzfb_CollectLostHPTick, tick)  | 
|     gameFB.SetPlayerGameFBDict(playerID, Map_Dogzfb_CollectLostHPCnt, 0)  | 
|     return  | 
|   | 
| ## ÊÕ¼¯ÖÐ  | 
| def OnCollecting(curPlayer, tick):  | 
|     tagObj = curPlayer.GetActionObj()  | 
|     if not tagObj:  | 
|         return  | 
|     if tagObj.GetGameObjType() != IPY_GameWorld.gotNPC:  | 
|         return  | 
|       | 
|     curNPC = GameWorld.GetNPCManager().GetNPCByIndex(tagObj.GetIndex())  | 
|     npcID = curNPC.GetNPCID()  | 
|     __DoCollectLostHP(curPlayer, npcID, tick)  | 
|     return  | 
|   | 
| def __DoCollectLostHP(curPlayer, npcID, tick):  | 
|       | 
|       | 
|     playerID = curPlayer.GetID()  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     collectLostHPTick = gameFB.GetPlayerGameFBDictByKey(playerID, Map_Dogzfb_CollectLostHPTick)  | 
|     lostHPCnt = gameFB.GetPlayerGameFBDictByKey(playerID, Map_Dogzfb_CollectLostHPCnt)  | 
|       | 
|     lostCD = IpyGameDataPY.GetFuncEvalCfg('DogzFBCollect', 1, {}).get(npcID, 1)  | 
|     lostTime = (tick - collectLostHPTick) / (1000*lostCD)-lostHPCnt  | 
|       | 
|     if not lostTime:  | 
|         return  | 
|     gameFB.SetPlayerGameFBDict(playerID, Map_Dogzfb_CollectLostHPCnt, lostHPCnt+lostTime)  | 
|           | 
|      | 
|     lostHPPer = IpyGameDataPY.GetFuncEvalCfg('DogzFBCollect', 2, {}).get(npcID, 1)  | 
|     skillTypeID, buffOwner = 0, None  | 
|     lostValue = min(int(GameObj.GetMaxHP(curPlayer) * lostHPPer / 100.0) * lostTime, GameObj.GetHP(curPlayer)-1)  | 
|     if lostValue <=0:  | 
|         return  | 
|     GameWorld.DebugLog("OnCollecting npcID=%s, lostHPPer=%s,lostTime=%s,lostValue=%s" % (npcID, lostHPPer, lostTime, lostValue))  | 
|     SkillCommon.SkillLostHP(curPlayer, skillTypeID, buffOwner, lostValue, tick)  | 
|     return  | 
|   | 
| ##Íæ¼ÒÊÕ¼¯³É¹¦(Ëþ, Æì)  | 
| # @param curPlayer Íæ¼ÒʵÀý  | 
| # @param tick Ê±¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks  | 
| def OnCollectOK(curPlayer, npcID, tick):  | 
|     __DoCollectLostHP(curPlayer, npcID, tick)  | 
|     return  | 
|   | 
| ##---¸±±¾×ÜÂß¼¼ÆÊ±Æ÷---  | 
| # @param tick:ʱ¼ä´Á  | 
| # @return ÎÞÒâÒå  | 
| # @remarks ¸±±¾×ÜÂß¼¼ÆÊ±Æ÷  | 
| def OnProcess(tick):  | 
|     CheckRefreshBoss(tick)  | 
|     return  | 
|   | 
|   | 
| def CheckRefreshBoss(tick, isFirst=False):  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     lastCheckTick = gameFB.GetGameFBDictByKey(Map_Dogzfb_LastCheckTick)  | 
|     if not (isFirst or (lastCheckTick and tick - lastCheckTick > 1000)):  | 
|         return  | 
|     gameFB.SetGameFBDict(Map_Dogzfb_LastCheckTick, tick)  | 
|       | 
|     dogzRefreshCfg = IpyGameDataPY.GetFuncEvalCfg('DogzFBRefreshCfg', 1, {})  | 
|     curTime = int(time.time())  | 
|     gameWorld = GameWorld.GetGameWorld()  | 
|     refreshDict = {}  | 
|     for markInfo, refreshInfo in dogzRefreshCfg.items():  | 
|         npcID = refreshInfo[Def_NPCID]  | 
|           | 
|         nextNeedTime = gameWorld.GetGameWorldDictByKey(Map_Dogzfb_NextNeedTime % npcID)  | 
|         if not nextNeedTime:  | 
|             continue  | 
|         lastRefreshTime = gameWorld.GetGameWorldDictByKey(Map_Dogzfb_LastRefreshTime % npcID)  | 
|         if lastRefreshTime and curTime - lastRefreshTime < nextNeedTime:  | 
|             #ʱ¼äδµ½  | 
|             continue  | 
|         refreshDict[markInfo] = refreshInfo  | 
|     if not refreshDict:  | 
|         return  | 
|       | 
|     npcCntDict = {}  #±êʶµã¶ÔÓ¦ÊýÁ¿  | 
|     gameNPC = GameWorld.GetNPCManager()  | 
|     for i in xrange(0, gameNPC.GetCustomNPCRefreshCount()):  | 
|         npcRefresh = gameNPC.GetCustomNPCRefreshAt(i)  | 
|         npcCnt = npcRefresh.GetCount()  | 
|         if not npcCnt:  | 
|             continue  | 
|         rmark = npcRefresh.GetRefreshMark()  | 
|         npcCntDict[rmark] = npcCntDict.get(rmark, 0) + npcRefresh.GetCount()  | 
|     isNeedSync = False #ÊÇ·ñÐèҪ֪ͨ  | 
|     for markInfo, refreshInfo in refreshDict.items():  | 
|         npcID = refreshInfo[Def_NPCID]  | 
|         refreshCnt = refreshInfo[Def_FirstRefreshCnt] if isFirst else refreshInfo[Def_RefreshCnt]  | 
|         gameWorld.SetGameWorldDict(Map_Dogzfb_LastRefreshTime % npcID, curTime)  | 
|         maxCnt = refreshInfo[Def_MaxCnt]  | 
|         markList = [markInfo] if isinstance(markInfo, int) else list(markInfo)  | 
|         curTotalCnt = 0  | 
|         for rMark in markList:  | 
|             curTotalCnt += npcCntDict.get(rMark, 0)  | 
|         refreshCnt = min(refreshCnt, refreshInfo[Def_TotalLimit] - curTotalCnt)  | 
|         if refreshCnt > 0:  | 
|             random.shuffle(markList)  | 
|             for rMark in markList:  | 
|                 if refreshCnt <=0:  | 
|                     break  | 
|                 curCnt = npcCntDict.get(rMark, 0)  | 
|                 if curCnt >= maxCnt:  | 
|                     continue  | 
|                 needRefreshCnt = min(refreshCnt, maxCnt - curCnt)  | 
|                 refreshCnt -= needRefreshCnt  | 
|                 NPCCustomRefresh.SetNPCRefresh(rMark, [(npcID, needRefreshCnt)], needRefreshCnt + curCnt, needRefreshCnt)  | 
|           | 
|         #¼ÆËãÏ´ζà¾ÃˢР | 
|         __UpdateBossTime(npcID, refreshInfo[Def_TimeFormula])  | 
|         if npcID in IpyGameDataPY.GetFuncEvalCfg('DogzFBRefreshCfg', 3):  | 
|             isNeedSync = True  | 
|     #֪ͨʱ¼ä  | 
|     if isNeedSync:  | 
|         SyncNPCRefreshTime()  | 
|       | 
|     return  | 
|   | 
| def OnOnlineCntChange(key, tick):  | 
|     if GameWorld.GetMap().GetMapID() != ChConfig.Def_FBMapID_Dogz:  | 
|         return  | 
|     bossid = IpyGameDataPY.GetFuncCfg('DogzFBRefreshCfg', 2)  | 
|     if str(bossid) not in key:  | 
|         return  | 
|     gameFB = GameWorld.GetGameFB()  | 
|     lastCheckTick = gameFB.GetGameFBDictByKey(Map_Dogzfb_LastCheckTick)  | 
|     if not lastCheckTick:  | 
|         dogzRefreshCfg = IpyGameDataPY.GetFuncEvalCfg('DogzFBRefreshCfg', 1, {})  | 
|         for refreshInfo in dogzRefreshCfg.values():  | 
|             npcID = refreshInfo[Def_NPCID]  | 
|             __UpdateBossTime(npcID, refreshInfo[Def_TimeFormula])  | 
|         CheckRefreshBoss(tick, True)  | 
|     return  | 
|   | 
| def __UpdateBossTime(npcID, formula):  | 
|     gameWorldMgr = GameWorld.GetGameWorld()  | 
|     onlineCnt = gameWorldMgr.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_BossOnlineHeroCnt)  | 
|     nextTime = eval(formula)  | 
|     gameWorldMgr.SetGameWorldDict(Map_Dogzfb_NextNeedTime % npcID, nextTime)  | 
|     #GameWorld.DebugLog('    ¹Öˢмä¸ô  npcID=%s, nextTime=%s'%(npcID, nextTime))  | 
|     return  | 
|   | 
| def GetDogzNPCRefreshTime(curTime, npcID):  | 
|     #»ñÈ¡NPCÊ£ÓàË¢ÐÂʱ¼ä  | 
|     gameWorldMgr = GameWorld.GetGameWorld()  | 
|     lastRefreshTime = gameWorldMgr.GetGameWorldDictByKey(Map_Dogzfb_LastRefreshTime % npcID)  | 
|     nextNeedTime = gameWorldMgr.GetGameWorldDictByKey(Map_Dogzfb_NextNeedTime % npcID)  | 
|     return max(0, nextNeedTime - curTime + lastRefreshTime)  | 
|   | 
| def SyncNPCRefreshTime():  | 
|     syncNPCIDList = IpyGameDataPY.GetFuncEvalCfg('DogzFBRefreshCfg', 3)  | 
|     syncDict = {}  | 
|     for npcID in syncNPCIDList:  | 
|         gameWorldMgr = GameWorld.GetGameWorld()  | 
|         lastRefreshTime = gameWorldMgr.GetGameWorldDictByKey(Map_Dogzfb_LastRefreshTime % npcID)  | 
|         nextNeedTime = gameWorldMgr.GetGameWorldDictByKey(Map_Dogzfb_NextNeedTime % npcID)  | 
|         syncDict[npcID] = [lastRefreshTime, nextNeedTime]  | 
|     msgStr = str(syncDict)  | 
|     GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'DogzNPCTime', msgStr, len(msgStr))  | 
|     return  | 
|   |