From f460b6035d693dd40c361f7c289c5dac2a2a32a1 Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期二, 16 十月 2018 16:30:12 +0800
Subject: [PATCH] 4201 【主干】【后端】新增战斗力参数:移动速度百分比
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py | 469 ++++++++++++++++++++++++++++++++++++++++++----------------
1 files changed, 336 insertions(+), 133 deletions(-)
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..0d7b24c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -52,6 +52,7 @@
import PlayerMagicWeapon
import PlayerBossReborn
import PlayerFairyCeremony
+import FamilyRobBoss
import IpyGameDataPY
import PyGameData
import PlayerTeam
@@ -71,9 +72,10 @@
NPCAttr_ParamDict, # 过程参数公式
NPCAttr_AttrStrengthenList, # 等级成长属性公式
NPCAttr_PlayerCntCoefficient, # 地图人数对应属性额外成长系数 {mapID:{"属性名":{组队进入人数:系数, ...}, ...}, ...}
+NPCAttr_NPCPlayerCntCoefficient, # NPC特殊成长人数对应属性额外成长系数 {npcID:{"属性名":{人数:系数, ...}, ...}, ...}, 优先级大于地图人数系数
NPCAttr_DynNPCLVMap, # 动态等级的地图ID列表,默认已刷新出来的NPC等级不会再变更,下次刷出来的怪物等级变更 [地图ID, ...]
NPCAttr_DynPCCoefficientMap, # 动态人数系数的地图ID {地图ID:是否马上刷新属性, ...}
-) = range(5)
+) = range(6)
#---------------------------------------------------------------------
##NPC初始化->出生调用
@@ -104,6 +106,7 @@
return curNPC.GetLV()
def GetRealmLV(curNPC): return curNPC.GetMAtkMin() # NPC表中此字段含义改成境界等级
+def SetRealmLV(curNPC, realmLV): return curNPC.SetMAtkMin(realmLV) # NPC表中此字段含义改成境界等级
def GetIsLVSuppress(curNPC): return curNPC.GetWindDef() # 风防代表是否等级压制
def GetSuppressFightPower(curNPC): return curNPC.GetThunderDef() # 雷防代表压制战力
def SetSuppressFightPower(curNPC, value): return curNPC.SetThunderDef(value)
@@ -112,6 +115,7 @@
def GetFaction(curNPC): return curNPC.GetCountry()
def GetSkillAtkRate(curNPC): return curNPC.GetPoisionAtk() # 毒攻代表NPC技能伤害加成万分率
def GetFinalHurt(curNPC): return curNPC.GetFireAtk() # 火攻代表NPC最终固定伤害加成, 普攻也有效果
+def SetFinalHurt(curNPC, hurt): return curNPC.SetFireAtk(hurt) # 火攻代表NPC最终固定伤害加成, 普攻也有效果
def GetSkillEnhance(curNPC): return curNPC.GetWindAtk() # 风攻代表NPC 《普攻》 的技能附加伤害固定值
def GetNPCSeries(curNPC): return curNPC.GetPoisionDef() # 毒防字段代表NPC系,按二进制位区分
@@ -137,11 +141,14 @@
gameFB = GameWorld.GetGameFB()
if strengthenIpyData.GetIsStrengthenByPlayerCount():
- strengthenPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)
- if not strengthenPlayerCnt:
- GameWorld.ErrLog("NPC配置了按玩家人数成长类型,但是无法获取到对应的玩家人数!npcID=%s" % (npcID))
- return
-
+ if FamilyRobBoss.IsHorsePetRobBoss(npcID):
+ strengthenPlayerCnt = GameWorld.GetGameWorld().GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_HorsePetRobBossPlayerCount)
+ else:
+ strengthenPlayerCnt = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenPlayerCnt)
+ if not strengthenPlayerCnt:
+ GameWorld.ErrLog("NPC配置了按玩家人数成长类型,但是无法获取到对应的玩家人数!npcID=%s" % (npcID))
+ return
+
lvStrengthenType = strengthenIpyData.GetLVStrengthenType()
# 根据世界等级
if lvStrengthenType == 3:
@@ -153,6 +160,9 @@
elif lvStrengthenType == 1:
strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenAverageLV)
+ if strengthenIpyData.GetCmpNPCBaseLV():
+ strengthenLV = max(strengthenLV, curNPC.GetLV())
+
if lvStrengthenType in [1, 2] and not strengthenLV:
GameWorld.ErrLog("NPC配置了成长等级类型,但是无法获取到对应的成长等级值!npcID=%s,lvStrengthenType=%s" % (npcID, lvStrengthenType))
return
@@ -216,6 +226,7 @@
paramDict = attrStrengthenInfo[NPCAttr_ParamDict] # 过程参数公式字典
attrStrengthenList = attrStrengthenInfo[NPCAttr_AttrStrengthenList] # 属性成长公式字典
playerCntCoefficient = attrStrengthenInfo[NPCAttr_PlayerCntCoefficient] # 人数系数
+ npcIDPlayerCntCoefficient = attrStrengthenInfo[NPCAttr_NPCPlayerCntCoefficient] # 特殊NPC人数系数
baseMaxHP = npcData.GetHPEx() * ShareDefine.Def_PerPointValue + npcData.GetHP()
if strengthenLV:
@@ -293,6 +304,8 @@
playerCntAttrCoefficient = playerCntCoefficient.get(mapID, {})
if not playerCntAttrCoefficient and dataMapID in playerCntCoefficient:
playerCntAttrCoefficient = playerCntCoefficient[dataMapID]
+ if npcID in npcIDPlayerCntCoefficient:
+ playerCntAttrCoefficient = npcIDPlayerCntCoefficient[npcID]
for attrKey, coefficientDict in playerCntAttrCoefficient.items():
if attrKey in attrDict:
attrValue = attrDict[attrKey]
@@ -822,13 +835,28 @@
tagPlaceSortList.sort() # 升序排序
tagPlaceSortList2.sort() # 升序排序
if isKillCountDropEquipEx:
- GameWorld.DebugLog("都不满足目标装备的优先级信息: npcID=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, tagPlaceSortList), playerID)
- GameWorld.DebugLog("部分满足目标装备的优先级信息: npcID=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, tagPlaceSortList2), playerID)
- tagPlaceSortList += tagPlaceSortList2
- if tagPlaceSortList:
- tagPlace = tagPlaceSortList[0][-2]
- tagJob = tagPlaceSortList[0][-1]
-
+ GameWorld.DebugLog("都不满足目标装备的优先级信息: npcID=%s, 数量=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, len(tagPlaceSortList), tagPlaceSortList), playerID)
+ GameWorld.DebugLog("部分满足目标装备的优先级信息: npcID=%s, 数量=%s, 颜色,阶,星,评分,部位,职业=%s" % (npcID, len(tagPlaceSortList2), tagPlaceSortList2), playerID)
+ if tagPlaceSortList or tagPlaceSortList2:
+ isOptimalPlace = IpyGameDataPY.GetFuncCfg("DropEquipPlaceMode", 1) # 是否取最优解部位
+ if isOptimalPlace:
+ tagPlaceSortList += tagPlaceSortList2
+ if tagPlaceSortList:
+ tagPlace = tagPlaceSortList[0][-2]
+ tagJob = tagPlaceSortList[0][-1]
+ GameWorld.DebugLog("掉落目标部位取最优解: tagPlace=%s,tagJob=%s" % (tagPlace, tagJob), playerID)
+ else:
+ randPlaceCountLimit = IpyGameDataPY.GetFuncCfg("DropEquipPlaceMode", 2) # 全不满足目标条件部位有几个时才优先随机
+ if len(tagPlaceSortList) < randPlaceCountLimit:
+ tagPlaceSortList += tagPlaceSortList2
+ else:
+ GameWorld.DebugLog("优先随机都不满足目标装备的,randPlaceCountLimit=%s" % randPlaceCountLimit, playerID)
+ randPlaceIndex = random.randint(0, len(tagPlaceSortList) - 1)
+ GameWorld.DebugLog("掉落目标部位随机, randPlaceIndex=%s, 颜色,阶,星,评分,部位,职业=%s" % (randPlaceIndex, tagPlaceSortList), playerID)
+ tagPlace = tagPlaceSortList[randPlaceIndex][-2]
+ tagJob = tagPlaceSortList[randPlaceIndex][-1]
+ GameWorld.DebugLog("掉落目标部位随机不满足条件的: tagPlace=%s,tagJob=%s" % (tagPlace, tagJob), playerID)
+
if isKillCountDropEquipEx:
GameWorld.DebugLog("附加掉落指定目标装备信息: npcID=%s,玩家最少的击杀次数=%s,目标击杀数=%s,tagClassLV=%s,tagColor=%s,tagStar=%s,tagStarMin=%s,tagPlace=%s,tagJob=%s"
% (npcID, dropEquipExKillCount, tagKillCount, tagClassLV, tagColor, tagStar, tagStarMin, tagPlace, tagJob), playerID)
@@ -1080,12 +1108,18 @@
if len(jobItemList) < job:
GameWorld.ErrLog("职业物品集合key没有配置对应职业ID: npcID=%s,jobItemKey=%s,job=%s" % (npcID, jobItemKey, job))
continue
+ mustDropCount = dropRate / Def_NPCMaxDropRate
+ dropRate = dropRate % Def_NPCMaxDropRate # 基础概率
+ canDropCount = mustDropCount
doCnt = ItemKeyMaxDropCountDict.get(jobItemKey, 1) # 默认1个
doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)
for _ in xrange(doCnt):
if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):
continue
- jobItemID = jobItemList[job - 1]
+ canDropCount += 1
+
+ jobItemID = jobItemList[job - 1]
+ for _ in xrange(canDropCount):
dropItemIDList.append(jobItemID)
#GameWorld.DebugLog("掉落自身职业指定物品ID: jobItemKey=%s,jobItemID=%s" % (jobItemKey, jobItemID))
@@ -1102,11 +1136,17 @@
# 在只掉本职业里的不处理
if jobItemKey in ItemKeyDropRateJobDict:
continue
+ mustDropCount = dropRate / Def_NPCMaxDropRate
+ dropRate = dropRate % Def_NPCMaxDropRate # 基础概率
+ canDropCount = mustDropCount
doCnt = ItemKeyMaxDropCountDict.get(jobItemKey, 1) # 默认1个
doCnt = __GetNPCDropDoCountChange(doCnt, doCountRate, doCountAdd)
for _ in xrange(doCnt):
if not GameWorld.CanHappen(dropRate, maxRate=Def_NPCMaxDropRate):
continue
+ canDropCount += 1
+
+ for _ in xrange(canDropCount):
randJobItemID = random.choice(jobItemList)
dropItemIDList.append(randJobItemID)
#GameWorld.DebugLog("掉落随机职业指定物品ID: jobItemKey=%s,randJobItemID=%s" % (jobItemKey, randJobItemID))
@@ -1175,6 +1215,48 @@
msgInfo = str([itemID, updKilledCnt])
GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "GlobalDropRate", msgInfo, len(msgInfo))
+ # 4. 指定全服击杀次数必掉,算额外掉落
+ globalKillDropDict = IpyGameDataPY.GetFuncEvalCfg("GlobalDropCD", 2) # {NPCID:{击杀次数:[是否本职业, [物品ID, ...], [随机物品ID, ...]]}, ...}
+ if npcID in globalKillDropDict:
+ killCountDropDict = globalKillDropDict[npcID]
+ updNPCKilledCount = min(gw.GetGameWorldDictByKey(ShareDefine.Def_Notify_WorldKey_NPCKilledCount % npcID) + 1, ShareDefine.Def_UpperLimit_DWord)
+ GameWorld.DebugLog("更新全服击杀次数: %s" % updNPCKilledCount)
+ # 通知GameServer记录
+ msgInfo = str([npcID, updNPCKilledCount])
+ GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, "GlobalKillCount", msgInfo, len(msgInfo))
+ if updNPCKilledCount in killCountDropDict:
+ isJobLimit, itemIDList, randItemIDList = killCountDropDict[updNPCKilledCount]
+ for itemID in itemIDList:
+ if isJobLimit:
+ itemData = GameWorld.GetGameData().GetItemByTypeID(itemID)
+ if not itemData:
+ continue
+ itemJob = itemData.GetJobLimit() / 100
+ if itemJob and itemJob != curPlayer.GetJob():
+ # 非本职业可用,不掉落
+ GameWorld.DebugLog("全服击杀次数必掉,非本职业可用,不掉落! itemID=%s" % itemID)
+ continue
+ dropItemIDList.append(itemID)
+ GameWorld.DebugLog("全服击杀次数必掉物品: itemID=%s" % itemID)
+ if randItemIDList:
+ if isJobLimit:
+ randJobItemList = []
+ for rItemID in randItemIDList:
+ itemData = GameWorld.GetGameData().GetItemByTypeID(rItemID)
+ if not itemData:
+ continue
+ itemJob = itemData.GetJobLimit() / 100
+ if itemJob and itemJob != curPlayer.GetJob():
+ # 非本职业可用,不掉落
+ GameWorld.DebugLog("全服击杀次数必掉随机,非本职业可用,不掉落! rItemID=%s" % rItemID)
+ continue
+ randJobItemList.append(rItemID)
+ randItemID = random.choice(randJobItemList)
+ else:
+ randItemID = random.choice(randItemIDList)
+ dropItemIDList.append(randItemID)
+ GameWorld.DebugLog("全服击杀次数必掉随机物品: randItemID=%s" % randItemID)
+
return dropItemIDList
def __GetEquipIDList(npcID, classLV, color, placeList, star, itemJobList, tagPlace=None):
@@ -1917,11 +1999,15 @@
#因为存在boss分流,所以用gameFB字典,但是存活状态还是用GameWorld字典
GameWorld.GetGameFB().SetGameFBDict(ChConfig.Map_NPC_WorldBossDeadTick % npcid, GameWorld.GetGameWorld().GetTick())
+ if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
+ FamilyRobBoss.ClearFamilyOwnerBossHurt(curNPC)
+ ChNPC.OnNPCSetDead(curNPC)
+
# 清除队伍成员伤血列表
AttackCommon.ClearTeamPlayerHurtValue(curNPC)
# 清除自定义伤血列表
- BossHurtMng.ClearHurtValueList(curNPC)
+ #BossHurtMng.ClearHurtValueList(curNPC)
# C++设置npc死亡
curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason),
@@ -1955,6 +2041,9 @@
self.__Killer = None # 击杀者, 由各种规则得出, 一般也是物品归属的代表, 用于广播、记录等确保与归属一致
self.__AllKillerDict = {} # 所有击杀的玩家ID对应字典, 非队伍, 一般也是归属的拥有者
self.__FeelPlayerList = [] # 所有摸怪玩家列表,处理任务及某些逻辑用
+
+ self.__OwnerHurtType = 0
+ self.__OwnerHurtID = 0
return
#---------------------------------------------------------------------
## 移动到某一个点的附近点
@@ -2485,7 +2574,7 @@
self.__AddAngryValue(npcAngry, curObjID, curObjType, plusAngryValue, canPile)
#激活呆滞的NPC
- if curNPC.GetHP() > 0 and not curNPC.GetIsNeedProcess() :
+ if GameObj.GetHP(curNPC) > 0 and not curNPC.GetIsNeedProcess() :
curNPC.SetIsNeedProcess(True)
@@ -2789,11 +2878,18 @@
# 这种情况一般是玩家未加入队伍前对该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
def __GetTeamHurtNPCPlayerIDList(self, refreshPoint, teamID, tick):
+ curNPC = self.__Instance
teamHurtPlayerIDList = []
# 如果没有在线队员在有效范围内,则进一步判断离线队员是否有伤血保护中的
playerMgr = GameWorld.GetPlayerManager()
@@ -2806,8 +2902,16 @@
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):
+ if self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
+ and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False):
#GameWorld.DebugLog("有队员在boss范围内,保留队伍伤血!teamID=%s,playerID=%s" % (teamID, curTeamPlayer.GetPlayerID()))
teamHurtPlayerIDList.append(playerID)
else:
@@ -2945,7 +3049,7 @@
#获得伤血对象
hurtObj = npcHurtList.GetHurtAt(index)
- curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, False)
+ curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, True)
if curPlayer or curTeam:
return hurtObj
@@ -2996,10 +3100,13 @@
curNPC = self.__Instance
#清除状态
self.__ClearNPCAllState(False)
- #初始化召唤兽
- self.__InitNPCSummon()
- #重置技能CD
- self.__NormalNPCInItCD()
+ #只在重生或者满血的状态下才重置以下内容
+ if isReborn or GameObj.GetHP(curNPC) >= GameObj.GetMaxHP(curNPC):
+ #初始化召唤兽
+ self.__InitNPCSummon()
+ #重置技能CD
+ self.__NormalNPCInItCD()
+
#重刷属性
self.RefreshNPCState(isReborn=isReborn)
#通知血量, 复活的情况不通知血量,由NPC出现包通知
@@ -3317,6 +3424,9 @@
GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(0, 0, 0, 'GameWorldBossState',
'%s' % (msgList), len(str(msgList)))
+ if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
+ FamilyRobBoss.FamilyOwnerBossOnReborn(curNPC)
+
# 检查是否有光环, 在重生时处理,不然可能导致有些无战斗逻辑的怪物无法套上光环buff
skillManager = curNPC.GetSkillManager()
for index in xrange(skillManager.GetSkillCount()):
@@ -3694,7 +3804,7 @@
#=====================================================================================================
#boss伤血排行榜击杀逻辑
- BossHurtMng.BossOnKilled(curNPC)
+ #BossHurtMng.BossOnKilled(curNPC)
#掉落需要用到摸怪,所以在处理掉落奖励之前设置
self.__SetFeelNPCPlayerList()
@@ -3710,6 +3820,8 @@
# 记录boss击杀信息的NPC
bossIpyData = IpyGameDataPY.GetIpyGameDataListNotLog('BOSSInfo', npcID)
if bossIpyData:
+ if GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
+ killerName = FamilyRobBoss.FamilyOwnerBossOnKilled(curNPC, self.__OwnerHurtID)
#KillerJob = 0 if not self.__Killer else self.__Killer.GetJob()
GameServer_KillGameWorldBoss(curNPC.GetNPCID(), killerName, 0)
#===========================================================================================
@@ -4149,56 +4261,15 @@
# @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.__OwnerHurtType, self.__OwnerHurtID = hurtType, hurtID
+ isGameBoss = ChConfig.IsGameBoss(curNPC)
+
#最后一击处理
self.__DoLastTimeHurtLogic()
@@ -4228,9 +4299,19 @@
elif curTeam != None:
self.__KilledByTeamSetPrize(curTeam, hurtType, hurtID)
- else:
- GameWorld.ErrLog("NPC归属异常:npcID=%s,hurtType=%s,hurtID=%s" % (npcID, hurtType, hurtID))
+ #被仙盟杀死
+ elif hurtType == ChConfig.Def_NPCHurtTypeFamily:
+ self.__KilledByFamilySetPrize(hurtType, hurtID)
+ elif isGameBoss:
+ GameWorld.ErrLog("NPC归属异常:npcID=%s,hurtType=%s,hurtID=%s" % (npcID, hurtType, hurtID))
+
+ if isGameBoss:
+ dataDict = {"objID":curNPC.GetID(), "bossID":npcID, "mapID":GameWorld.GetMap().GetMapID(),
+ "lineID":GameWorld.GetGameWorld().GetLineID(), "teamID":curTeam.GetTeamID() if curTeam else 0,
+ "killerID":self.__AllKillerDict.keys(), "hurtType":hurtType,"hurtID":hurtID}
+ DataRecordPack.SendEventPack("KillBossRecord", dataDict)
+
if OnNPCDie:
OnNPCDie(curNPC, hurtType, hurtID)
@@ -4299,6 +4380,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 +4561,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 +4578,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 +4601,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
@@ -4612,7 +4703,60 @@
self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
#GameWorld.Log("队伍杀死怪物奖励,逻辑成功结束")
return
-
+
+ def __KilledByFamilySetPrize(self, hurtType, hurtID):
+ ## 仙盟杀死NPC奖励逻辑
+ curNPC = self.__Instance
+
+ maxLV = 0
+ dropPlayer = None
+ ownerPlayerList = []
+ refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
+ copyPlayerMgr = GameWorld.GetMapCopyPlayerManager()
+ for index in xrange(copyPlayerMgr.GetPlayerCount()):
+ player = copyPlayerMgr.GetPlayerByIndex(index)
+ if not player:
+ continue
+
+ if player.GetFamilyID() != hurtID or not self.GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
+ continue
+
+ curPlayerLV = player.GetLV()
+ if maxLV < curPlayerLV:
+ maxLV = curPlayerLV
+ dropPlayer = player
+ ownerPlayerList.append(player)
+
+ if not ownerPlayerList:
+ GameWorld.Log("奖励归属仙盟,但是不存在可获得该奖励的成员!npcID=%s,hurtType=%s,hurtID=%s"
+ % (curNPC.GetNPCID(), hurtType, hurtID))
+
+ # 因为仙盟归属boss归属伤血第一的仙盟,仙盟伤血有保护,可能存在伤血第一仙盟在boss死亡的时候都不在
+ # 此时掉落计算玩家算最后一击玩家,归属还是算伤血第一仙盟的
+ if not dropPlayer:
+ dropPlayer = self.__LastHurtPlayer
+
+ if not dropPlayer:
+ GameWorld.ErrLog("奖励归属仙盟,找不到掉落玩家!npcID=%s,hurtType=%s,hurtID=%s"
+ % (curNPC.GetNPCID(), hurtType, hurtID))
+ return
+
+ # 赶时间,先简单处理直接取最大等级的,之后可按实际情况来
+ if not self.__LastHurtPlayer:
+ self.__LastHurtPlayer = dropPlayer
+ if not self.__MaxHurtPlayer:
+ self.__MaxHurtPlayer = dropPlayer
+ if not self.__Killer:
+ self.__Killer = dropPlayer
+ maxHurtID = dropPlayer.GetPlayerID()
+
+ for curPlayer in ownerPlayerList:
+ self.__KillNPCFuncEx(curPlayer, curNPC, maxHurtID, False)
+
+ #调用物品掉落
+ self.__NPCDropItem(dropPlayer, hurtType, hurtID, ownerPlayerList)
+ return
+
## 队伍或自己击杀NPC扩展功能
# @param curPlayer
# @return None
@@ -4629,7 +4773,10 @@
#掉落归属
if mapFBType != IPY_GameWorld.fbtNull:
FBLogic.DoFB_DropOwner(curPlayer , curNPC)
-
+ else:
+ if curNPC.GetLV()>=curPlayer.GetLV() - IpyGameDataPY.GetFuncCfg('DailyQuestKillMonster'):
+ PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_KillNPC)
+
killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
if limitIndex != None:
@@ -4643,13 +4790,11 @@
dataDict = {"objID":curNPC.GetID(), "bossID":npcID, "touchCnt":newCnt,
"AccID":curPlayer.GetAccID(), "PlayerID":curPlayer.GetPlayerID()}
DataRecordPack.SendEventPack("AddKillBossCnt", dataDict, curPlayer)
-
if limitIndex == 0:
# 世界BOSS击杀成就
PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillWorldBoss, 1)
# 每日活动
PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_WorldBOSS)
- PlayerMagicWeapon.SetMWPrivilegeData(curPlayer, ChConfig.MWPrivilege_KillBossAddAttr, 1, True)
PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_WorldBOSS, 1)
PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_WorldBoss, 1)
elif limitIndex == 1: #BOSS之家
@@ -4659,8 +4804,8 @@
PlayerActivity.AddDailyActionFinishCnt(curPlayer, ShareDefine.DailyActionID_BOSSHome)
PlayerBossReborn.AddBossRebornActionCnt(curPlayer, ChConfig.Def_BRAct_BOSSHome, 1)
PlayerFairyCeremony.AddFCPartyActionCnt(curPlayer, ChConfig.Def_PPAct_BossHome, 1)
- #击杀特定NPC成就
- PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, 1, [npcID])
+
+
return
#---------------------------------------------------------------------
@@ -4682,10 +4827,10 @@
#不是普通NPC
elif npcObjType != IPY_GameWorld.gnotNormal:
return
-
+ npcID = curNPC.GetNPCID()
#GameWorld.DebugLog("__MissionOnKillNPC isFeel=%s" % (isFeel), curPlayer.GetPlayerID())
killBossCntLimitDict = IpyGameDataPY.GetFuncCfg('KillBossCntLimit', 1)
- limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, curNPC.GetNPCID())
+ limitIndex = GameWorld.GetDictValueByKey(killBossCntLimitDict, npcID)
isWorldBoos = limitIndex == 0
if isFeel:
#击杀NPC触发摸怪任务事件
@@ -4697,7 +4842,8 @@
EventShell.EventRespons_OnKillById(curPlayer, curNPC)
if isWorldBoos:
EventShell.EventRespons_KillWorldBoss(curPlayer)
-
+ #击杀特定NPC成就
+ PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_KillSpecificNPC, 1, [npcID])
return
def __GetIsLog(self):
@@ -4867,7 +5013,7 @@
return max(value / pow(10, nlen), 1)
-Def_CollNPCCfg_Len = 9
+Def_CollNPCCfg_Len = 10
(
Def_CollNPCCfg_CanTogether, # 是否允许同时采集
Def_CollNPCCfg_SysMsgMark, # 不可同时采集提示
@@ -4878,6 +5024,7 @@
Def_CollNPCCfg_ZhenQi, # 获得的真气/魔魂
Def_CollNPCCfg_GiveItemModeID, # 获得的物品信息模板编号
Def_CollNPCCfg_NotCostItemNotify, # 消耗品不足提示
+Def_CollNPCCfg_LimitSysMsgMark, #采集上限提示
) = range(Def_CollNPCCfg_Len)
@@ -4952,7 +5099,8 @@
GameWorld.DebugLog(" maxTime=%s,todayTime=%s" % (limitMaxTime, todayCollTime))
if limitMaxTime > 0 and todayCollTime >= limitMaxTime:
- PlayerControl.NotifyCode(curPlayer, "GeRen_liubo_807125")
+
+ PlayerControl.NotifyCode(curPlayer, collectNPCInfo[Def_CollNPCCfg_LimitSysMsgMark], [limitMaxTime])
return True
# 采集消耗
@@ -4992,7 +5140,7 @@
PlayerControl.Sync_PrepareBegin(curPlayer, prepareTime, IPY_GameWorld.pstMissionCollecting, \
prepareID=curNPC.GetID())
-
+ FBLogic.OnBeginCollect(curPlayer, curNPC)
##添加这个NPC的伤血列表,用于判断可否同时采集,改为字典判断
AttackCommon.AddHurtValue(curNPC, curPlayer.GetPlayerID(), ChConfig.Def_NPCHurtTypePlayer, 1)
return
@@ -5244,7 +5392,8 @@
PlayerControl.NomalDictSetProperty(curPlayer, ChConfig.Def_PDict_CollNpcIDCollTime % npcID, updCollTime)
SyncCollNPCTime(curPlayer, npcIDList=[npcID])
GameWorld.DebugLog(" 增加当日采集次数: todayCollTime=%s,updCollTime=%s" % (todayCollTime, updCollTime))
-
+ #采集成就
+ PlayerSuccess.DoAddSuccessProgress(curPlayer, ShareDefine.SuccType_Collect, successCnt, [npcID])
SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, giveItemInfoList, npcID)
#DataRecordPack.DR_CollectNPCOK(curPlayer, npcID, addMoney, addExp, addZhenQi, giveItemInfoList)
return True
@@ -5303,44 +5452,45 @@
GameWorld.DebugLog(" 最终可得到物品giveItemInfoList=%s" % giveItemInfoList)
syncItemInfoList = [] # 同步的采集到的物品信息列表
- for itemType, itemID, itemCnt, isBind in giveItemInfoList:
+ for itemID, itemCnt, isBind in giveItemInfoList:
if not ItemCommon.CheckPackHasSpace(curPlayer, IPY_GameWorld.rptItem):
break
isBind = setBind or isBind
- if itemType == 0:
- getItemObj = ItemControler.GetOutPutItemObj(itemID)
- elif itemType == 1:
- itemDictData = ItemControler.GetAppointItemDictData(itemID, isBind)
- getItemObj = ItemControler.GetItemByData(itemDictData)
- elif itemType == 2:
- quality = ItemCommon.GetRandEquipQualityByTable(itemID, "CollectEquipRandQuality")
- if quality == 0:
- isBroadcast = False
- getItemObj = ItemCommon.RandNormalEquip(curPlayer, itemID, isBind, "CollectNormalEquip")
- else:
- getItemObj, isBroadcast = ItemCommon.RandGreateEquip(curPlayer, itemID, isBind, "CollectGreateEquip", quality)
- if getItemObj == None:
- continue
-
- itemID = getItemObj.GetItemTypeID()
+
+ getItemObj = ItemControler.GetOutPutItemObj(itemID)
+# elif itemType == 1:
+# itemDictData = ItemControler.GetAppointItemDictData(itemID, isBind)
+# getItemObj = ItemControler.GetItemByData(itemDictData)
+# elif itemType == 2:
+# quality = ItemCommon.GetRandEquipQualityByTable(itemID, "CollectEquipRandQuality")
+# if quality == 0:
+# isBroadcast = False
+# getItemObj = ItemCommon.RandNormalEquip(curPlayer, itemID, isBind, "CollectNormalEquip")
+# else:
+# getItemObj, isBroadcast = ItemCommon.RandGreateEquip(curPlayer, itemID, isBind, "CollectGreateEquip", quality)
+# if getItemObj == None:
+# continue
+#
+# itemID = getItemObj.GetItemTypeID()
userData = getItemObj.GetUserData()
getItemObj.SetCount(itemCnt)
getItemObj.SetIsBind(isBind)
ItemCommon.NotifyItemDropByKill(curPlayer, getItemObj, npcID)
- SendGameServerGoodItemRecord(mapID, npcID, curPlayer.GetPlayerName(), curPlayer.GetPlayerID(), itemID)
+ #SendGameServerGoodItemRecord(mapID, npcID, curPlayer.GetPlayerName(), curPlayer.GetPlayerID(), itemID)
#可以放入背包
if not ItemControler.DoLogic_PutItemInPack(curPlayer, getItemObj, True, True,
event=["CollectNPC", False, {"npcID":npcID}]):
break
- syncItemInfoList.append([itemType, itemID, itemCnt, isBind, userData])
+ syncItemInfoList.append([itemID, itemCnt, isBind, userData])
return syncItemInfoList
## 采集结果同步
# @param None
# @param None
def SyncCollectionItemInfo(curPlayer, addExp, addMoney, addZhenQi, syncItemInfoList, collectNPCID=0):
+ return #暂不同步
if addExp <= 0 and addMoney <= 0 and addZhenQi <= 0 and not syncItemInfoList:
return
@@ -5428,15 +5578,15 @@
collectNPCIDTimeLimit = ReadChConfig.GetEvalChConfig('CollectNPCIDTimeLimit')
npcIDList = collectNPCIDTimeLimit.keys()
- if funcTypeList:
- collection = ChPyNetSendPack.tagMCFuncNPCCollectionCnt()
- for fType in funcTypeList:
- todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcCollTime % fType)
- collection.Clear()
- collection.FuncType = fType
- collection.CollectionCnt = todayCollTime
- collection.BuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcBuyTime % fType)
- NetPackCommon.SendFakePack(curPlayer, collection)
+# if funcTypeList:
+# collection = ChPyNetSendPack.tagMCFuncNPCCollectionCnt()
+# for fType in funcTypeList:
+# todayCollTime = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcCollTime % fType)
+# collection.Clear()
+# collection.FuncType = fType
+# collection.CollectionCnt = todayCollTime
+# collection.BuyCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_PDict_CollNpcBuyTime % fType)
+# NetPackCommon.SendFakePack(curPlayer, collection)
if npcIDList:
npcIDCollInfo = ChPyNetSendPack.tagMCNPCIDCollectionCntInfo()
@@ -5551,6 +5701,59 @@
NetPackCommon.SendFakePack(curPlayer, npcInfoPack)
return
+
+## 获取本地图NPC数量
+# @param queryNPCIDList:查询的NPCID列表
+# @param tick
+# @return {NPCID:cnt}
+def GetNPCCntInfo(queryNPCIDList, tick):
+ npcCntDict = {}
+
+ if not queryNPCIDList:
+ return npcCntDict
+
+ gameNPCManager = GameWorld.GetNPCManager()
+ GameWorld.DebugLog("GetNPCCntInfo...queryNPCIDList=%s" % (str(queryNPCIDList)))
+
+ for index in xrange(gameNPCManager.GetNPCCount()):
+ curNPC = gameNPCManager.GetNPCByIndex(index)
+ curID = curNPC.GetID()
+ if curID == 0:
+ continue
+
+ curNPCID = curNPC.GetNPCID()
+
+ if curNPCID not in queryNPCIDList:
+ continue
+ if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
+ continue
+ npcCntDict[curNPCID] = npcCntDict.get(curNPCID, 0) + 1
+
+ GameWorld.DebugLog(" npcCntDict=%s" % (str(npcCntDict)))
+ return npcCntDict
+
+## 同步地图NPC数量信息
+# @param curPlayer:采集玩家实例
+# @param mapID:
+# @param npcInfoDict:
+# @return None
+def SyncNPCCntInfo(curPlayer, mapID, npcCntDict):
+ npcInfoPack = ChPyNetSendPack.tagMCNPCCntList()
+ npcInfoPack.Clear()
+ npcInfoPack.MapID = mapID
+ npcInfoPack.NPCInfoList = []
+
+ for npcid, npcCnt in npcCntDict.items():
+ npcInfo = ChPyNetSendPack.tagMCNPCCntInfo()
+ npcInfo.Clear()
+ npcInfo.NPCID = npcid
+ npcInfo.Cnt = npcCnt
+ npcInfoPack.NPCInfoList.append(npcInfo)
+
+ npcInfoPack.NPCInfoCnt = len(npcInfoPack.NPCInfoList)
+ NetPackCommon.SendFakePack(curPlayer, npcInfoPack)
+ return
+
def SendGameServerGoodItemRecord(mapID, npcID, playerName, playerID, itemID, equipInfo=[]):
# @param equipInfo: [equipPlace, itemClassLV, itemColor, itemQuality, itemUserData]
# GameWorld.DebugLog("检查物品是否发送GameServer: mapID=%s, npcID=%s, playerName=%s, itemID=%s"
--
Gitblit v1.8.0