From cc385fbb7443180fefe3a6bb36a693f84b3914f0 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期三, 15 八月 2018 18:17:44 +0800
Subject: [PATCH] Fix: 1382 【BUG】古神禁地杀死BOSS不涨怒气不掉东西无击杀人;      2540 【后端】掉落归属优化(增加死亡伤血保护时长配置);

---
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py        |  114 +++++++++++++++----------------------
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py           |    2 
 ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py |   29 +++++++--
 3 files changed, 72 insertions(+), 73 deletions(-)

diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py
index 1978c26..a460007 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCAI/AIType_186.py
@@ -25,7 +25,7 @@
 # @change: "2014-12-31 14:40" Alee 降低NPCAI消耗
 # @change: "2016-11-22 21:00" hxp 支持添加最大仇恨buff
 #------------------------------------------------------------------------------ 
-"""Version = 2016-11-22 21:00"""
+#"""Version = 2016-11-22 21:00"""
 #-------------------------------------------------------------------------------
 import ChConfig
 import NPCCommon
@@ -36,6 +36,7 @@
 import BaseAttack
 import PlayerState
 import SkillCommon
+import PyGameData
 import BuffSkill
 import GameObj
 
@@ -92,7 +93,7 @@
     npcControl.DoHPPerLogic(ChConfig.Def_NPCHurtTypeAll, 0)
     return
 
-def __RefreshDropOwner(curNPC, tick, refreshInterval=3000):
+def __RefreshDropOwner(curNPC, tick, refreshInterval=3000, isDead=False):
     ## 刷新boss掉落归属
     # @return: 可攻击的掉落归属目标玩家
     
@@ -121,13 +122,13 @@
             maxAngryObj = GameWorld.GetObj(angryID, angryObjType)
             
         tagObj = maxAngryObj
-        if dropOwnerType == ChConfig.DropOwnerType_MaxAngry and angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj:
+        if angryObjType == IPY_GameWorld.gotPlayer and maxAngryObj:
             teamID = maxAngryObj.GetTeamID()
             if teamID:
                 ownerType, ownerID = ChConfig.Def_NPCHurtTypeTeam, teamID
             else:
                 ownerType, ownerID = ChConfig.Def_NPCHurtTypePlayer, maxAngryObj.GetPlayerID()
-    __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType, ownerID)
+    __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType, ownerID, isDead)
     return tagObj
 
 def __GetMaxHurtTeamPlayer(curNPC, npcControl, teamID):
@@ -145,7 +146,7 @@
                 return curTeamPlayer
     return
 
-def __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType=0, ownerID=0):
+def __RefreshBossDropOwnerObjBuff(curNPC, npcControl, tick, ownerType=0, ownerID=0, isDead=False):
     npcID = curNPC.GetNPCID()
     dropOwnerType = NPCCommon.GetDropOwnerType(curNPC)
     if dropOwnerType not in [ChConfig.DropOwnerType_MaxHurt, ChConfig.DropOwnerType_MaxAngry]:
@@ -160,6 +161,8 @@
                            % (ownerType, ownerID, lastDropOwnerType, lastDropOwnerID))
         __DelBossDropOwnerBuff(curNPC, lastDropOwnerType, lastDropOwnerID, tick)
     
+    killerDict, curTeam, hurtType, hurtID = {}, None, 0, 0
+    
     # 更新归属
     curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerID, ownerID)
     curNPC.SetDict(ChConfig.Def_NPC_Dict_LastDropOwnerType, ownerType)
@@ -168,12 +171,18 @@
     if ownerType == ChConfig.Def_NPCHurtTypePlayer:
         curPlayer = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
         if curPlayer:
+            playerID = curPlayer.GetPlayerID()
+            hurtType, hurtID = ChConfig.Def_NPCHurtTypePlayer, playerID
+            killerDict[playerID] = curPlayer
             __AddBossDropOwnerPlayerBuff(curPlayer, tick, curNPC)
             
     elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
         curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
         if not curTeam:
             return
+        
+        # 因为有击杀次数限制,所以不是所有的队员都可以获得归属,所以这里设置为特殊指定玩家掉落
+        hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0
         
         refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
         for i in xrange(curTeam.GetMemberCount()):
