#!/usr/bin/python # -*- coding: GBK -*- #------------------------------------------------------------------------------- # ##@package NPCHurtMgr # # @todo:NPCÉËѪ¹ÜÀí # @author hxp # @date 2020Äê03ÔÂ16ÈÕ # @version 1.0 # # ÏêϸÃèÊö: NPCÉËѪ¹ÜÀí # # ÓÉÓÚ NPCHurtManager Ä£¿é֮ǰÕë¶ÔЭÖú×öµÄ£¬²âÊԱȽÏÂé·³£¬ÎªÁ˲»È¥¶¯µ½Ô­À´µÄÄ£¿éÂß¼­£¬¹ÊÐÂдһ¸öÉËѪģ¿é¹ÜÀí # ÐÂÄ£¿éÉËѪÁбíͨÓÃÂß¼­Óɸ¸Àà´¦Àí£¬ÇÒº¯ÊýÃüÃûÓëc++½Ó¿ÚÌṩµÄº¯ÊýÃûÒ»Ö£¬²»Í¬ÐèÇóÀàÐ͵ÄÉËѪÁбí¶îÍâÂß¼­Ôò¿ÉÀ©Õ¹×ÓÀà½øÐд¦Àí # #------------------------------------------------------------------------------- #"""Version = 2020Äê03ÔÂ16ÈÕ 18:00""" #------------------------------------------------------------------------------- import GameWorld import PyGameData import IPY_GameWorld import IpyGameDataPY import PlayerBossReborn import PlayerActHorsePetFeast import ChPyNetSendPack import NetPackCommon import ShareDefine import PlayerTeam import NPCCommon import ChConfig import GameObj class HurtValueObj(): ''' ÉËѪ¶ÔÏ󣬿ÉÄÜÊÇÍæ¼Ò¡¢¶ÓÎéµÈ ''' def __init__(self): self.__hurtID = 0 self.__hurtType = ChConfig.Def_NPCHurtTypePlayer # ¾ùĬÈÏÊÇÍæ¼Ò self.__hurtName = "" self.__hurtValue = 0 return def GetValueID(self): return self.__hurtID def SetValueID(self, hurtID): self.__hurtID = hurtID def GetValueType(self): return self.__hurtType def SetValueType(self, hurtType): self.__hurtType = hurtType def GetHurtName(self): return self.__hurtName def SetHurtName(self, hurtName): self.__hurtName = hurtName def GetHurtValue(self): return self.__hurtValue def SetHurtValue(self, hurtValue): self.__hurtValue = hurtValue class HurtValueObjList(object): ''' ÉËѪÁÐ±í¸¸À࣬ÀàËÆ IPY_GameObj.IPY_PlayerHurtList Ö»×ö»ù´¡µÄÉËѪÀÛ¼Ó¡¢ÅÅÐòµÈ¹«¹²Âß¼­ ×¢Ò⣺ ԭЭÖúÉ˺¦ÒòΪÊÇ×îÏÈ×öµÄÂß¼­£¬²âÊԱȽÏÂé·³£¬Ôݲ»Ð޸ļ̳иÃÀ࣬»¹ÊDZ£ÁôÔ­À´µÄµ¥¶À´¦Àí ºóÐøÐèÒªÔö¼ÓµÄ²»Í¬ÉËѪ¹æÔòÂß¼­¿ÉÖ±½Ó¼Ì³Ð¸ÃÀà½øÐÐÀ©Õ¹´¦Àí ''' def __init__(self, lineID, objID, npcID): GameWorld.DebugLog("¼ÓÔØNPCÉËѪÁбí!", npcID, lineID) self.lineID = lineID self.objID = objID self.npcID = npcID self.curNPC = GameWorld.FindNPCByID(objID) self.__hurtPlayerDict = {} # ËùÓÐÉËÑªÍæ¼Ò¸öÌåʵÀý×Öµä {playerID:HurtValueObj, ...} self.__hurtSortList = [] self.__hurtDict = {} # ÉËѪÁбíʵÀý×ֵ䣬ʵ¼ÊµÄNPCÉËѪÁбíʵÀý£¬¿ÉÄܲ»ÊÇÍæ¼Ò{(hurtID, hurtType):HurtValueObj, ...} self.checkHurtValidFunc = None # ¼ì²éÉËѪÓÐЧÐÔº¯Êý£¬ÎÞЧÉËѪÇå³ý£¬¿É²»ÉèÖã¬Ôò²»¼ì²é self.getHurtObjPlayerIDListFunc = None # »ñÈ¡ÉËѪÍÅÌåʵÀý°üº¬µÄÍæ¼ÒIDÁÐ±í£¬¿É²»ÉèÖã¬Ôò°´ÉËѪÀàÐÍÈ¡¶ÔӦĬÈÏIDÁбí self.onKilledFunc = None # npc±»»÷ɱºóÐø´¦Àíº¯Êý£¬¿É²»ÉèÖà return def Clear(self): GameWorld.DebugLog("Çå³ýNPCÉËѪÁбí!", self.npcID, self.lineID) self.__hurtSortList = [] self.__hurtDict = {} # ÖØÖÃËùÓÐÍæ¼ÒÉËѪֵ for hurtObj in self.__hurtPlayerDict.values(): hurtObj.SetHurtValue(0) return def OnDelete(self): return def __GetHurtObj(self, hurtID, hurtType, hurtName=""): ## »ñÈ¡ÉËѪÁбíÉËѪÀàÐÍʵÀý£¬¿ÉÄÜÊǸöÈË¡¢¶ÓÎé¡¢¼Ò×å¡¢ÕóÓªµÈ hurtObj = None hurtKey = (hurtID, hurtType) if hurtKey not in self.__hurtDict: GameWorld.DebugLog("Ìí¼ÓÉËѪÁбí¶ÔÏó: hurtID=%s,hurtType=%s" % (hurtID, hurtType), self.npcID, self.lineID) hurtObj = HurtValueObj() hurtObj.SetValueID(hurtID) hurtObj.SetValueType(hurtType) hurtObj.SetHurtName(hurtName) self.__hurtDict[hurtKey] = hurtObj hurtObj = self.__hurtDict[hurtKey] return hurtObj def __GetHurtPlayer(self, playerID, playerName=""): ## »ñÈ¡ÉËÑªÍæ¼ÒʵÀý, ÿ¸öÍæ¼Ò¶ÀÁ¢, ÇÒÉËѪ¶ÀÁ¢Í³¼Æ hurtPlayer = None if playerID not in self.__hurtPlayerDict: GameWorld.DebugLog("Ìí¼ÓÉËÑªÍæ¼Ò: playerID=%s,playerName=%s" % (playerID, playerName), self.npcID, self.lineID) hurtPlayer = HurtValueObj() hurtPlayer.SetValueID(playerID) #hurtPlayer.SetHurtName(playerName) self.__hurtPlayerDict[playerID] = hurtPlayer hurtPlayer = self.__hurtPlayerDict[playerID] # ÒòΪÉËÑªÍæ¼Ò¿ÉÄÜÔÚijЩÇé¿öÏ´´½¨ÁËûÓÐÃû×ÖµÄʵÀý£¬ËùÒÔÕâÀïÔÚÓд«ÈëÃû×Öʱ½øÐÐÇ¿ÖÆ¸üРif playerName: hurtPlayer.SetHurtName(playerName) return hurtPlayer def AddHurtValue(self, playerID, playerName, addValue, hurtType, hurtID, hurtName): ''' Ìí¼ÓÉËѪ @param playerID: ¹±Ï×É˺¦µÄÍæ¼ÒID @param playerName: ¹±Ï×É˺¦µÄÍæ¼ÒÃû @param addValue: ¹±Ï×É˺¦Öµ @param hurtType: ÉËѪÍÅÌåʵÀýÀàÐÍ£¬¿ÉÄÜÊÇÍæ¼Ò¸öÈË¡¢¶ÓÎé¡¢¼Ò×å¡¢ÕóÓªµÈ @param hurtID: ÉËѪÍÅÌåʵÀýID @param hurtName: ÉËѪÍÅÌåʵÀýÃû ''' hurtObj = self.__GetHurtObj(hurtID, hurtType, hurtName) # ÉËѪÁбíÉËѪÀÛ¼Ó£¬Ä³¸öÍÅÌåµÄÀÛ¼ÆÉ˺¦ befValue = hurtObj.GetHurtValue() updValue = befValue + addValue hurtObj.SetHurtValue(updValue) isNewHurt = befValue == 0 and updValue > 0 hurtPlayer = self.__GetHurtPlayer(playerID, playerName) # ÉËÑªÍæ¼ÒÉËѪÀÛ¼Ó£¬Õâ¸ö½öÉËÑªÍæ¼Ò×Ô¼ºµÄ¸öÈËÊä³ö£¬·ÇÉËѪÁбíÖеĻã×ÜÊä³ö updHurtPlayerValue = hurtPlayer.GetHurtValue() + addValue hurtPlayer.SetHurtValue(updHurtPlayerValue) #GameWorld.DebugLog(" hurtID=%s,hurtType=%s,updValue=%s (%s + %s), playerID=%s,updHurtPlayerValue=%s" # % (hurtID, hurtType, updValue, befValue, addValue, playerID, updHurtPlayerValue), self.npcID, self.lineID) if isNewHurt: self.Sort() return isNewHurt def __CmpHurtValue(self, hurtObjA, hurtObjB): ## É˺¦ÅÅÐò±È½Ïº¯Êý if hurtObjA.GetHurtValue() > hurtObjB.GetHurtValue(): return 1 if hurtObjA.GetHurtValue() == hurtObjB.GetHurtValue(): return 0 return -1 def Sort(self): ## ÉËѪÅÅÐò self.__hurtSortList = sorted(self.__hurtDict.values(), cmp=self.__CmpHurtValue, reverse=True) return def __SyncHurtList(self): ## ͬ²½Ç°¶ËÉËѪÁбí syncPlayerIDList = [] # Ôݶ¨ÅÅÐòºóĬÈÏͬ²½ÉËѪÁÐ±í¸øËùÓÐÏà¹ØÍæ¼Ò£¬ÉËѪΪ0µÄ²»Í¬²½Ç°¶Ë£¬½öÓÃÓÚºó¶ËÂß¼­Óà hurtValueList = [] for hurtObj in self.__hurtSortList: hurtValue = hurtObj.GetHurtValue() if not hurtValue: continue syncPlayerIDList += self.__GetHurtObjAllPlayerID(hurtObj) hurtValueObj = ChPyNetSendPack.tagMCBossHurtValue() hurtValueObj.HurtID = hurtObj.GetValueID() hurtValueObj.HurtType = hurtObj.GetValueType() hurtValueObj.HurtName = hurtObj.GetHurtName() hurtValueObj.HurtValue = hurtValue % ShareDefine.Def_PerPointValue hurtValueObj.HurtValueEx = hurtValue / ShareDefine.Def_PerPointValue hurtValueList.append(hurtValueObj) if len(hurtValueList) > 250: break if not syncPlayerIDList: return bossHurtInfoPack = ChPyNetSendPack.tagMCBossHurtValueRankInfo() bossHurtInfoPack.ObjID = self.objID bossHurtInfoPack.HurtValueList = hurtValueList bossHurtInfoPack.HurtCount = len(hurtValueList) curNPC = self.curNPC copyPlayerManager = GameWorld.GetMapCopyPlayerManager() for playerID in syncPlayerIDList: player = copyPlayerManager.FindPlayerByID(playerID) if not player: continue if not player.CanSeeOther(curNPC): continue NetPackCommon.SendFakePack(player, bossHurtInfoPack) return def RefreshHurtList(self, tick, refreshInterval=3000, isKilled=False): '''Ë¢ÐÂÉËѪÁбí @return: atkPlayer, hurtID, hurtType ''' curNPC = self.curNPC if not isKilled: if refreshInterval and tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < refreshInterval: return self.__GetAtkObj(isKilled) curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick) # 1. ¼ì²éÇå³ýÎÞЧÉËѪ if self.checkHurtValidFunc: self.checkHurtValidFunc() # 2. ÅÅÐò self.Sort() # 3. ͬ²½Ç°¶Ë self.__SyncHurtList() # 4. »÷ɱ¸½¼ÓÂß¼­ if isKilled: if self.onKilledFunc: self.onKilledFunc() return self.__GetAtkObj(isKilled) def __GetAtkObj(self, isKilled): '''µÚÒ»¸ö¿É¹¥»÷µÄ×î´óÉËѪ¶ÔÏó @return: atkPlayer, hurtType, hurtID ''' import AttackCommon atkPlayer, atkHurtType, atkHurtID = None, 0, 0 curNPC = self.curNPC refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex()) for rank, hurtObj in enumerate(self.__hurtSortList, 1): hurtID = hurtObj.GetValueID() hurtType = hurtObj.GetValueType() playerIDList = self.__GetHurtObjAllPlayerID(hurtObj) playerDisableReason = {} maxHurtValue = 0 for playerID in playerIDList: player = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer) if player == None: continue if GameObj.GetHP(player) <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie: playerDisableReason[playerID] = "dead" continue if not player.GetVisible() or not AttackCommon.CheckSightLevel(player, curNPC): playerDisableReason[playerID] = "no visible or sightLevel different" continue if not self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint): playerDisableReason[playerID] = "not in boss area" continue if playerID not in self.__hurtPlayerDict: playerDisableReason[playerID] = "no hurt" continue hurtPlayer = self.__hurtPlayerDict[playerID] hurtValue = hurtPlayer.GetHurtValue() if hurtValue > maxHurtValue: maxHurtValue = hurtValue atkPlayer, atkHurtType, atkHurtID = player, hurtType, hurtID if maxHurtValue: return atkPlayer, atkHurtType, atkHurtID if rank == 1 and isKilled: pass #GameWorld.Log("bossËÀÍöʱ£¬µÚÒ»ÃûÍŶÓûÓйéÊôȨ! playerDisableReason=%s" % playerDisableReason) return atkPlayer, atkHurtType, atkHurtID def __GetHurtObjAllPlayerID(self, hurtObj): ## »ñÈ¡ÉËѪʵÀýÍÅÌåËùÓеÄÍæ¼ÒID hurtID = hurtObj.GetValueID() hurtType = hurtObj.GetValueType() if self.getHurtObjPlayerIDListFunc: return self.getHurtObjPlayerIDListFunc(hurtObj) if hurtType == ChConfig.Def_NPCHurtTypePlayer: return [hurtID] if hurtType == ChConfig.Def_NPCHurtTypeTeam: teamID = hurtID return PlayerTeam.GetMapTeamPlayerIDList(teamID) return [] def GetIsInRefreshPoint(self, curPosX, curPosY, refreshPoint): if not refreshPoint: return False if (curPosX >= refreshPoint.GetPosX() - refreshPoint.GetMoveDist() and curPosX <= refreshPoint.GetPosX() + refreshPoint.GetMoveDist() and curPosY >= refreshPoint.GetPosY() - refreshPoint.GetMoveDist() and curPosY <= refreshPoint.GetPosY() + refreshPoint.GetMoveDist()): return True return False def GetHurtCount(self): return len(self.__hurtSortList) def GetHurtAt(self, index): return self.__hurtSortList[index] def GetMaxHurtValue(self): return None if not self.__hurtSortList else self.__hurtSortList[0] def GetLastTimeHurtValue(self): return class PlayerRankHurtList(HurtValueObjList): ''' ÅÅÐÐÉËѪÁбí×ÓÀà, ÀàËÆ IPY_GameObj.IPY_PlayerHurtList ÉËѪÁÐ±í¹æÔò: ͳ¼Æ¹éÊôÀàÐÍΪ ChConfig.DropOwnerType_RankHurtPlayer ²»Ö§³ÖЭÖú£¬½öͳ¼Æ¸öÈËÉ˺¦£¬²»ÇåÉËѪ£¬¸ù¾ÝÍæ¼ÒÅÅÃû·¢·ÅÓʼþ½±Àø ''' def __init__(self, lineID, objID, npcID): super(PlayerRankHurtList, self).__init__(lineID, objID, npcID) self.onKilledFunc = self.__DoNPCOnKilledLogic return def Clear(self): ## ¸ÃÁÐ±í²»ÇåÉËѪ£¬ÖØÐ´Clearº¯Êý GameWorld.DebugLog("²»ÇåNPCÉËѪÁбí!", self.npcID, self.lineID) return def AddHurtValue(self, atkPlayer, addValue): ## Ìí¼ÓÍæ¼ÒÅÅÐÐÉËѪ playerID = atkPlayer.GetPlayerID() playerName = atkPlayer.GetPlayerName() hurtType = ChConfig.Def_NPCHurtTypePlayer # ¸ÃÁбíֻĬÈÏÍæ¼Ò super(PlayerRankHurtList, self).AddHurtValue(playerID, playerName, addValue, hurtType, playerID, playerName) return def __DoNPCOnKilledLogic(self): ## Ö´ÐÐNPC»÷ɱºóÐø´¦ÀíÂß¼­ if self.npcID == IpyGameDataPY.GetFuncCfg("BossRebornServerBoss", 3): PlayerBossReborn.DoBossRebornActionBossOnKilledLogic(self) PlayerActHorsePetFeast.DoActBossOnKilledLogic(self) ## ͬÑù°ñµ¥Âß¼­µÄ²»Í¬¹¦Äܽ±Àø´¦Àí ... return def __GetBossLineID(npcID): return GameWorld.GetGameWorld().GetLineID() def ClearPlayerHurtList(curNPC): ## Çå¿ÕÉËѪÁбí - ÖØÖÃNPC״̬ʱµ÷Óà objID = curNPC.GetID() npcID = curNPC.GetNPCID() lineID = __GetBossLineID(npcID) key = (lineID, objID, npcID) if key in PyGameData.g_npcHurtListDict: hurtList = PyGameData.g_npcHurtListDict[key] hurtList.Clear() return def DeletePlayerHurtList(curNPC): ## ɾ³ýÉËѪÁбí - NPCËÀÍöʱµ÷Óà objID = curNPC.GetID() npcID = curNPC.GetNPCID() lineID = __GetBossLineID(npcID) key = (lineID, objID, npcID) if key in PyGameData.g_npcHurtListDict: hurtList = PyGameData.g_npcHurtListDict.pop(key) hurtList.OnDelete() return def RefreshHurtList(curNPC, tick, refreshInterval=3000, isKilled=False): ## Ë¢ÐÂÉËѪÁбí # @return: atkPlayer, ownerType, ownerID objID = curNPC.GetID() npcID = curNPC.GetNPCID() lineID = __GetBossLineID(npcID) key = (lineID, objID, npcID) if key not in PyGameData.g_npcHurtListDict: return hurtList = PyGameData.g_npcHurtListDict[key] return hurtList.RefreshHurtList(tick, refreshInterval, isKilled) def AddHurtValue(atkPlayer, defNPC, value, isBounce): '''Ìí¼ÓÉËѪ @param isBounce: ÊÇ·ñ·´µ¯É˺¦£¬·´µ¯É˺¦²»¼ÆÈë·ÇÖ÷¶¯¹¥»÷µÄÍæ¼ÒÉËѪ£¬ÒòΪ¹æ¶¨Íæ¼Ò¹¥»÷ÁíÒ»¸öbossÔòÒªÇå³ýͬµØÍ¼ÉÏÒ»¸öbossµÄ¸ÃÍæ¼ÒÉ˺¦ ·ÀÖ¹ËÀÍö»Ø¸´»îµãÅÜͼÖб»Ö÷¶¯ÐÍboss¹¥»÷¼ÆÈëÉËѪµ¼ÖÂÇå³ýͬµØÍ¼ÉÏÒ»¸öÖ÷¶¯¹¥»÷µÄbossÉËѪ ''' if not ChConfig.IsGameBoss(defNPC): return ## ¸ù¾Ý¸öÈËÉËѪÅÅÐÐÖ±½Ó¸ø½±ÀøµÄ if NPCCommon.GetDropOwnerType(defNPC) == ChConfig.DropOwnerType_RankHurtPlayer: hurtList = __AddNewHurtList(defNPC, PlayerRankHurtList) ## ÆäËûÉËѪÁбí×ÓÀà¹ÜÀí ... else: return return hurtList.AddHurtValue(atkPlayer, value) def __AddNewHurtList(curNPC, className): objID = curNPC.GetID() npcID = curNPC.GetNPCID() lineID = __GetBossLineID(npcID) key = (lineID, objID, npcID) if key not in PyGameData.g_npcHurtListDict: hurtList = className(lineID, objID, npcID) PyGameData.g_npcHurtListDict[key] = hurtList hurtList = PyGameData.g_npcHurtListDict[key] return hurtList def GetPlayerHurtList(curNPC): ''' »ñÈ¡ÉËѪÁÐ±í£¬¿ÉÄÜΪNone ''' if not ChConfig.IsGameBoss(curNPC): return objID = curNPC.GetID() npcID = curNPC.GetNPCID() lineID = __GetBossLineID(npcID) key = (lineID, objID, npcID) if key not in PyGameData.g_npcHurtListDict: return return PyGameData.g_npcHurtListDict[key]