#!/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]
|
|