@@ -185,12 +194,20 @@
                 and npcControl.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
                 and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False):
                 __AddBossDropOwnerPlayerBuff(curTeamPlayer, tick, curNPC)
+                killerDict[curTeamPlayer.GetPlayerID()] = curTeamPlayer
                 
             # 不同线、或者距离超出boss范围的队员不加归属buff
             else:
                 isOk = BuffSkill.DelBuffBySkillID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
                 if isOk:
                     GameWorld.DebugLog("删除归属队员buff: teamID=%s,playerID=%s" % (ownerID, curTeamPlayer.GetPlayerID()))
+                    
+    if isDead:
+        key = (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), npcID)
+        teamID = curTeam.GetTeamID() if curTeam else 0
+        if killerDict:
+            PyGameData.g_npcKillerInfo[key] = killerDict, curTeam, hurtType, hurtID
+        GameWorld.Log("Boss被击杀: npcID=%s,key=%s,playerIDList=%s,teamID=%s" % (npcID, key, killerDict.keys(), teamID))
     return
 
 def __AddBossDropOwnerPlayerBuff(curPlayer, tick, curNPC):
@@ -296,7 +313,7 @@
     PlayerState.SetBossStateTick(curPlayer, tick)
     
     #被击杀时强制刷新归属
-    __RefreshDropOwner(curNPC, tick, 0)
+    __RefreshDropOwner(curNPC, tick, 0, True)
     return
 
 ## NPC死亡处理
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
index de3baf4..59b7260 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -2789,6 +2789,12 @@
             # 这种情况一般是玩家未加入队伍前对该NPC有伤血,加入到某个队伍后,将该伤害转移到队伍中
             return True
         
+        if hurtPlayer.GetHP() <= 0 or hurtPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
+            deadTime = hurtPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)
+            if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):
+                #GameWorld.DebugLog("伤血玩家死亡超过伤血保护时长,清除该伤血!playerID=%s" % hurtID)
+                return True
+            
         #GameWorld.DebugLog("正常玩家伤血保护中!playerID=%s" % hurtID)
         return False
     
@@ -2806,6 +2812,13 @@
                 if curTeamPlayer.GetCopyMapID() != copyMapID:
                     #GameWorld.DebugLog("队员不在本线路,不计!playerID=%s" % playerID)
                     continue
+                
+                if curTeamPlayer.GetHP() <= 0 or curTeamPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
+                    deadTime = curTeamPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)
+                    if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):
+                        #GameWorld.DebugLog("伤血队员死亡超过伤血保护时长,不计!playerID=%s" % playerID)
+                        continue
+                    
                 #if curTeamPlayer.GetHP() > 0 and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
                 if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
                     #GameWorld.DebugLog("有队员在boss范围内,保留队伍伤血!teamID=%s,playerID=%s" % (teamID, curTeamPlayer.GetPlayerID()))
@@ -2945,7 +2958,7 @@
             #获得伤血对象
             hurtObj = npcHurtList.GetHurtAt(index)
             
-            curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, False)
+            curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, True)
             
             if curPlayer or curTeam:
                 return hurtObj
@@ -4149,55 +4162,12 @@
     #  @remarks 设置对象奖励
     def __GiveObjPrize(self):
         curNPC = self.__Instance
-        objID = curNPC.GetID()
+        #objID = curNPC.GetID()
         npcID = curNPC.GetNPCID()
         self.__LastHurtPlayer = self.__FindLastTimeHurtObjEx()
         self.__MaxHurtPlayer = self.__FindBossMaxHurtObj() # py自定义伤血所得到的Boss最大伤血玩家
         
         self.__AllKillerDict, curTeam, hurtType, hurtID = self.__FindNPCKillerInfo()
-        #isLog = self.__GetIsLog()
-        #if isLog:
-        #    GameWorld.Log("__GiveObjPrize npcID=%s,hurtType=%s,hurtID=%s,allKillPlayer=%s,curTeam=%s" 
-        #                  % (npcID, hurtType, hurtID, self.__AllKillerDict.keys(), curTeam.GetTeamID() if curTeam else None))
-            
-        # 归属队伍时,有击杀次数限制的NPC特殊处理
-        if hurtType == ChConfig.Def_NPCHurtTypeTeam and curTeam:
-            if ChConfig.IsGameBoss(curNPC) and GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_MaxHurt:
-                #if isLog:
-                #    GameWorld.DebugLog("击杀boss有次数限制的NPC,队伍人数=%s" % (curTeam.GetMemberCount()))
-                memInfoList = []
-                for i in xrange(curTeam.GetMemberCount()):
-                    curTeamPlayer = curTeam.GetMember(i)
-                    if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
-                        #if isLog:
-                        #    GameWorld.DebugLog("    i=%s,队员不存在!" % i)
-                        memInfoList.append(None)
-                        continue
-                    findBuff = SkillCommon.FindBuffByID(curTeamPlayer, ChConfig.Def_SkillID_DropOwnerBuff)[0]
-                    if not findBuff:
-                        #if isLog:
-                        #    GameWorld.DebugLog("    i=%s,找不到归属buff!" % i, curTeamPlayer.GetPlayerID())
-                        memInfoList.append([curTeamPlayer.GetPlayerID(), "Not DropOwnerBuff"])
-                        continue
-                    #同一张地图可能有多个boss,该队伍可能同时在打多个boss,且都获得归属,所以需判断归属的buff所对应的NPC实例ID
-                    if findBuff.GetOwnerType() != IPY_GameWorld.gotNPC or findBuff.GetOwnerID() != objID:
-                        #if isLog:
-                        #    GameWorld.DebugLog("    i=%s,不同归属bossBuff,不能设置归属!objID=%s,curBuffOwnerID=%s" 
-                        #                       % (i, objID, findBuff.GetOwnerID()), curTeamPlayer.GetPlayerID())
-                        #GameWorld.DebugLog("不同归属bossbuff,不能设置归属!objID=%s,curBuffOwnerID=%s" 
-                        #                   % (objID, findBuff.GetOwnerID()), curTeamPlayer.GetPlayerID())
-                        memInfoList.append([curTeamPlayer.GetPlayerID(), {"OwnerType":findBuff.GetOwnerType(), "OwnerID":findBuff.GetOwnerID()}])
-                        continue
-                    playerID = curTeamPlayer.GetPlayerID()
-                    if playerID not in self.__AllKillerDict:
-                        self.__AllKillerDict[playerID] = curTeamPlayer
-                    memInfoList.append([playerID, 1])
-                        
-                curTeam = None
-                hurtType, hurtID = ChConfig.Def_NPCHurtTypeSpecial, 0
-                
-                if not self.__AllKillerDict:
-                    GameWorld.ErrLog("归属异常队伍信息: objID=%s,npcID=%s, %s" % (objID, npcID, memInfoList))
                     
         #最后一击处理
         self.__DoLastTimeHurtLogic()
@@ -4299,6 +4269,14 @@
     def __FindNPCKillerInfo(self):
         curNPC = self.__Instance
         npcID = curNPC.GetNPCID()
+        objID = curNPC.GetID()
+        key = (GameWorld.GetGameWorld().GetLineID(), objID, npcID)
+        if key in PyGameData.g_npcKillerInfo:
+            killerDict, killTeam, hurtType, hurtID = PyGameData.g_npcKillerInfo.pop(key)
+            teamID = killTeam.GetTeamID() if killTeam else 0
+            GameWorld.Log("NPC被击杀,归属信息: key=%s,playerIDList=%s,teamID=%s,hurtType=%s,hurtID=%s" 
+                          % (key, killerDict.keys(), teamID, hurtType, hurtID))
+            return killerDict, killTeam, hurtType, hurtID
         
         hurtType = 0
         hurtID = 0
@@ -4472,16 +4450,16 @@
     #  @param maxHurtObj 最大伤血对象
     #  @return 返回值, 伤血对象
     #  @remarks 获得伤血对象,支持抢怪
-    def __GetTagByHurtObj(self, maxHurtObj, isLog=True):
+    def __GetTagByHurtObj(self, maxHurtObj, isCheckRefreshArea=False):
         #获得死亡的NPC
         curNPC = self.__Instance
         # 伤害的obj类型元组(玩家, 队伍)
         hurtObjTuple = (None, None)
-        #isLog = self.__GetIsLog() and isLog
         if maxHurtObj == None:
             GameWorld.DebugLog("伤血对象错误,npcID=%s" % (curNPC.GetNPCID()))
             return hurtObjTuple
         
+        refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
         #最大伤血类型
         maxHurtValueType = maxHurtObj.GetValueType()
         
@@ -4489,21 +4467,18 @@
             curPlayer = GameWorld.GetObj(maxHurtObj.GetValueID(), IPY_GameWorld.gotPlayer)
             
             if curPlayer == None:
-                #if isLog:
-                #    GameWorld.DebugLog("无法找到玩家,npcID=%s" % (curNPC.GetNPCID()))
                 return hurtObjTuple
             
             #支持抢怪,个人杀死,但自己死亡,不算
-            if curPlayer.GetHP() <= 0 :
-                #if isLog:
-                #    GameWorld.DebugLog("玩家已死亡!playerID=%s" % curPlayer.GetPlayerID())
+            if curPlayer.GetHP() <= 0 or curPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
                 return hurtObjTuple
             
+            if isCheckRefreshArea:
+                if not self.GetIsInRefreshPoint(curPlayer.GetPosX(), curPlayer.GetPosY(), refreshPoint):
+                    return hurtObjTuple
             #如果玩家已经超出指定距离,不加经验
-            if GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(),
+            elif GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(),
                                      curPlayer.GetPosX(), curPlayer.GetPosY()) > ChConfig.Def_Team_GetExpScreenDist:
-                #if isLog:
-                #    GameWorld.DebugLog("玩家已经超出指定距离,npcPos(%s,%s),playerPos(%s,%s)" % (curNPC.GetPosX(), curNPC.GetPosY(), curPlayer.GetPosX(), curPlayer.GetPosY()))
                 return hurtObjTuple
             
             #正常返回
@@ -4515,31 +4490,36 @@
             teamID = maxHurtObj.GetValueID()
             curTeam = GameWorld.GetTeamManager().FindTeam(teamID)
             if curTeam == None:
-                #if isLog:
-                #    GameWorld.Log("该队伍异常不存在!npcID=%s,teamID=%s" % (curNPC.GetNPCID(), teamID))
                 return hurtObjTuple
             
-            #组队成员检查
-            playerlist = PlayerControl.GetAreaTeamMember(curTeam, curNPC.GetPosX(), curNPC.GetPosY())
-            if len(playerlist) == 0 :
-                #所有队伍成员,均超过获得奖励距离,或者全部死亡
+            #遍历队伍,半径为一屏半的距离内的所有队伍/团队成员,可以获得经验
+            for i in xrange(curTeam.GetMemberCount()):
+                curTeamPlayer = curTeam.GetMember(i)
+                if curTeamPlayer == None or curTeamPlayer.GetPlayerID() == 0:
+                    continue
+                
+                if curTeamPlayer.GetHP() <= 0 or curTeamPlayer.GetPlayerAction() == IPY_GameWorld.paDie:
+                    continue
+                
+                if isCheckRefreshArea:
+                    if not self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint):
+                        continue
+                elif GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTeamPlayer.GetPosX(),
+                                       curTeamPlayer.GetPosY()) > ChConfig.Def_Team_GetExpScreenDist:
+                    continue
+                
+                hurtObjTuple = (None, curTeam)
                 return hurtObjTuple
             
-            #正常返回
-            hurtObjTuple = (None, curTeam)
             return hurtObjTuple
             
         #最大伤血对象是NPC,那么一定不给经验(玩家的召唤兽伤血算玩家)
         elif maxHurtValueType == ChConfig.Def_NPCHurtTypeNPC:
-            #if isLog:
-            #    GameWorld.DebugLog("最大伤血对象是NPC...valueID=%s" % maxHurtObj.GetValueID())
             return hurtObjTuple
         
         #异常信息,添加伤血类型错误
         else:
             pass
-            #if isLog:
-            #    GameWorld.Log("异常信息,伤血类型错误 maxHurtValueType = %s" % (maxHurtValueType))
         
         return hurtObjTuple
     
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index 37e353b..20c46dc 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -61,3 +61,5 @@
 
 g_operationActionDict = {} # {actName:actInfo, ...}
 
+g_npcKillerInfo = {} # NPC击杀者信息 {(lineID, objID, npcID):[killerDict, curTeam, hurtType, hurtID], ...}
+

--
Gitblit v1.8.0