From bd61f5e92fad5dc02f693747fde8fdb86ee01c5c Mon Sep 17 00:00:00 2001
From: hxp <ale99527@vip.qq.com>
Date: 星期五, 06 十二月 2019 20:46:52 +0800
Subject: [PATCH] 8346 【恺英】【后端】协助系统(初版,可完成协助完整流程,增加新NPC伤血管理,支持协助、支持超过20亿伤害)
---
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtManager.py | 953 +++++++++++++++++++++++
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerAssist.py | 668 ++++++++++++++++
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetWorldPos.py | 3
ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Assist.py | 59 +
ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py | 3
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py | 23
ServerPython/CoreServerGroup/GameServer/PyNetPack.ini | 23
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py | 10
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py | 3
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py | 11
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAssist.py | 151 +++
ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py | 18
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTeam.py | 15
ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py | 14
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py | 21
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py | 23
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py | 34
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini | 16
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py | 338 -------
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_PlayerAssist.py | 51 +
ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTeam.py | 10
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/NormalNPC_Attack_Player.py | 2
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py | 7
ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py | 2
25 files changed, 2,113 insertions(+), 347 deletions(-)
diff --git a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
index a05a72c..06be58e 100644
--- a/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
+++ b/ServerPython/CoreServerGroup/GameServer/PyNetPack.ini
@@ -390,6 +390,29 @@
PacketSubCMD_3=0x03
PacketCallFunc_3=OnQueryXMZZInfo
+[PlayerAssist]
+ScriptName = Player\PlayerAssist.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 4
+
+PacketCMD_1=0xB0
+PacketSubCMD_1=0x12
+PacketCallFunc_1=OnStartAssistBoss
+
+PacketCMD_2=0xB0
+PacketSubCMD_2=0x13
+PacketCallFunc_2=OnCancelAssistBoss
+
+PacketCMD_3=0xB0
+PacketSubCMD_3=0x14
+PacketCallFunc_3=OnUseAssistThanksGift
+
+PacketCMD_4=0xB0
+PacketSubCMD_4=0x15
+PacketCallFunc_4=OnGetAssistThanksGift
+
[PlayerTalk]
ScriptName = Player\PlayerTalk.py
Writer = alee
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Assist.py b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Assist.py
new file mode 100644
index 0000000..d9ead76
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/GM/Commands/Assist.py
@@ -0,0 +1,59 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package GM.Commands.Assist
+#
+# @todo:显示当前协助列表
+# @author hxp
+# @date 2019-12-06
+# @version 1.0
+#
+# 详细描述: 显示当前协助列表
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-12-06 21:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyDataManager
+
+#---------------------------------------------------------------------
+#全局变量
+#---------------------------------------------------------------------
+
+#---------------------------------------------------------------------
+#逻辑实现
+## 执行逻辑
+# @param curPlayer 当前玩家
+# @param gmList [cmdIndex gmAccID msg]
+# @return None
+# @remarks 函数详细说明.
+def OnExec(curPlayer, gmList):
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ GameWorld.Log("---------- 当前总协助条数: %s" % len(assistMgr.allAssistDict))
+ for assist in assistMgr.allAssistDict.values():
+ GameWorld.DebugLog("%s" % assist.outputString())
+ GameWorld.DebugLog("IsSaveDB=%s,ObjID=%s,AssistType=%s,AssistPlayerIDList=%s" % (assist.IsSaveDB, assist.ObjID, assist.AssistType, assist.AssistPlayerIDList))
+ GameWorld.DebugLog("--- ")
+
+ GameWorld.DebugLog("--- ")
+ for familyID, assistList in assistMgr.familyAssistDict.items():
+ GameWorld.DebugLog("仙盟协助列表: %s, 条数: %s" % (familyID, len(assistList)))
+ for assist in assistList:
+ GameWorld.DebugLog(" %s" % assist.GUID)
+
+ GameWorld.DebugLog("--- ")
+ for playerID, assistList in assistMgr.playerNoSaveDBAssistDict.items():
+ GameWorld.DebugLog("玩家协助列表: %s, 条数: %s" % (playerID, len(assistList)))
+ for assist in assistList:
+ GameWorld.DebugLog(" %s" % assist.GUID)
+
+ GameWorld.DebugLog("--- ")
+ for playerID, assist in assistMgr.playerAssistingDict.items():
+ GameWorld.DebugLog("玩家协助中的: %s, %s" % (playerID, assist.GUID))
+
+ GameWorld.DebugLog("-----------------------------------------")
+ return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
index 34b1463..94b3cbf 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/ChPlayer.py
@@ -62,6 +62,7 @@
import IPY_PlayerDefine
import CrossRealmPK
import AuctionHouse
+import PlayerAssist
import PlayerFB
#---------------------------------------------------------------------
@@ -189,7 +190,14 @@
PlayerZhuXianBoss.OnPlayerLogin(curPlayer)
#骑宠boss状态通知
PlayerHorsePetBoss.OnLogin(curPlayer)
+ #协助
+ PlayerAssist.OnPlayerLogin(curPlayer, False)
GMT_CTG.OnPlayerLogin(curPlayer)
+
+ else:
+ #协助
+ PlayerAssist.OnPlayerLogin(curPlayer, True)
+
return
def __UpdOnedayJobPlayerLoginoffTime(curPlayer):
@@ -542,6 +550,8 @@
SetPlayerOfflineTime(curPlayer)
#拍卖行
AuctionHouse.OnPlayerLeaveServer(curPlayer)
+ #协助
+ PlayerAssist.OnLeaveServer(curPlayer)
#------------镖车逻辑
#TruckPlayerDisconnectProcess(curPlayer, tick)
@@ -645,6 +655,14 @@
PlayerTeam.SetTeamCheckState(curPlayer, packValue)
return
+ #if packType == IPY_GameServer.CDBPlayerRefresh_ExAttr1:
+ # PlayerControl.SetAssistTagPlayerID(curPlayer, packValue)
+ # return
+
+ if packType == IPY_GameServer.CDBPlayerRefresh_ExAttr3:
+ PlayerControl.SetFBFuncLineID(curPlayer, packValue)
+ return
+
#---常规逻辑处理---
elif packType == IPY_GameServer.CDBPlayerRefresh_LV:
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerAssist.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerAssist.py
new file mode 100644
index 0000000..91db9e4
--- /dev/null
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerAssist.py
@@ -0,0 +1,668 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerAssist
+#
+# @todo:协助系统
+# @author hxp
+# @date 2019-12-06
+# @version 1.0
+#
+# 详细描述: 协助系统
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-12-06 21:00"""
+#-------------------------------------------------------------------------------
+
+import PyDataManager
+import NetPackCommon
+import PyGameDataStruct
+import ChPyNetSendPack
+import PlayerControl
+import PlayerFamily
+import ShareDefine
+import PlayerTeam
+import GameWorld
+import ChConfig
+
+import uuid
+
+# 协助类型
+(
+AssistType_Unknown,
+AssistType_Boss, # boss
+AssistType_TeamFB, # 组队副本
+) = range(3)
+
+
+def OnPlayerLogin(curPlayer, isTJ=False):
+ ## 玩家上线
+ # @param isTJ: 是否脱机上线
+
+ familyID = curPlayer.GetFamilyID()
+ playerID = curPlayer.GetPlayerID()
+ if not familyID:
+ return
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID in assistMgr.playerNoSaveDBAssistDict:
+ playerNoSaveList = assistMgr.playerNoSaveDBAssistDict[playerID]
+
+ # 非脱机上线
+ if not isTJ:
+ GameWorld.DebugLog("玩家上线,恢复协助发布到仙盟列表!", playerID)
+ if familyID not in assistMgr.familyAssistDict:
+ assistMgr.familyAssistDict[familyID] = []
+ recoverList = []
+ familyAssistList = assistMgr.familyAssistDict[familyID]
+ for assistObj in playerNoSaveList:
+ familyAssistList.append(assistObj)
+ recoverList.append(assistObj)
+ GameWorld.DebugLog(" 恢复: %s" % assistObj.GUID)
+
+ if recoverList:
+ # 通知本盟其他玩家
+ PlayerFamily.SendFamilyFakePack(familyID, GetAssistInfoListPack(recoverList), [playerID])
+
+ # 脱机上线
+ else:
+ GameWorld.DebugLog("玩家脱机上线,强制取消发布的非存库协助!", playerID)
+ for assistObj in playerNoSaveList:
+ OnCancelPlayerRequestAssist(assistObj, "TJGLogin", True)
+
+ if not isTJ:
+ SyncFamilyAssist(curPlayer)
+
+ # 没有协助中的信息
+ if playerID in assistMgr.playerAssistingDict:
+ assistObj = assistMgr.playerAssistingDict[playerID]
+ if not isTJ:
+ tagPlayerID = assistObj.PlayerID
+ GameWorld.DebugLog("非脱机上线,继续协助!tagPlayerID=%s" % tagPlayerID, playerID)
+
+ PlayerControl.SetAssistTagPlayerID(curPlayer, tagPlayerID)
+ assistPack = ChPyNetSendPack.tagGCAssistingInfo()
+ assistPack.AssistGUID = assistObj.GUID
+ NetPackCommon.SendFakePack(curPlayer, assistPack)
+
+ # 脱机上线
+ else:
+ OnCancelPlayerAssist(curPlayer, playerID, assistObj, "TJGLogin", True)
+
+ return
+
+def OnLeaveServer(curPlayer):
+ ## 玩家离线
+ familyID = curPlayer.GetFamilyID()
+ if not familyID:
+ return
+
+ if PlayerControl.GetAssistTagPlayerID(curPlayer):
+ PlayerControl.SetAssistTagPlayerID(curPlayer, 0)
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if familyID not in assistMgr.familyAssistDict:
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ if playerID not in assistMgr.playerNoSaveDBAssistDict:
+ #GameWorld.DebugLog("玩家没有发布过协助,离线不处理!", playerID)
+ return
+ playerNoSaveList = assistMgr.playerNoSaveDBAssistDict[playerID]
+ familyAssistList = assistMgr.familyAssistDict[familyID]
+ # 暂时移除离线玩家发布的不存库协助信息,不再让其他盟友继续前往协助,已经在协助的不影响
+ for assistObj in playerNoSaveList:
+ if assistObj not in familyAssistList:
+ continue
+ familyAssistList.remove(assistObj)
+ SyncFamilyClearAssist(familyID, assistObj.GUID)
+ GameWorld.DebugLog("玩家下线,暂时从仙盟协助列表移除玩家发布的协助: %s" % assistObj.GUID)
+
+ return
+
+def OnPlayerLeaveFamily(familyID, leavePlayerID, leavePlayer):
+ ## 玩家离开仙盟
+ ## @param leavePlayer: 可能不在线为None
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+
+ # 玩家发布的
+ if leavePlayerID in assistMgr.playerNoSaveDBAssistDict:
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[leavePlayerID]
+ for assistObj in playerAssistList[::-1]:
+ OnCancelPlayerRequestAssist(assistObj, "LeaveFamily", True)
+
+ # 玩家协助中的
+ if leavePlayerID in assistMgr.playerAssistingDict:
+ assistObj = assistMgr.playerAssistingDict[leavePlayerID]
+ OnCancelPlayerAssist(leavePlayer, leavePlayerID, assistObj, "LeaveFamily", True)
+
+ return
+
+def OnInitAssistData(dbData, isSaveDB):
+ ## 加载协助数据额外处理
+ setattr(dbData, "IsSaveDB", isSaveDB) # 是否保存数据库,离线可协助的需要存库,如挖矿类
+ setattr(dbData, "ObjID", 0) # NPC实例ID
+
+ assistType = AssistType_Unknown
+ if dbData.NPCID:
+ assistType = AssistType_Boss
+ else:
+ assMapID = dbData.MapID
+ gameMap = GameWorld.GetMap(assMapID)
+ if gameMap and gameMap.GetMapFBType() == ChConfig.fbtTeam:
+ assistType = AssistType_TeamFB
+ setattr(dbData, "AssistType", assistType) # 协助类型
+ setattr(dbData, "AssistPlayerIDList", []) # 协助中的玩家ID列表
+ return
+
+#// B0 12 开始协助Boss #tagCGStartAssistBoss
+#
+#struct tagCGStartAssistBoss
+#
+#{
+# tagHead Head;
+# char AssistGUID[40]; //协助GUID
+#};
+def OnStartAssistBoss(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ assistGUID = clientData.AssistGUID
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if assistGUID not in assistMgr.allAssistDict:
+ GameWorld.DebugLog("不存在该协助!assistGUID=%s" % assistGUID)
+ return
+ assistObj = assistMgr.allAssistDict[assistGUID]
+ if assistObj.AssistType != AssistType_Boss:
+ return
+ if assistObj.PlayerID == curPlayer.GetPlayerID():
+ GameWorld.DebugLog("不能协助自己!")
+ return
+
+ if assistObj.FamilyID != curPlayer.GetFamilyID():
+ GameWorld.DebugLog("非同盟玩家不能协助!")
+ return
+
+ mapID = assistObj.MapID
+ lineID = assistObj.LineID
+ gameMap = GameWorld.GetMap(mapID)
+ if not gameMap:
+ return
+ if gameMap.GetMapFBType() != ChConfig.fbtNull:
+ playerMapID = curPlayer.GetMapID()
+ playerLineID = PlayerControl.GetFBFuncLineID(curPlayer)
+ if playerMapID != mapID or playerLineID != lineID:
+ #副本中无法协助
+ PlayerControl.NotifyCode(curPlayer, "AssistFBLimit")
+ return
+
+ # 设定协助必须离开队伍
+ if gameMap.GetMapFBType() != ChConfig.fbtTeam:
+ curTeam = curPlayer.GetTeam()
+ if curTeam:
+ PlayerTeam.DoPlayerLeaveTeam(curPlayer, curTeam, tick)
+
+ SetPlayerStartAssistBoss(curPlayer, assistObj)
+ return
+
+#// B0 13 取消协助Boss #tagCGCancelAssistBoss
+#
+#struct tagCGCancelAssistBoss
+#
+#{
+# tagHead Head;
+# char AssistGUID[40]; //协助GUID
+#};
+def OnCancelAssistBoss(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ assistGUID = clientData.AssistGUID
+
+ playerID = curPlayer.GetPlayerID()
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID not in assistMgr.playerAssistingDict:
+ GameWorld.DebugLog("没有在协助中,无需取消!", playerID)
+ return
+ assistObj = assistMgr.playerAssistingDict[playerID]
+ if assistGUID != assistObj.GUID:
+ GameWorld.DebugLog("非正在协助中的GUID,不能取消!assistGUID=%s,assisting=%s" % (assistGUID, assistObj.GUID), playerID)
+ return
+ OnCancelPlayerAssist(curPlayer, curPlayer.GetPlayerID(), assistObj, "ClientCancel", True)
+ return
+
+def SetPlayerStartAssistBoss(curPlayer, assistObj):
+ ## 玩家开始协助 boss
+
+ assistGUID = assistObj.GUID
+ tagPlayerID = assistObj.PlayerID
+ mapID = assistObj.MapID
+ lineID = assistObj.LineID
+ npcID = assistObj.NPCID
+ objID = assistObj.ObjID
+
+ tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
+ if not tagPlayer:
+ GameWorld.DebugLog("玩家已离线,无法协助!tagPlayerID=%s" % (tagPlayerID))
+ return
+
+ if tagPlayer.GetMapID() != mapID:
+ GameWorld.DebugLog("目标玩家已不在请求协助的地图,无法协助!tagPlayerID=%s" % (tagPlayerID))
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ # 设置新协助之前需要先取消正在进行中的协助
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID in assistMgr.playerAssistingDict:
+ assistingObj = assistMgr.playerAssistingDict[playerID]
+ if assistGUID != assistingObj.GUID:
+ OnCancelPlayerAssist(curPlayer, playerID, assistingObj, "StartNewAssistBoss", True)
+ assistMgr.playerAssistingDict[playerID] = assistObj
+
+ #if playerID in assistObj.AssistPlayerIDList:
+ # GameWorld.DebugLog("已经在协助中!", playerID)
+ # return
+ if playerID not in assistObj.AssistPlayerIDList:
+ assistObj.AssistPlayerIDList.append(playerID)
+
+ GameWorld.DebugLog("开始协助: tagPlayerID=%s,mapID=%s,lineID=%s,npcID=%s,objID=%s" % (tagPlayerID, mapID, lineID, npcID, objID), playerID)
+
+ # 设置协助
+ PlayerControl.SetAssistTagPlayerID(curPlayer, tagPlayerID)
+
+ # 通知目标玩家
+ assistPlayerID = curPlayer.GetPlayerID()
+ assistPlayerName = curPlayer.GetName()
+ # xxx开始协助你
+ PlayerControl.NotifyCode(tagPlayer, "AssistStart", [assistPlayerName])
+
+ tagPlayerName = tagPlayer.GetName()
+ tagTeamID = tagPlayer.GetTeamID()
+ assistData = [mapID, "Start", assistGUID, assistPlayerID, assistPlayerName, tagPlayerID, tagPlayerName, tagTeamID, lineID, objID, npcID]
+ GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_AssistBoss, assistData)
+ return
+
+def OnAddAssistBossPlayerOK(queryData):
+ ## 添加协助Boss的玩家成功,通知协助玩家可以前往
+ assistGUID, assistPlayerID = queryData
+ assistPlayer = GameWorld.GetPlayerManager().FindPlayerByID(assistPlayerID)
+ if not assistPlayer:
+ return
+
+ assistPack = ChPyNetSendPack.tagGCAssistingInfo()
+ assistPack.AssistGUID = assistGUID
+ NetPackCommon.SendFakePack(assistPlayer, assistPack)
+ return
+
+def SetPlayerStartAssistTeamFB(curPlayer, queryData):
+ ## 开始协助组队副本 - 玩家进入副本后才真正进入协助状态
+
+ #mapID, lineID, tagPlayerID = queryData
+
+ return
+
+def MapServer_PlayerAssistLogic(curPlayer, msgList, tick):
+ ## 地图同步的协助信息逻辑处理
+
+ playerID = 0 if not curPlayer else curPlayer.GetPlayerID()
+ familyID = 0 if not curPlayer else curPlayer.GetFamilyID()
+ queryType, queryData = msgList
+ #result = []
+
+ GameWorld.Log("收到地图协助信息: familyID=%s,queryType=%s,queryData=%s" % (familyID, queryType, queryData), playerID)
+
+ # 请求协助boss
+ if queryType == "RequestAssistBoss":
+ __DoRequestAssistBoss(curPlayer, queryData)
+ return
+
+ # 添加协助Boss的玩家成功
+ elif queryType == "AddAssistBossPlayerOK":
+ OnAddAssistBossPlayerOK(queryData)
+ return
+
+ # 取消boss协助发布
+ elif queryType == "OnCancelBossRequestAssist":
+ mapID, lineID, npcID, objID, reason, cancelPlayerIDList = queryData
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ for cancelPlayerID in cancelPlayerIDList:
+ if cancelPlayerID in assistMgr.playerNoSaveDBAssistDict:
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[cancelPlayerID]
+ for assistObj in playerAssistList:
+ if assistObj.MapID == mapID and assistObj.LineID == lineID and assistObj.NPCID == npcID and assistObj.ObjID == objID:
+ OnCancelPlayerRequestAssist(assistObj, reason, False)
+ break
+ return
+
+ # 取消协助Boss
+ elif queryType == "OnCancelBossAssist":
+ mapID, lineID, npcID, objID, reason = queryData
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID in assistMgr.playerAssistingDict:
+ assistObj = assistMgr.playerAssistingDict[playerID]
+ if assistObj.MapID == mapID and assistObj.LineID == lineID and assistObj.NPCID == npcID and assistObj.ObjID == objID:
+ OnCancelPlayerAssist(curPlayer, playerID, assistObj, reason, False)
+ return
+
+ ## -------------------------------------------------------------------------------------------
+
+ # 请求协助组队副本
+ elif queryType == "RequestAssistTeamFB":
+ __DoRequestAssistTeamFB(curPlayer, queryData)
+ return
+
+ # 开始协助组队副本
+ elif queryType == "OnStartAssistTeamFB":
+ SetPlayerStartAssistTeamFB(curPlayer, queryData)
+ return
+
+ #QueryPlayerResult_PlayerAssist(curPlayer, queryType, queryData, result)
+ return
+
+#def QueryPlayerResult_PlayerAssist(curPlayer, queryType, queryData, result=[]):
+# if not curPlayer:
+# return
+# resultMsg = str([queryType, queryData, result])
+# curPlayer.MapServer_QueryPlayerResult(0, 0, "PlayerAssist", resultMsg, len(resultMsg))
+# GameWorld.DebugLog("协助信息发送 MapServer: playerID=%s,queryType=%s,queryData=%s" % (curPlayer.GetPlayerID(), queryType, queryData))
+# return
+
+def __DoRequestAssistBoss(curPlayer, queryData):
+ ## 请求协助Boss
+
+ familyID = curPlayer.GetFamilyID()
+ if not familyID:
+ return
+ mapID, lineID, npcID, objID = queryData
+
+ playerID = curPlayer.GetPlayerID()
+
+ assistObj = None
+ addNewAssist = True
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID in assistMgr.playerNoSaveDBAssistDict:
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[playerID]
+ for assistObj in playerAssistList:
+ if assistObj.AssistType != AssistType_Boss:
+ continue
+ if npcID != assistObj.NPCID or lineID != assistObj.LineID or objID != assistObj.ObjID:
+ OnCancelPlayerRequestAssist(assistObj, "RequestNewAssistBoss", True)
+ else:
+ addNewAssist = False
+ break
+
+ if addNewAssist:
+ assistObj = __AddNewAssist(assistMgr, curPlayer, mapID, lineID, npcID, objID)
+
+ if not assistObj:
+ return
+
+ # 通知本仙盟玩家
+ PlayerFamily.SendFamilyFakePack(familyID, GetAssistInfoListPack([assistObj]))
+ # 求助信息已发送,请等待盟友支援
+ PlayerControl.NotifyCode(curPlayer, "AssistRequestOK")
+ return
+
+def __DoRequestAssistTeamFB(curPlayer, queryData):
+ ## 请求协助组队副本
+
+ familyID = curPlayer.GetFamilyID()
+ if not familyID:
+ return
+ mapID, lineID = queryData
+
+ playerID = curPlayer.GetPlayerID()
+
+ assistObj = None
+ addNewAssist = False
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if playerID in assistMgr.playerNoSaveDBAssistDict:
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[playerID]
+ for assistObj in playerAssistList:
+ if assistObj.AssistType != AssistType_TeamFB:
+ continue
+ if mapID != assistObj.MapID or lineID != assistObj.LineID:
+ OnCancelPlayerRequestAssist(assistObj, "RequestNewAssistTeamFB", True)
+ addNewAssist = True
+ break
+ else:
+ addNewAssist = True
+
+ if addNewAssist:
+ assistObj = __AddNewAssist(assistMgr, curPlayer, mapID, lineID)
+
+ if not assistObj:
+ return
+
+ # 通知本仙盟玩家
+ PlayerFamily.SendFamilyFakePack(familyID, GetAssistInfoListPack([assistObj]))
+ # 求助信息已发送,请等待盟友支援
+ PlayerControl.NotifyCode(curPlayer, "AssistRequestOK")
+ return
+
+def __AddNewAssist(assistMgr, curPlayer, mapID, lineID, npcID=0, objID=0, exData="", isSaveDB=0):
+ ## 添加新协助请求
+ assistGUID = str(uuid.uuid1())
+ familyID = curPlayer.GetFamilyID()
+ playerID = curPlayer.GetPlayerID()
+ assistObj = PyGameDataStruct.tagDBAssist()
+ assistObj.GUID = assistGUID
+ assistObj.FamilyID = familyID
+ assistObj.PlayerID = playerID
+ assistObj.PlayerName = curPlayer.GetName()
+ assistObj.Job = curPlayer.GetJob()
+ assistObj.LV = curPlayer.GetLV()
+ assistObj.RealmLV = curPlayer.GetOfficialRank()
+ assistObj.MapID = mapID
+ assistObj.LineID = lineID
+ assistObj.NPCID = npcID
+ assistObj.ExData = exData
+ assistObj.ExDataLen = len(exData)
+
+ # 以下是非DB字段属性
+ OnInitAssistData(assistObj, isSaveDB)
+ assistObj.ObjID = objID
+
+ #assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ assistMgr.allAssistDict[assistGUID] = assistObj
+ if familyID not in assistMgr.familyAssistDict:
+ assistMgr.familyAssistDict[familyID] = []
+ familyAssistList = assistMgr.familyAssistDict[familyID]
+ familyAssistList.append(assistObj)
+
+ if not isSaveDB:
+ if playerID not in assistMgr.playerNoSaveDBAssistDict:
+ assistMgr.playerNoSaveDBAssistDict[playerID] = []
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[playerID]
+ playerAssistList.append(assistObj)
+
+ GameWorld.DebugLog(" 增加新协助请求: familyID=%s,mapID=%s,lineID=%s,npcID=%s,objID=%s,exData=%s,assistGUID=%s"
+ % (familyID, mapID, lineID, npcID, objID, exData, assistGUID), playerID)
+ return assistObj
+
+def GetAssistInfoListPack(familyAssistList):
+ ## 协助列表封包数据
+ assistList = []
+ for assistObj in familyAssistList:
+ assistInfo = ChPyNetSendPack.tagGCAssistInfo()
+ assistInfo.AssistGUID = assistObj.GUID
+ assistInfo.PlayerName = assistObj.PlayerName
+ assistInfo.Job = assistObj.Job
+ assistInfo.LV = assistObj.LV
+ assistInfo.RealmLV = assistObj.RealmLV
+ assistInfo.MapID = assistObj.MapID
+ assistInfo.LineID = assistObj.LineID
+ assistInfo.NPCID = assistObj.NPCID
+ assistInfo.ExData = assistObj.ExData
+ assistInfo.ExDataLen = len(assistObj.ExData)
+ assistList.append(assistInfo)
+
+ infoListPack = ChPyNetSendPack.tagGCAssistInfoList()
+ infoListPack.AssistInfoList = assistList
+ infoListPack.Count = len(assistList)
+ return infoListPack
+
+def OnCancelPlayerRequestAssist(assistObj, reason, isGameServer):
+ '''取消玩家协助 - 发布方
+ MapServer 触发取消
+ 1. 攻击了另一只boss
+ 2. 重新发布了另一条协助boss/组队副本
+ 3. 进入协助状态,即本来在打同一只boss,后面直接改为协助
+ 4. 退出了发布协助地图
+
+ GameServer 触发取消
+ 5. 被踢/退出仙盟
+ '''
+
+ assistGUID = assistObj.GUID
+ playerID = assistObj.PlayerID
+ familyID = assistObj.FamilyID
+ assistType = assistObj.AssistType
+ mapID = assistObj.MapID
+ lineID = assistObj.LineID
+ npcID = assistObj.NPCID
+ objID = assistObj.ObjID
+
+ GameWorld.DebugLog("取消发布的协助请求: mapID=%s,lineID=%s,npcID=%s,objID=%s,reason=%s,isGameServer=%s, %s"
+ % (mapID, lineID, npcID, objID, reason, isGameServer, assistGUID))
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if assistGUID not in assistMgr.allAssistDict:
+ return
+ assistMgr.allAssistDict.pop(assistGUID)
+
+ if familyID in assistMgr.familyAssistDict:
+ familyAssistList = assistMgr.familyAssistDict[familyID]
+ if assistObj in familyAssistList:
+ familyAssistList.remove(assistObj)
+
+ if playerID in assistMgr.playerNoSaveDBAssistDict:
+ playerAssistList = assistMgr.playerNoSaveDBAssistDict[playerID]
+ if assistObj in playerAssistList:
+ playerAssistList.remove(assistObj)
+
+ SyncFamilyClearAssist(familyID, assistGUID)
+
+ # 取消boss协助
+ if assistType == AssistType_Boss:
+
+ # 强制取消正在协助中的玩家
+ playerMgr = GameWorld.GetPlayerManager()
+ for assPlayerID in assistObj.AssistPlayerIDList[::-1]:
+ assistObj.AssistPlayerIDList.remove(assPlayerID)
+ if assPlayerID in assistMgr.playerAssistingDict:
+ assistingObj = assistMgr.playerAssistingDict[assPlayerID]
+ if assistingObj.GUID == assistGUID:
+ assPlayer = playerMgr.FindPlayerByID(assPlayerID)
+ OnCancelPlayerAssist(assPlayer, assPlayerID, assistObj, reason, isGameServer, isNotify=False)
+
+ # 发布方取消不需要通知地图,对地图发布玩家没有影响,可继续攻击boss
+
+ # 取消副本协助
+ elif assistType == AssistType_TeamFB:
+ # 暂不需要处理
+ pass
+
+ return
+
+def OnCancelPlayerAssist(cancelPlayer, cancelPlayerID, assistObj, reason, isGameServer, isNotify=True):
+ '''取消玩家协助 - 协助方
+ MapServer 触发取消
+ 1. 攻击了另一只boss
+ 2. 退出了当前协助的协助地图
+
+ GameServer 触发取消
+ 3. 重新协助了另一条协助boss/组队副本
+ 4. 被踢/退出仙盟
+ 5. 主动点取消
+
+ 其他,发布方取消方式
+ 6. 发布方取消了发布的协助
+ '''
+
+ assistGUID = assistObj.GUID
+ tagPlayerID = assistObj.PlayerID
+ mapID = assistObj.MapID
+ lineID = assistObj.LineID
+ npcID = assistObj.NPCID
+ objID = assistObj.ObjID
+
+ GameWorld.DebugLog("取消协助: tagPlayerID=%s,mapID=%s,lineID=%s,npcID=%s,objID=%s,reason=%s,isGameServer=%s, %s"
+ % (tagPlayerID, mapID, lineID, npcID, objID, reason, isGameServer, assistGUID), cancelPlayerID)
+
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ if cancelPlayerID in assistMgr.playerAssistingDict:
+ assistMgr.playerAssistingDict.pop(cancelPlayerID)
+
+ if cancelPlayerID in assistObj.AssistPlayerIDList:
+ assistObj.AssistPlayerIDList.remove(cancelPlayerID)
+
+ if cancelPlayer:
+ PlayerControl.SetAssistTagPlayerID(cancelPlayer, 0)
+
+ # 取消boss协助
+ if assistObj.AssistType == AssistType_Boss:
+
+ # GameServer取消的需要通知协助boss地图,删除协助玩家记录
+ if isGameServer:
+ assistData = [mapID, "Cancel", cancelPlayerID, lineID, objID, npcID]
+ GameWorld.SendMapServerMsgEx(ShareDefine.Def_Notify_WorldKey_AssistBoss, assistData)
+
+ if isNotify and cancelPlayer:
+ tagPlayer = GameWorld.GetPlayerManager().FindPlayerByID(tagPlayerID)
+ if tagPlayer:
+ # xxx取消对你协助
+ PlayerControl.NotifyCode(tagPlayer, "AssistCancel", [cancelPlayer.GetName()])
+
+ # 取消副本协助
+ elif assistObj.AssistType == AssistType_TeamFB:
+ pass
+
+ return
+
+#// B0 14 使用协助感谢礼盒 #tagCGUseAssistThanksGift
+#
+#struct tagCGUseAssistThanksGift
+#
+#{
+# tagHead Head;
+# DWORD ItemID;
+# char GiftGUID[40]; //预览时GUID不发,确认使用时需发送预览返回的GUID
+#};
+def OnUseAssistThanksGift(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ itemID = clientData.ItemID
+ giftGUID = clientData.GiftGUID
+ return
+
+#// B0 15 领取协助感谢礼物 #tagCGGetAssistThanksGift
+#
+#struct tagCGGetAssistThanksGift
+#
+#{
+# tagHead Head;
+# char GiftGUID[40]; //礼盒GUID
+#};
+def OnGetAssistThanksGift(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ giftGUID = clientData.GiftGUID
+ return
+
+def SyncFamilyAssist(curPlayer):
+ ## 同步当前仙盟所有协助请求信息
+ familyID = curPlayer.GetFamilyID()
+ if not familyID:
+ return
+ assistMgr = PyDataManager.GetPlayerAssistPyManager()
+ familyAssistList = assistMgr.familyAssistDict.get(familyID, [])
+ if not familyAssistList:
+ return
+ NetPackCommon.SendFakePack(curPlayer, GetAssistInfoListPack(familyAssistList))
+ return
+
+def SyncFamilyClearAssist(familyID, assistGUID):
+ # 封包通知仙盟清除协助
+ clearPack = ChPyNetSendPack.tagGCClearAssist()
+ clearPack.AssistGUID = assistGUID
+ PlayerFamily.SendFamilyFakePack(familyID, clearPack)
+ return
+
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
index 2176370..60b9741 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerControl.py
@@ -192,6 +192,16 @@
#------------------------------------------------------------------------------
+## 协助目标玩家ID
+def SetAssistTagPlayerID(curPlayer, value):
+ curPlayer.SetExAttr1(value)
+ SetMapServerPlayerAttrValue(curPlayer, "SetAssistTagPlayerID", value)
+ return
+def GetAssistTagPlayerID(curPlayer): return curPlayer.GetExAttr1()
+
+## 副本功能线路ID
+def SetFBFuncLineID(curPlayer, funcLineID): return curPlayer.SetExAttr3(funcLineID)
+def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3()
##VIP到期时间
def GetVIPExpireTime(curPlayer): return curPlayer.GetExAttr9()
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
index 312fb5d..cb145d1 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerFamily.py
@@ -41,6 +41,7 @@
import PlayerViewCache
import GameWorldBoss
import AuctionHouse
+import PlayerAssist
import PlayerTalk
import PlayerTeam
@@ -405,6 +406,8 @@
PlayerFamilyParty.NotifyFamilyPartyQuestion(jionPlayer)
#通知守卫人皇信息
PlayerFamilySWRH.NotifySWRHInfo(jionPlayer, curFamily.GetID())
+ #通知仙盟协助信息
+ PlayerAssist.SyncFamilyAssist(jionPlayer)
#oss记录加入家族信息
DataRecordPack.DR_PlayerJoinFamily(jionPlayer, curFamily.GetID(), curFamily.GetName(), curFamily.GetCount())
return
@@ -608,7 +611,7 @@
#===============================================================================================
return
-def SendFamilyFakePack(familyID, clientPack):
+def SendFamilyFakePack(familyID, clientPack, excludePlayerIDList=[]):
## 广播家族成员PY封包
family = GameWorld.GetFamilyManager().FindFamily(familyID)
if not family:
@@ -617,8 +620,11 @@
for index in xrange(family.GetCount()):
member = family.GetAt(index)
memPlayer = member.GetPlayer()
- if memPlayer:
- NetPackCommon.SendFakePack(memPlayer, clientPack)
+ if not memPlayer:
+ continue
+ if excludePlayerIDList and memPlayer.GetPlayerID() in excludePlayerIDList:
+ continue
+ NetPackCommon.SendFakePack(memPlayer, clientPack)
return
def Sync_PyAllFamilyInfo(curPlayer, allPageCnt, viewPage, startIndex, endIndex):
@@ -1465,10 +1471,10 @@
PlayerFamilyAction.AddFamilyActionNote(tagPlayerName, curFamily.GetID(), ShareDefine.Def_ActionType_FamilyEvent,
[ShareDefine.Def_FamilyActionEvent_MemberChange, ShareDefine.Def_FamilyMemberChange_KickOut], tick)
#删除玩家
- curFamily.DeleteMember(tagPlayerID)
- __DoPlayerLeaveFamilyByID(curFamily, tagPlayerID)
-
+ curFamily.DeleteMember(tagPlayerID)
tagPlayer = playerManager.FindPlayerByID(tagMemberID)
+
+ __DoPlayerLeaveFamilyByID(curFamily, tagPlayerID, tagPlayer)
#玩家在线, 设置这个玩家的属性
PlayerForceLeaveFamily(tagPlayer, tick)
@@ -1565,7 +1571,7 @@
curFamily.DeleteMember(curMember.GetPlayerID())
#玩家在线, 设置这个玩家的属性
PlayerForceLeaveFamily(curPlayer, tick)
- __DoPlayerLeaveFamilyByID(curFamily, curPlayerID)
+ __DoPlayerLeaveFamilyByID(curFamily, curPlayerID, curPlayer)
DataRecordPack.DR_PlayerLeaveFamily(curPlayer, curFamily.GetID(), curFamily.GetName(), curFamily.GetCount(),
familyLV, curPlayer.GetPlayerID(), curPlayer.GetName(), familyLV, updTime)
@@ -1583,12 +1589,13 @@
# @param curFamily 离开的家族
# @param leavePlayerID 离开的玩家ID
# @return None
-def __DoPlayerLeaveFamilyByID(curFamily, leavePlayerID):
+def __DoPlayerLeaveFamilyByID(curFamily, leavePlayerID, tagPlayer=None):
PlayerFamilyAction.DelFamilyOfficerModelEquip(curFamily.GetID(), leavePlayerID)
# 玩家战盟名变更处理
__OnFamilyNameChange(leavePlayerID, '')
AddFamilyIDToFightPowerChangeList(curFamily.GetID())
PlayerViewCache.OnPlayerFamilyChange(leavePlayerID, 0, "")
+ PlayerAssist.OnPlayerLeaveFamily(curFamily.GetID(), leavePlayerID, tagPlayer)
if leavePlayerID in PyGameData.g_autoViceleaderDict.get(curFamily.GetID(),[]):
PyGameData.g_autoViceleaderDict[curFamily.GetID()].remove(leavePlayerID)
return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
index b934983..450a64d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerQuery.py
@@ -74,6 +74,7 @@
import AuctionHouse
import PlayerFairyDomain
import GameWorldItem
+import PlayerAssist
import time
import datetime
@@ -779,6 +780,16 @@
AuctionHouse.MapServer_AuctionHouseLogic(curPlayer, eval(resultName), tick)
return
+ # 协助
+ if callName == "PlayerAssist":
+ curPlayer = None
+ if srcPlayerID:
+ curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(srcPlayerID)
+ if not curPlayer:
+ return
+ PlayerAssist.MapServer_PlayerAssistLogic(curPlayer, eval(resultName), tick)
+ return
+
if callName == "TeamMemFuncData":
PlayerTeam.MapServer_TeamMemFuncData(srcPlayerID, eval(resultName))
return
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTeam.py b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTeam.py
index 53ff4f7..a511d9f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTeam.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/Player/PlayerTeam.py
@@ -590,6 +590,11 @@
PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
return False
+ if PlayerControl.GetAssistTagPlayerID(curPlayer):
+ #协助中无法执行此操作
+ PlayerControl.NotifyCode(curPlayer, "InAssistForbid")
+ return False
+
if tagPlayer:
tagPlayerID = tagPlayer.GetPlayerID()
#检查ID
@@ -614,6 +619,11 @@
PlayerControl.NotifyCode(curPlayer, "TeamEnterForbid")
return False
+ if PlayerControl.GetAssistTagPlayerID(tagPlayer):
+ #对方协助中,无法执行此操作
+ PlayerControl.NotifyCode(curPlayer, "TagInAssistForbid")
+ return False
+
return True
#===============================================================================
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
index 9f0c1c5..15f575f 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/PyDataManager.py
@@ -23,6 +23,7 @@
import PyGameData
import CrossRealmPK
import AuctionHouse
+import PlayerAssist
import PyGameDataStruct
import CommFunc
@@ -86,8 +87,11 @@
class PlayerAssistPyManager(object):
def __init__(self):
- self.playerAssistDict = {} # 所有协助 {GUID:tagDBAssist, ...}
+ self.allAssistDict = {} # 所有协助 {GUID:tagDBAssist, ...}
self.familyAssistDict = {} # 仙盟协助缓存 {familyID:[tagDBAssist, ...], ...}
+
+ self.playerNoSaveDBAssistDict = {} # 玩家发布的不存库协助 {playerID:[tagDBAssist, ...], ...}
+ self.playerAssistingDict = {} # 玩家正在协助中的协助,只能存在一条 {playerID:tagDBAssist, ...}
return
# 保存数据 存数据库和realtimebackup
@@ -96,7 +100,9 @@
cntData = ""
cnt = 0
- for dbData in self.playerAssistDict.values():
+ for dbData in self.allAssistDict.values():
+ if not dbData.IsSaveDB:
+ continue
cnt += 1
savaData += dbData.getBuffer()
@@ -113,7 +119,9 @@
dbData.clear()
pos += dbData.readData(datas, pos, dataslen)
- self.playerAssistDict[dbData.GUID] = dbData
+ PlayerAssist.OnInitAssistData(dbData, 1)
+
+ self.allAssistDict[dbData.GUID] = dbData
familyID = dbData.FamilyID
if familyID not in self.familyAssistDict:
self.familyAssistDict[familyID] = []
diff --git a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
index 1c964a5..a520f4d 100644
--- a/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
+++ b/ServerPython/CoreServerGroup/GameServer/Script/ShareDefine.py
@@ -195,6 +195,9 @@
Def_Notify_WorldKey_RedPacketOutput = 'RedPacketOutput' # 红包产出信息
Def_Notify_WorldKey_HurtLog = 'HurtLog' # 战斗伤害日志
Def_Notify_WorldKey_FairyDomainLimit = "FairyDomainLimit" # 缥缈仙域限制事件
+
+Def_Notify_WorldKey_AssistBoss = "AssistBoss" # 协助boss
+
#运营活动表名定义
OperationActionName_ExpRate = "ActExpRate" # 多倍经验活动
OperationActionName_CostRebate = "ActCostRebate" # 消费返利活动
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
index 0725a6e..e58a32c 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/PyNetPack.ini
@@ -1422,6 +1422,22 @@
PacketSubCMD_1=0x25
PacketCallFunc_1=OnDailyActionBuyCnt
+;协助
+[PlayerAssist]
+ScriptName = Player\PlayerAssist.py
+Writer = hxp
+Releaser = hxp
+RegType = 0
+RegisterPackCount = 2
+
+PacketCMD_1=0xB0
+PacketSubCMD_1=0x10
+PacketCallFunc_1=OnRequestAssistBoss
+
+PacketCMD_2=0xB0
+PacketSubCMD_2=0x11
+PacketCallFunc_2=OnRequestAssistTeamFB
+
;缥缈仙域
[PlayerFairyDomain]
ScriptName = Player\PlayerFairyDomain.py
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
index b164b78..81f8c02 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/AttackCommon.py
@@ -55,6 +55,7 @@
import BuffSkill
import PlayerState
import ChPyNetSendPack
+import NPCHurtManager
import NetPackCommon
import FamilyRobBoss
import FBCommon
@@ -699,15 +700,14 @@
# @param hurtHP 攻击伤血值
# @return None or True
# @remarks 函数详细说明.
-def NPCAddObjInHurtList(curObj, curTagObj, curTaglNPCHPBefore, hurtHP) :
+def NPCAddObjInHurtList(curObj, curTagObj, curTaglNPCHPBefore, hurtHP, isBounce=False):
if curObj == None:
GameWorld.ErrLog("NPCAddObjInHurtList NoFindObj")
return
if curTaglNPCHPBefore < hurtHP:
hurtHP = curTaglNPCHPBefore
-
- defNPCHurtList = curTagObj.GetPlayerHurtList()
+
curObjType = curObj.GetGameObjType()
if curObjType == IPY_GameWorld.gotPlayer:
#BossHurtMng.BossAddPlayerInHurtList(curObj, curTagObj, hurtHP)
@@ -716,6 +716,9 @@
FBLogic.DoFB_Player_HurtNPC(curObj, curTagObj, hurtHP)
if GameObj.GetHP(curTagObj) == 0:
curTagObj.SetDict(ChConfig.Def_PlayerKey_LastHurt, curObj.GetPlayerID())
+
+ if NPCHurtManager.AddHurtValue(curObj, curTagObj, hurtHP, isBounce):
+ return
curTeam = curObj.GetTeam()
@@ -780,7 +783,7 @@
# return False
#击杀次数判断
- if not CheckKillNPCByCnt(attacker, defender):
+ if not NPCHurtManager.IsAssistPlayer(attacker.GetPlayerID(), defender) and not CheckKillNPCByCnt(attacker, defender):
return False
#仙盟归属NPC判断
@@ -794,7 +797,7 @@
# return False
#击杀次数判断
- if not CheckKillNPCByCnt(defender, attacker, False):
+ if not CheckKillNPCByCnt(defender, attacker, False) and not NPCHurtManager.IsAssistPlayer(defender.GetPlayerID(), attacker):
return False
#仙盟归属NPC判断
@@ -806,8 +809,10 @@
if PetControl.IsPet(attacker) or attacker.GetGameNPCObjType()== IPY_GameWorld.gnotSummon:
#击杀次数判断
if not CheckKillNPCByCnt(attacker, defender, False):
- return False
-
+ ownerPlayer = GetAttackPlayer(attacker)[0]
+ if ownerPlayer and not NPCHurtManager.IsAssistPlayer(ownerPlayer.GetPlayerID(), defender):
+ return False
+
#仙盟归属NPC判断
if not CheckCanAttackFamilyOwnerNPC(attacker, defender, False):
return False
@@ -2464,7 +2469,7 @@
# GameWorld.DebugLog("不能攻击,不反弹")
# return
#杀怪次数判断
- if not CheckKillNPCByCnt(defObj, atkObj, False):
+ if not CheckKillNPCByCnt(defObj, atkObj, False) and not NPCHurtManager.IsAssistPlayer(defObj.GetPlayerID(), atkObj):
#GameWorld.DebugLog("不能攻击,不反弹")
return
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/NormalNPC_Attack_Player.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/NormalNPC_Attack_Player.py
index d3dee81..ebb1910 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/NormalNPC_Attack_Player.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Attack/AttackLogic/NormalNPC_Attack_Player.py
@@ -87,7 +87,7 @@
lastHP = curNPCBeHP - GameObj.GetHP(curNormalNPC)
if lastHP > 0 :
#添加伤血列表
- AttackCommon.NPCAddObjInHurtList(curTagPlayer, curNormalNPC, curNPCBeHP, lastHP)
+ AttackCommon.NPCAddObjInHurtList(curTagPlayer, curNormalNPC, curNPCBeHP, lastHP, True)
#给这个玩家的召唤兽增加仇恨
AttackCommon.SummonAddAngryByOwner(curNormalNPC, curTagPlayer, hurtHP)
#添加技能伤害通知列表,(用于攻击结束,统一通知客户端)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
index 04f263d..90856b2 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ChConfig.py
@@ -2220,6 +2220,7 @@
1000 * 15, # 渡劫鼓舞间隔
1000 * 1, # vip体验时效
1000 * 1, # 限时抢购
+ 1000 * 5, # 请求协助间隔
]
TYPE_Player_Tick_Count = len(TYPE_Player_Tick_Time)
@@ -2293,6 +2294,7 @@
TYPE_Player_Tick_DuJieInspire, # 渡劫鼓舞间隔
TYPE_Player_Tick_VIPExperience, #vip体验时效
TYPE_Player_Tick_FlashSale, #限时抢购
+TYPE_Player_Tick_RequestAssist, #请求协助间隔
) = range(0, TYPE_Player_Tick_Count)
#---------------------------------------------------------------------
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
index fb307e5..78be798 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/PrintNPCHurt.py
@@ -19,6 +19,8 @@
import FamilyRobBoss
import NPCCommon
import ChConfig
+import NPCHurtManager
+import PlayerTeam
##查看点选的NPC仇恨列表
# @param curPlayer 玩家实例
@@ -38,19 +40,29 @@
GameWorld.DebugAnswer(curPlayer, "objID(%s) 错误 找不到对应NPC" % objID)
return
- GameWorld.DebugAnswer(curPlayer, "---%s,ID=%s,team=%s,family=%s"
- % (GameWorld.GetGameWorld().GetTick()%1000, curPlayer.GetPlayerID(), curPlayer.GetTeamID(), curPlayer.GetFamilyID()))
+ GameWorld.DebugAnswer(curPlayer, "---------------- %s" % (GameWorld.GetGameWorld().GetTick() % 1000))
+ GameWorld.DebugAnswer(curPlayer, "ID=%s,team=%s,family=%s" % (curPlayer.GetPlayerID(), curPlayer.GetTeamID(), curPlayer.GetFamilyID()))
# 归属仙盟的,取仙盟伤血统计
if NPCCommon.GetDropOwnerType(curNPC) == ChConfig.DropOwnerType_Family:
FamilyRobBoss.OnGMPrintFamilyOwnerBossHurt(curPlayer, curNPC)
return
- npcHurtList = curNPC.GetPlayerHurtList()
+ isPyHurtList = True
+ npcHurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
+ if not npcHurtList:
+ npcHurtList = curNPC.GetPlayerHurtList()
+ isPyHurtList = False
if isSort:
npcHurtList.Sort() #sort以后伤血列表从大到小排序
GameWorld.DebugAnswer(curPlayer, "ID=%s, NPCID=%s, 伤血数=%s, isSort=%s" % (curNPC.GetID(), curNPC.GetNPCID(), npcHurtList.GetHurtCount(), isSort))
+ if isPyHurtList:
+ for playerID, assistPlayerIDList in npcHurtList.GetNoAssitPlayerIDDict().items():
+ GameWorld.DebugAnswer(curPlayer, "玩家:%s, 协助玩家:%s" % (playerID, assistPlayerIDList))
+ for assistPlayerID, tagPlayerID in npcHurtList.GetAssistPlayerIDDict().items():
+ GameWorld.DebugAnswer(curPlayer, "协助玩家:%s, 目标:%s" % (assistPlayerID, tagPlayerID))
+
for index in xrange(npcHurtList.GetHurtCount()):
#获得伤血对象
hurtObj = npcHurtList.GetHurtAt(index)
@@ -71,6 +83,12 @@
d = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), hurtPlayer.GetPosX(), hurtPlayer.GetPosY())
GameWorld.DebugAnswer(curPlayer, "%s 玩家ID=%s,距离=%s, V=%s" % (index, hurtID, d, hurtValue))
+ if isPyHurtList:
+ playerHurtValue, assistPlayerHurtDict = npcHurtList.GetPlayerHurtDetail(hurtID)
+ GameWorld.DebugAnswer(curPlayer, " 非协id=%s,v=%s" % (hurtID, playerHurtValue))
+ for assistPlayerID, assistHurtValue in assistPlayerHurtDict.items():
+ GameWorld.DebugAnswer(curPlayer, " 协助id=%s,v=%s" % (assistPlayerID, assistHurtValue))
+
elif hurtType == ChConfig.Def_NPCHurtTypeTeam:
#获得当前队伍
curTeam = GameWorld.GetTeamManager().FindTeam(hurtID)
@@ -79,6 +97,16 @@
else:
GameWorld.DebugAnswer(curPlayer, "%s 队伍ID=%s,人数=%s, V=%s" % (index, hurtID, curTeam.GetMemberCount(), hurtValue))
+ if isPyHurtList:
+ mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(hurtID)
+ for teamPlayerID in mapTeamPlayerIDList:
+ if not npcHurtList.IsNoAssistPlayer(teamPlayerID):
+ continue
+ playerHurtValue, assistPlayerHurtDict = npcHurtList.GetPlayerHurtDetail(teamPlayerID)
+ GameWorld.DebugAnswer(curPlayer, " 非协id=%s,v=%s" % (teamPlayerID, playerHurtValue))
+ for assistPlayerID, assistHurtValue in assistPlayerHurtDict.items():
+ GameWorld.DebugAnswer(curPlayer, " 协助id=%s,v=%s" % (assistPlayerID, assistHurtValue))
+
elif hurtType == ChConfig.Def_NPCHurtTypeNPC:
GameWorld.DebugAnswer(curPlayer, "%s NPC=%s, V=%s" % (index, hurtID, hurtValue))
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetWorldPos.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetWorldPos.py
index 86d3fc1..453fcbe 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetWorldPos.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/GM/Commands/SetWorldPos.py
@@ -22,6 +22,9 @@
# @remarks 函数详细说明.
def OnExec(curPlayer, paramList):
#输入命令格式错误
+ if not paramList:
+ GameWorld.DebugAnswer(curPlayer, "SetWorldPos mapID posX posY")
+ return
mapID, posX, posY = paramList[:3]
lineID = paramList[3] if len(paramList) > 3 else - 1
if not mapID:
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 39c9ca2..3c88207 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCCommon.py
@@ -53,6 +53,7 @@
import PlayerNewFairyCeremony
import GameLogic_CrossGrassland
import PlayerWeekParty
+import NPCHurtManager
import PlayerActLogin
import FamilyRobBoss
import IpyGameDataPY
@@ -2271,6 +2272,7 @@
AttackCommon.ClearTeamPlayerHurtValue(curNPC)
# 清除自定义伤血列表
#BossHurtMng.ClearHurtValueList(curNPC)
+ NPCHurtManager.DeletePlayerHurtList(curNPC)
if curNPC.GetType() == ChConfig.ntRobot:
lineID = GameWorld.GetGameWorld().GetLineID()
lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})
@@ -2393,7 +2395,6 @@
# @remarks 类初始化
def __init__(self, iNPC):
self.__Instance = iNPC
- self.__MaxHurtPlayer = None # 最大伤血者,队伍取队长
self.__LastHurtPlayer = None # 最后一击的玩家
self.__Killer = None # 击杀者, 由各种规则得出, 一般也是物品归属的代表, 用于广播、记录等确保与归属一致
self.__AllKillerDict = {} # 所有击杀的玩家ID对应字典, 非队伍, 一般也是归属的拥有者
@@ -3198,231 +3199,6 @@
npcHurtList.Clear()
return True
- def __IsBossHurtOfflineProtect(self, refreshPoint, playerID, tick):
- ## boss伤血是否掉线保护中
- # 是否离线超过3分钟,下线坐标是否不在boss区域等
- leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)
- leavePos = PlayerControl.GetPlayerLeaveServerPos(playerID)
- if not leaveTick or not leavePos:
- GameWorld.DebugLog("玩家不在本地图或已长久离线!清除该伤血!playerID=%s" % playerID)
- return False
-
- if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:
- GameWorld.DebugLog("本地图离线玩家超过保护时长!清除该伤血!playerID=%s,tick=%s,leaveTick=%s" % (playerID, tick, leaveTick))
- return False
-
- if not self.GetIsInRefreshPoint(leavePos[0], leavePos[1], refreshPoint):
- GameWorld.DebugLog("本地图离线玩家不在保护区域内!playerID=%s,leavePos=%s" % (playerID, leavePos))
- return False
-
- return True
-
- def __IsClearPlayerHurt(self, hurtPlayer, refreshPoint, hurtID, tick):
- if hurtPlayer == None:
- if not self.__IsBossHurtOfflineProtect(refreshPoint, hurtID, tick):
- return True
-
- #GameWorld.DebugLog("本地图离线玩家伤血值保护中!playerID=%s" % (hurtID))
- return False
-
- #if hurtPlayer.GetHP() <= 0:
- # GameWorld.DebugLog("伤血玩家血量为0,清除该伤血!playerID=%s" % hurtID)
- # return True
-
- curNPC = self.__Instance
- if hurtPlayer.GetInitOK() and (not hurtPlayer.GetVisible() or hurtPlayer.GetSightLevel() != curNPC.GetSightLevel()):
- GameWorld.DebugLog("伤血玩家不可见,清除该伤血!playerID=%s" % hurtID)
- return True
-
- if not self.GetIsInRefreshPoint(hurtPlayer.GetPosX(), hurtPlayer.GetPosY(), refreshPoint):
- GameWorld.DebugLog("伤血玩家不在boss范围里,清除该伤血!playerID=%s" % hurtID)
- return True
-
- if hurtPlayer.GetTeamID():
- # 这种情况一般是玩家未加入队伍前对该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()
- copyMapID = GameWorld.GetGameWorld().GetCopyMapID()
- mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID) # 因为需要判断离线队员,所以只能用含离线的队伍缓存
- for playerID in mapTeamPlayerIDList:
-
- curTeamPlayer = playerMgr.FindPlayerByID(playerID)
- if curTeamPlayer:
- if curTeamPlayer.GetCopyMapID() != copyMapID:
- #GameWorld.DebugLog("队员不在本线路,不计!playerID=%s" % playerID)
- continue
-
- if curTeamPlayer.GetInitOK() and (not curTeamPlayer.GetVisible() or curTeamPlayer.GetSightLevel() != curNPC.GetSightLevel()):
- #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) \
- and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False):
- #GameWorld.DebugLog("有队员在boss范围内,保留队伍伤血!teamID=%s,playerID=%s" % (teamID, curTeamPlayer.GetPlayerID()))
- teamHurtPlayerIDList.append(playerID)
- else:
- if self.__IsBossHurtOfflineProtect(refreshPoint, playerID, tick):
- #GameWorld.DebugLog("有队员对boss离线伤血保护中!teamID=%s,playerID=%s" % (teamID, playerID))
- teamHurtPlayerIDList.append(playerID)
-
- if not teamHurtPlayerIDList:
- GameWorld.DebugLog("伤血队伍没有符合条件的队员在boss区域内,清除该伤血!teamID=%s,mapTeamPlayerIDList=%s" % (teamID, mapTeamPlayerIDList))
- return teamHurtPlayerIDList
-
- def RefreshHurtList(self, tick, refreshInterval=3000):
- ## 刷新伤血列表
- # @return: 可攻击的最大伤血数值对象 IPY_PlayerHurtValue
-
- curNPC = self.__Instance
- if not curNPC.GetIsBoss() or GetDropOwnerType(curNPC) != ChConfig.DropOwnerType_MaxHurt:
- return
-
- npcHurtList = curNPC.GetPlayerHurtList()
- if tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < (refreshInterval):
- if npcHurtList.GetHurtCount():
- return self.__GetAtkObjByHurtList(npcHurtList)
- return
- curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)
-
- hurtPlayerDict = {} # {playerID:teamID, ...}
- refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
- hurtCount = npcHurtList.GetHurtCount()
- isInHurt = 0
- for index in xrange(hurtCount):
- #获得伤血对象
- hurtObj = npcHurtList.GetHurtAt(index)
- hurtType = hurtObj.GetValueType()
- hurtID = hurtObj.GetValueID()
- hurtValue = hurtObj.GetHurtValue()
- if not hurtID:
- continue
-
- # Clear()只会把伤血类型及数值重置为0,不会清除该伤血数值对象
-
- if hurtType == ChConfig.Def_NPCHurtTypePlayer:
- hurtPlayer = GameWorld.GetObj(hurtID, IPY_GameWorld.gotPlayer)
- if self.__IsClearPlayerHurt(hurtPlayer, refreshPoint, hurtID, tick):
- hurtObj.Clear()
- teamID = 0 if not hurtPlayer else hurtPlayer.GetTeamID()
- if teamID:
- GameWorld.DebugLog("加入队伍,之气的伤血转移到队伍中!playerID=%s,teamID=%s" % (hurtID, teamID))
- AttackCommon.AddHurtValue(curNPC, teamID, ChConfig.Def_NPCHurtTypeTeam, hurtValue)
- else:
- isInHurt = 1
- hurtPlayerDict[hurtID] = 0
-
- elif hurtType == ChConfig.Def_NPCHurtTypeTeam:
- teamHurtPlayerIDList = self.__GetTeamHurtNPCPlayerIDList(refreshPoint, hurtID, tick)
- if not teamHurtPlayerIDList:
- hurtObj.Clear()
- else:
- isInHurt = 1
- for tPlayerID in teamHurtPlayerIDList:
- hurtPlayerDict[tPlayerID] = hurtID
-
- mapID = GameWorld.GetMap().GetMapID()
- if IsMapNeedBossShunt(mapID):
- self.__UpdBossShuntInfo(mapID, hurtPlayerDict, tick)
-
- #GameWorld.DebugLog("RefreshHurtList, hurtCount=%s,isInHurt=%s" % (hurtCount, isInHurt))
- npcHurtList.Sort()
- curNPC.SetDict(ChConfig.Def_NPC_Dict_InHurtProtect, isInHurt)
-
- if hurtCount:
- # 排序后的,第一个可攻击的最大伤血对象
- return self.__GetAtkObjByHurtList(npcHurtList)
- return
-
- def __UpdBossShuntInfo(self, mapID, hurtPlayerDict, tick):
- ## 更新本地图线路boss分流信息
- curNPC = self.__Instance
- npcID = curNPC.GetNPCID()
- lineID = GameWorld.GetGameWorld().GetLineID()
- key = (mapID, lineID)
- shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
-
- shuntChange = False
- for playerID, shuntInfo in shuntPlayerDict.items():
- bossID, teamID, relatedTick = shuntInfo
- if bossID != npcID:
- # 不是该boss的伤害不处理
- continue
-
- # 还在伤血中
- if playerID in hurtPlayerDict:
- newTeamID = hurtPlayerDict[playerID]
- if newTeamID != teamID:
- shuntPlayerDict[playerID] = [npcID, newTeamID, 0]
- shuntChange = True
- GameWorld.DebugLog("boss分流 -> 玩家对该boss的伤害变更队伍!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"
- % (playerID, npcID, teamID, newTeamID), lineID)
- elif relatedTick:
- shuntPlayerDict[playerID] = [npcID, newTeamID, 0]
- shuntChange = True
- GameWorld.DebugLog("boss分流 -> 玩家对该boss的关联状态转为伤害状态!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"
- % (playerID, npcID, teamID, newTeamID), lineID)
-
- # 不在伤血中,更新关联tick
- elif not relatedTick:
- shuntPlayerDict[playerID] = [npcID, teamID, tick]
- shuntChange = True
- GameWorld.DebugLog("boss分流 -> 玩家不在该boss伤血中,设置为关联状态!playerID=%s,npcID=%s,teamID=%s,tick=%s"
- % (playerID, npcID, teamID, tick), lineID)
-
- # 伤先优先级最高,可直接覆盖更新
- for playerID, teamID in hurtPlayerDict.items():
- if playerID not in shuntPlayerDict:
- shuntPlayerDict[playerID] = [npcID, teamID, 0]
- shuntChange = True
- GameWorld.DebugLog("boss分流 -> 新增玩家对boss伤害!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)
-
- elif shuntPlayerDict[playerID][0] != npcID:
- shuntPlayerDict[playerID] = [npcID, teamID, 0]
- shuntChange = True
- GameWorld.DebugLog("boss分流 -> 伤害转移到本boss上!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)
-
- if shuntChange:
- PyGameData.g_bossShuntPlayerInfo[key] = shuntPlayerDict
- GameServer_WorldBossShuntInfo(mapID, lineID)
- return
-
- def __GetAtkObjByHurtList(self, npcHurtList):
- '''第一个可攻击的最大伤血对象,也是实际的归属者或队伍
- 因为玩家伤血掉线、死亡有一定时间的保留机制,故最大伤血不一定是可攻击目标(归属者)
- 注意: 该规则必须与最终算归属的规则一致,不然可能导致归属错乱
- '''
- for index in xrange(npcHurtList.GetHurtCount()):
- #获得伤血对象
- hurtObj = npcHurtList.GetHurtAt(index)
-
- curPlayer, curTeam = self.__GetTagByHurtObj(hurtObj, True)
-
- if curPlayer or curTeam:
- return hurtObj
- return
-
def IsInHurtProtect(self):
'''NPC是否伤血保护中
因为手游比较会出现网络切换的情况,此时会可能会引起掉线重连
@@ -3457,6 +3233,8 @@
self.ClearNPCHurtList()
#清除所有身上buff
self.ClearAllBuff(isClearAuraBuff)
+ curNPC = self.__Instance
+ NPCHurtManager.ClearPlayerHurtList(curNPC)
return True
#---------------------------------------------------------------------
@@ -4234,7 +4012,9 @@
curNPC = self.__Instance
self.__FeelPlayerList = []
- npcHurtList = curNPC.GetPlayerHurtList()
+ npcHurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
+ if not npcHurtList:
+ npcHurtList = curNPC.GetPlayerHurtList()
#npcHurtList.Sort() #这里不排序,只要有伤害就算
eventPlayerList = []
@@ -4672,7 +4452,6 @@
#objID = curNPC.GetID()
npcID = curNPC.GetNPCID()
self.__LastHurtPlayer = self.__FindLastTimeHurtObjEx()
- self.__MaxHurtPlayer = self.__FindBossMaxHurtObj() # py自定义伤血所得到的Boss最大伤血玩家
isGameBoss = ChConfig.IsGameBoss(curNPC)
self.__AllKillerDict, curTeam, hurtType, hurtID = self.__FindNPCKillerInfo(isGameBoss)
@@ -4691,8 +4470,6 @@
for curPlayer in self.__AllKillerDict.values():
if not self.__LastHurtPlayer:
self.__LastHurtPlayer = curPlayer
- if not self.__MaxHurtPlayer:
- self.__MaxHurtPlayer = curPlayer
if not self.__Killer:
self.__Killer = curPlayer
@@ -4736,12 +4513,7 @@
if OnNPCDie:
OnNPCDie(curNPC, hurtType, hurtID)
-
- #执行玩家连轧逻辑
- lastTimeHurtObj = self.__FindLastTimeHurtObj()
- if lastTimeHurtObj[0] == None and lastTimeHurtObj[1] == None:
- return
-
+
return
## 最后一击处理
@@ -4757,35 +4529,6 @@
return
curNPC = self.__Instance
- #npcID = curNPC.GetNPCID()
- #mapID = GameWorld.GetMap().GetMapID()
- #playerName = lastHurtPlayer.GetPlayerName()
-
- #===========================================================================================
- # # 最后一击奖励
- # lastTimeHurtBossAwardDict = ReadChConfig.GetEvalChConfig("LastTimeHurtBossAward")
- # if npcID in lastTimeHurtBossAwardDict:
- # giveItemList = lastTimeHurtBossAwardDict[npcID]
- # playerID = lastHurtPlayer.GetPlayerID()
- # bossAwardMailInfo = ReadChConfig.GetEvalChConfig("LastTimeHurtBossAwardMail")
- # title, content, getDays = bossAwardMailInfo
- # mailContent = content % (npcID)
- # PlayerControl.SendMail(title, mailContent, getDays, [playerID], giveItemList)
- #
- # # 广播
- # if len(giveItemList) > 0:
- # itemID = giveItemList[0][0] # 默认取第一个奖励物品广播
- # PlayerControl.WorldNotify(0, "GeRen_liubo_698214", [playerName, mapID, npcID, itemID, itemID])
- #===========================================================================================
-
- #===========================================================================================
- # # 最后一击广播
- # LastHurtNotifyDict = ReadChConfig.GetEvalChConfig("LastHurtNotify")
- # for npcIDTuple, notifyMark in LastHurtNotifyDict.items():
- # if npcID in npcIDTuple:
- # PlayerControl.WorldNotify(0, notifyMark, [playerName, mapID, npcID])
- # break
- #===========================================================================================
# VIP杀怪加攻
PlayerVip.DoAddVIPKillLVExp(lastHurtPlayer, curNPC)
@@ -4851,14 +4594,6 @@
if isGameBoss:
GameWorld.Log(" 归属最大伤血队伍: npcID=%s,dropOwnerType=%s,teamID=%s" % (npcID, dropOwnerType, curTeam.GetTeamID()))
return killerDict, curTeam, ChConfig.Def_NPCHurtTypeTeam, curTeam.GetTeamID()
- # 最大伤血玩家 - 伤血不会被重置
- elif dropOwnerType == ChConfig.DropOwnerType_MaxHurtPlayer:
- if self.__MaxHurtPlayer:
- maxHurtPlayerID = self.__MaxHurtPlayer.GetPlayerID()
- if maxHurtPlayerID not in killerDict:
- killerDict[maxHurtPlayerID] = self.__MaxHurtPlayer
- #GameWorld.DebugLog(" 特殊归属最大伤害玩家: playerID=%s" % maxHurtPlayerID)
- return killerDict, None, ChConfig.Def_NPCHurtTypePlayer, maxHurtPlayerID
# 最大仇恨
elif dropOwnerType == ChConfig.DropOwnerType_MaxAngry:
@@ -4946,20 +4681,7 @@
return curTag, GameWorld.GetTeamManager().FindTeam(teamID)
#---------------------------------------------------------------------
- ## 获取补刀者,包含队伍
- # @param self 类实例
- # @return 返回值 玩家或者None
- # @remarks
- def __FindLastTimeHurtObj(self):
- curNPC = self.__Instance
- npcHurtList = curNPC.GetPlayerHurtList()
- if npcHurtList.GetHurtCount() <= 0:
- return (None, None)
-
- maxHurtObj = npcHurtList.GetLastTimeHurtValue()
- return self.__GetTagByHurtObj(maxHurtObj)
-
-
+
## 获取补刀者(这个绝对是玩家)
# @param self 类实例
# @return 返回值 玩家或者None
@@ -4968,17 +4690,6 @@
playerID = curNPC.GetDictByKey(ChConfig.Def_PlayerKey_LastHurt)
curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
- if not curPlayer:
- return None
-
- return curPlayer
-
- def __FindBossMaxHurtObj(self):
- # py自定义伤血所得到的Boss最大伤血玩家
- curNPC = self.__Instance
- maxHurtID = curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_BossMaxHurtID % (curNPC.GetID(), curNPC.GetNPCID()))
-
- curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(maxHurtID)
if not curPlayer:
return None
@@ -5137,8 +4848,6 @@
if not self.__LastHurtPlayer:
self.__LastHurtPlayer = playerlist[0]
- if not self.__MaxHurtPlayer:
- self.__MaxHurtPlayer = playerlist[0]
if not self.__Killer:
self.__Killer = playerlist[0]
maxHurtID = playerlist[0].GetPlayerID()
@@ -5217,8 +4926,6 @@
# 赶时间,先简单处理直接取最大等级的,之后可按实际情况来
if not self.__LastHurtPlayer:
self.__LastHurtPlayer = dropPlayer
- if not self.__MaxHurtPlayer:
- self.__MaxHurtPlayer = dropPlayer
if not self.__Killer:
self.__Killer = dropPlayer
maxHurtID = dropPlayer.GetPlayerID()
@@ -5441,14 +5148,10 @@
GameWorld.Log("Boss死亡: lineID=%s,objID=%s,npcID=%s,dropOwnerType=%s"
% (GameWorld.GetGameWorld().GetLineID(), curNPC.GetID(), curNPC.GetNPCID(), dropOwnerType))
if dropOwnerType == ChConfig.DropOwnerType_MaxHurt:
- maxHurtObj = self.RefreshHurtList(tick, refreshInterval)
- if maxHurtObj:
- ownerType, ownerID = maxHurtObj.GetValueType(), maxHurtObj.GetValueID()
- if ownerType == ChConfig.Def_NPCHurtTypeTeam:
- tagObj = self.__GetMaxHurtTeamPlayer(ownerID, isDead)
- elif ownerType == ChConfig.Def_NPCHurtTypePlayer:
- tagObj = GameWorld.GetObj(ownerID, IPY_GameWorld.gotPlayer)
-
+ maxHurtInfo = NPCHurtManager.RefreshHurtList(curNPC, tick, refreshInterval, isDead)
+ if maxHurtInfo:
+ tagObj, ownerType, ownerID = maxHurtInfo
+
elif dropOwnerType == ChConfig.DropOwnerType_Family:
ownerInfo = FamilyRobBoss.RefreshFamilyOwnerNPCHurt(self, curNPC, tick, refreshInterval)
if ownerInfo:
@@ -5576,16 +5279,20 @@
if isDead:
GameWorld.Log("Boss归属: key=%s,ownerType=%s,ownerID=%s" % (key, ownerType, ownerID))
+ hurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
# 刷新归属
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
- self.__AddDropOwnerPlayerBuff(curPlayer, tick)
- if dropOwnerType == ChConfig.DropOwnerType_Contend:
- curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, curNPC.GetID())
+ if not hurtList or hurtList.HaveHurtValue(playerID):
+ hurtType, hurtID = ChConfig.Def_NPCHurtTypePlayer, playerID
+ killerDict[playerID] = curPlayer
+ self.__AddDropOwnerPlayerBuff(curPlayer, tick)
+ if dropOwnerType == ChConfig.DropOwnerType_Contend:
+ curPlayer.SetDict(ChConfig.Def_PlayerKey_ContendNPCObjID, curNPC.GetID())
+ else:
+ BuffSkill.DelBuffBySkillID(curPlayer, ChConfig.Def_SkillID_DropOwnerBuff, tick, buffOwner=curNPC)
elif ownerType == ChConfig.Def_NPCHurtTypeTeam:
curTeam = GameWorld.GetTeamManager().FindTeam(ownerID)
@@ -5605,6 +5312,7 @@
continue
if curTeamPlayer.GetCopyMapID() == GameWorld.GetGameWorld().GetCopyMapID() \
+ and (not hurtList or hurtList.HaveHurtValue(curTeamPlayer.GetPlayerID()))\
and self.GetIsInRefreshPoint(curTeamPlayer.GetPosX(), curTeamPlayer.GetPosY(), refreshPoint) \
and AttackCommon.CheckKillNPCByCnt(curTeamPlayer, curNPC, False) and curTeamPlayer.GetVisible():
self.__AddDropOwnerPlayerBuff(curTeamPlayer, tick)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtManager.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtManager.py
new file mode 100644
index 0000000..7e39069
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/NPC/NPCHurtManager.py
@@ -0,0 +1,953 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package NPCHurtManager
+#
+# @todo:NPC伤血管理
+# @author hxp
+# @date 2019-12-06
+# @version 1.0
+#
+# 详细描述: NPC伤血管理
+# 因为加入了协助系统,协助玩家暂无上限限制,所以总伤害会超过20亿
+# 原伤血列表不支持协助、不支持总伤害超过20亿,故重写一套py版伤血管理,函数命名与c++接口提供的函数名一致
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-12-06 21:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import PyGameData
+import PlayerAssist
+import AttackCommon
+import IPY_GameWorld
+import PlayerControl
+import ChPyNetSendPack
+import ItemControler
+import NetPackCommon
+import IpyGameDataPY
+import ShareDefine
+import PlayerTeam
+import NPCCommon
+import ChConfig
+
+import time
+
+
+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 PlayerHurtList():
+ ''' 伤血列表, 类似 IPY_GameObj.IPY_PlayerHurtList
+ '''
+
+ 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.__noAssitPlayerIDDict = {} # 非协助玩家ID字典 {playerID:[assistPlayerID, ...], ...}
+ self.__assistPlayerIDDict = {} # 协助玩家对应目标ID字典 {assistPlayerID:tagPlayerID, ...}
+ self.__hurtPlayerDict = {} # 所有伤血玩家个体实例字典,含协助玩家 {playerID:HurtValueObj, ...}
+
+ self.__hurtSortList = []
+ self.__hurtDict = {} # 伤血列表实例字典,实际的NPC伤血列表实例,可能不是玩家{(hurtID, hurtType):HurtValueObj, ...}
+ return
+
+ def Clear(self):
+ # 在NPC触发重置伤血时重置,不重置协助关系及伤血玩家实例,只重置伤血值
+
+ GameWorld.DebugLog("Clear重置NPC伤血!", self.npcID, self.lineID)
+ self.__hurtSortList = []
+ self.__hurtDict = {}
+ # 重置所有玩家伤血值
+ for hurtObj in self.__hurtPlayerDict.values():
+ hurtObj.SetHurtValue(0)
+ return
+
+ def OnDelete(self):
+ # 删除伤血列表,NPC死亡调用
+
+ cancelPlayerIDList = self.__noAssitPlayerIDDict.keys()
+ if cancelPlayerIDList:
+ mapID = GameWorld.GetMap().GetMapID()
+ queryData = [mapID, self.lineID, self.npcID, self.objID, "OnBossDead", cancelPlayerIDList]
+ PlayerAssist.QueryGameServer_PlayerAssist(0, "OnCancelBossRequestAssist", queryData)
+
+ return
+
+ def __GetHurtTypeObj(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]
+ # 因为伤血玩家可能在某些情况下创建了没有名字的实例,所以这里在有传入名字时进行强制更新
+ if playerName:
+ hurtPlayer.SetHurtName(playerName)
+ return hurtPlayer
+
+ def AddAssistPlayer(self, assistPlayerID, assistPlayerName, tagPlayerID, tagPlayerName, tagTeamID):
+ ## 添加助战玩家
+ # @param assistPlayerID: 协助玩家ID
+ # @param tagPlayerID: 目标玩家ID,即发布协助的玩家ID
+
+ if assistPlayerID == tagPlayerID:
+ # 不能协助自己
+ return
+
+ if tagPlayerID not in self.__noAssitPlayerIDDict or tagPlayerID not in self.__hurtPlayerDict:
+ GameWorld.ErrLog("新增协助玩家异常,不存在该常规伤血玩家,无法协助他!assistPlayerID=%s,tagPlayerID=%s"
+ % (assistPlayerID, tagPlayerID), self.npcID, self.lineID)
+ return
+
+ GameWorld.DebugLog("新增协助玩家: assistPlayerID=%s,tagPlayerID=%s,tagTeamID=%s"
+ % (assistPlayerID, tagPlayerID, tagTeamID), self.npcID, self.lineID)
+
+ if assistPlayerID in self.__noAssitPlayerIDDict:
+ GameWorld.DebugLog("原来为常规玩家,需要先删除!", self.npcID, self.lineID)
+ self.DelHurtPlayer(assistPlayerID, "BecomeAssistPlayer")
+
+ assistPlayerIDList = self.__noAssitPlayerIDDict[tagPlayerID]
+ if assistPlayerID not in assistPlayerIDList:
+ assistPlayerIDList.append(assistPlayerID)
+ self.__assistPlayerIDDict[assistPlayerID] = tagPlayerID
+
+ GameWorld.DebugLog(" self.__noAssitPlayerIDDict=%s" % (self.__noAssitPlayerIDDict), self.npcID, self.lineID)
+ GameWorld.DebugLog(" self.__assistPlayerIDDict=%s" % (self.__assistPlayerIDDict), self.npcID, self.lineID)
+ return
+
+ def DelHurtPlayer(self, playerID, reason, isMapServerDel=True):
+ ## 删除伤血玩家, 可能由地图、GameServer触发删除
+
+ if playerID not in self.__hurtPlayerDict:
+ return
+
+ GameWorld.DebugLog("删除伤血玩家: playerID=%s,reason=%s,isMapServerDel=%s" % (playerID, reason, isMapServerDel), self.npcID, self.lineID)
+
+ #非协助玩家
+ if playerID in self.__noAssitPlayerIDDict:
+ # 先清玩家伤血
+ self.__ClearPlayerHurt(playerID)
+
+ assistPlayerIDList = self.__noAssitPlayerIDDict.pop(playerID, [])
+ GameWorld.DebugLog(" 是常规玩家,同时删除协助玩家: assistPlayerIDList=%s" % assistPlayerIDList, self.npcID, self.lineID)
+
+ # 强制删除所有协助该玩家,列表倒序删
+ for assistPlayerID in assistPlayerIDList[::-1]:
+ self.DelHurtPlayer(assistPlayerID, "RequestPlayerCancel_%s" % reason, isMapServerDel)
+
+ # 地图删除的同步GameServer
+ if isMapServerDel:
+ mapID = GameWorld.GetMap().GetMapID()
+ cancelPlayerIDList = [playerID]
+ queryData = [mapID, self.lineID, self.npcID, self.objID, reason, cancelPlayerIDList]
+ PlayerAssist.QueryGameServer_PlayerAssist(0, "OnCancelBossRequestAssist", queryData)
+
+ # 协助玩家
+ elif playerID in self.__assistPlayerIDDict:
+ # 先清玩家伤血
+ self.__ClearPlayerHurt(playerID)
+
+ tagPlayerID = self.__assistPlayerIDDict.pop(playerID, 0)
+
+ # 移除协助对应关系
+ if tagPlayerID in self.__noAssitPlayerIDDict:
+ assistPlayerIDList = self.__noAssitPlayerIDDict[tagPlayerID]
+ if playerID in assistPlayerIDList:
+ assistPlayerIDList.remove(playerID)
+ GameWorld.DebugLog(" 是协助玩家,删除协助关系: tagPlayerID=%s,assistPlayerIDList=%s"
+ % (tagPlayerID, self.__noAssitPlayerIDDict[tagPlayerID]), self.npcID, self.lineID)
+
+ # 地图删除的同步GameServer
+ if isMapServerDel:
+ mapID = GameWorld.GetMap().GetMapID()
+ queryData = [mapID, self.lineID, self.npcID, self.objID, reason]
+ PlayerAssist.QueryGameServer_PlayerAssist(playerID, "OnCancelBossAssist", queryData)
+
+ self.__hurtPlayerDict.pop(playerID) # 放在最后pop伤血实例
+
+ if not self.__hurtPlayerDict:
+ GameWorld.DebugLog("没有伤血玩家了!", self.npcID, self.lineID)
+ self.Clear()
+
+ return
+
+ def HaveHurtValue(self, playerID):
+ ## 是否对该boss有伤害贡献
+
+ if playerID not in self.__hurtPlayerDict:
+ return False
+
+ hurtPlayer = self.__GetHurtPlayer(playerID)
+ if hurtPlayer.GetHurtValue():
+ return True
+
+ if playerID in self.__noAssitPlayerIDDict:
+ assistPlayerIDList = self.__noAssitPlayerIDDict[playerID]
+ for assistPlayerID in assistPlayerIDList:
+ assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)
+ if assHurtPlayer.GetHurtValue():
+ return True
+
+ return False
+
+ def GetPlayerHurtDetail(self, playerID):
+ ## 玩家伤血输出明细 - 暂时GM命令输出数据用
+ # @return: hurtValue, {assistPlayerID:hurtValue, ...}
+
+ if playerID in self.__noAssitPlayerIDDict:
+ hurtPlayer = self.__GetHurtPlayer(playerID)
+ assistPlayerHurtDict = {}
+ assistPlayerIDList = self.__noAssitPlayerIDDict[playerID]
+ for assistPlayerID in assistPlayerIDList:
+ assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)
+ assistPlayerHurtDict[assistPlayerID] = assHurtPlayer.GetHurtValue()
+ return hurtPlayer.GetHurtValue(), assistPlayerHurtDict
+
+ if playerID in self.__assistPlayerIDDict:
+ assHurtPlayer = self.__GetHurtPlayer(playerID)
+ return assHurtPlayer.GetHurtValue(), {}
+
+ return 0, {}
+
+ def GetNoAssitPlayerIDDict(self): return self.__noAssitPlayerIDDict
+ def GetAssistPlayerIDDict(self): return self.__assistPlayerIDDict
+
+ def IsNoAssistPlayer(self, playerID):
+ ## 是否非助战伤血玩家
+ return playerID in self.__noAssitPlayerIDDict
+
+ def IsAssistPlayer(self, playerID):
+ ## 是否助战伤血玩家
+ return playerID in self.__assistPlayerIDDict
+
+ def OnHurtPlayerEnterTeam(self, playerID, playerName, befTeamID, newTeam, tick):
+ ''' 伤血玩家加入队伍
+ 个人伤害并入队伍伤害,个人所有协助玩家伤害重新统计,表现在协助伤害排行榜,协助玩家之后的伤害计入队伍伤害
+ '''
+ if playerID not in self.__noAssitPlayerIDDict:
+ # 只处理非协助玩家
+ return
+
+ newTeamID = newTeam.GetTeamID()
+
+ if befTeamID:
+ # 因为必须是先退队再进队的,所以进入队伍时不存在有之前队伍ID的情况
+ GameWorld.ErrLog("玩家进入时已有队伍!playerID=%s,befTeamID=%s,newTeamID=%s" % (playerID, befTeamID, newTeamID), self.npcID, self.lineID)
+ return
+
+ # 更新玩家个人伤血类型、ID
+ hurtPlayer = self.__GetHurtPlayer(playerID, playerName)
+ hurtPlayer.SetValueType(ChConfig.Def_NPCHurtTypeTeam)
+ hurtPlayer.SetValueID(newTeamID)
+
+ # 删除个人伤血列表实例
+ playerTotalHurt = 0
+ playerHurtKey = (playerID , ChConfig.Def_NPCHurtTypePlayer)
+ if playerHurtKey in self.__hurtDict:
+ playerHurtObj = self.__hurtDict.pop(playerHurtKey)
+ playerTotalHurt = playerHurtObj.GetHurtValue()
+
+ GameWorld.DebugLog("常规伤血玩家加入队伍: playerID=%s,playerTotalHurt=%s,newTeamID=%s"
+ % (playerID, playerTotalHurt, newTeamID), self.npcID, self.lineID)
+
+ # 伤血并入队伍伤血
+ if playerTotalHurt:
+ teamHurtObj = self.__GetHurtTypeObj(newTeamID , ChConfig.Def_NPCHurtTypeTeam, playerName)
+ teamHurtValue = teamHurtObj.GetHurtValue()
+ updTeamHurtValue = teamHurtValue + playerTotalHurt
+ teamHurtObj.SetHurtValue(updTeamHurtValue)
+ GameWorld.DebugLog(" 个人总伤血并入新队伍伤血: teamHurtValue=%s,playerTotalHurt=%s,updTeamHurtValue=%s"
+ % (teamHurtValue, playerTotalHurt, updTeamHurtValue), self.npcID, self.lineID)
+ self.__UpdHurtTeamName(newTeamID)
+
+ self.Sort()
+ return
+
+ def OnHurtPlayerLeaveTeam(self, playerID, leaveTeamID, tick):
+ ''' 伤血玩家退出队伍
+ 原队伍伤害不变,个人及所有协助玩家伤害重新计算,协助玩家之后的伤害计入个人伤害;
+ 离线被踢离队的情况协助玩家可继续协助输出并获得协助奖励,伤害计入个人,但是离线玩家无法获得归属
+ '''
+ if playerID not in self.__noAssitPlayerIDDict:
+ # 只处理非协助玩家
+ return
+
+ # 玩家个人伤血类型、ID
+ hurtPlayer = self.__GetHurtPlayer(playerID)
+ hurtPlayer.SetValueType(ChConfig.Def_NPCHurtTypePlayer)
+ hurtPlayer.SetValueID(playerID)
+
+ # 统计个人及协助总伤害
+ playerTotalHurt = hurtPlayer.GetHurtValue()
+ assistPlayerIDList = self.__noAssitPlayerIDDict.get(playerID, [])
+ for assistPlayerID in assistPlayerIDList:
+ assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID)
+ playerTotalHurt += assistHurtPlayer.GetHurtValue()
+
+ GameWorld.DebugLog("常规伤血玩家离开队伍: playerID=%s,playerTotalHurt=%s,leaveTeamID=%s"
+ % (playerID, playerTotalHurt, leaveTeamID), self.npcID, self.lineID)
+
+ if not playerTotalHurt:
+ return
+
+ # 原队伍扣除对应伤害
+ teamHurtKey = (leaveTeamID , ChConfig.Def_NPCHurtTypeTeam)
+ if teamHurtKey in self.__hurtDict:
+ teamHurtObj = self.__hurtDict[teamHurtKey]
+ teamHurtValue = teamHurtObj.GetHurtValue()
+ updTeamHurtValue = max(0, teamHurtValue - playerTotalHurt)
+ teamHurtObj.SetHurtValue(updTeamHurtValue)
+ GameWorld.DebugLog(" 原队伍伤害扣除: teamHurtValue=%s,playerTotalHurt=%s,updTeamHurtValue=%s"
+ % (teamHurtValue, playerTotalHurt, updTeamHurtValue), self.npcID, self.lineID)
+ self.__UpdHurtTeamName(leaveTeamID)
+
+ # 创建新个人伤害列表实例
+ newHurtObj = self.__GetHurtTypeObj(playerID, ChConfig.Def_NPCHurtTypePlayer, hurtPlayer.GetHurtName())
+ newHurtObj.SetHurtValue(playerTotalHurt)
+
+ self.Sort()
+ return
+
+ def __UpdHurtTeamName(self, teamID):
+ ## 更新队伍伤血名称,队长在优先使用队长名字,否则使用任意一个在线攻击此boss的非协助队员名
+
+ hurtTeamObj = self.__GetHurtTypeObj(teamID , ChConfig.Def_NPCHurtTypeTeam)
+
+ updName = ""
+ copyPlayerManager = GameWorld.GetMapCopyPlayerManager()
+ mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)
+ for memPlayerID in mapTeamPlayerIDList:
+ if memPlayerID not in self.__noAssitPlayerIDDict:
+ continue
+ player = copyPlayerManager.FindPlayerByID(memPlayerID)
+ if not player:
+ continue
+ playerName = player.GetPlayerName()
+ if player.GetTeamLV() == IPY_GameWorld.tmlLeader:
+ hurtTeamObj.SetHurtName(playerName)
+ GameWorld.DebugLog(" 更新队伍名称,使用队长名称!teamID=%s" % teamID, self.npcID, self.lineID)
+ return
+ if not updName:
+ updName = playerName
+
+ if updName:
+ hurtTeamObj.SetHurtName(updName)
+ GameWorld.DebugLog(" 更新队伍名称,使用队员名称!teamID=%s" % teamID, self.npcID, self.lineID)
+ return
+
+ def AddPlayerHurtValue(self, atkPlayerID, atkName, value, atkTeamID=0, isSort=False):
+ ## 添加玩家伤血
+
+ tagPlayerID = 0 # 协助目标玩家ID
+ atkHurtPlayer = self.__GetHurtPlayer(atkPlayerID, atkName)
+ if atkPlayerID in self.__assistPlayerIDDict:
+ tagPlayerID = self.__assistPlayerIDDict[atkPlayerID]
+ tagHurtPlayer = self.__GetHurtPlayer(tagPlayerID)
+ tagPlayerName = tagHurtPlayer.GetHurtName()
+ hurtID, hurtType = tagHurtPlayer.GetValueID(), tagHurtPlayer.GetValueType()
+ #GameWorld.DebugLog("协助玩家伤血: atkPlayerID=%s,value=%s,tagPlayerID=%s" % (atkPlayerID, value, tagPlayerID), self.npcID, self.lineID)
+
+ else:
+ if atkTeamID:
+ hurtID, hurtType = atkTeamID, ChConfig.Def_NPCHurtTypeTeam
+ else:
+ hurtID, hurtType = atkPlayerID, ChConfig.Def_NPCHurtTypePlayer
+ atkHurtPlayer.SetValueType(hurtType)
+ atkHurtPlayer.SetValueID(hurtID)
+ if atkPlayerID not in self.__noAssitPlayerIDDict:
+ self.__noAssitPlayerIDDict[atkPlayerID] = []
+ GameWorld.DebugLog("新增常规玩家: atkPlayerID=%s" % (atkPlayerID), self.npcID, self.lineID)
+ #GameWorld.DebugLog("常规玩家伤血: atkPlayerID=%s,value=%s" % (atkPlayerID, value), self.npcID, self.lineID)
+
+ hurtObj = self.__GetHurtTypeObj(hurtID, hurtType, tagPlayerName if tagPlayerID else atkName)
+
+ # 伤血列表伤血累加
+ befValue = hurtObj.GetHurtValue()
+ updValue = befValue + value
+ hurtObj.SetHurtValue(updValue)
+ isNewHurt = befValue == 0 and updValue > 0
+
+ # 伤血玩家伤血累加,这个仅伤血玩家自己的个人输出,非伤血列表中的汇总输出
+ updAtkHurtValue = atkHurtPlayer.GetHurtValue() + value
+ atkHurtPlayer.SetHurtValue(updAtkHurtValue)
+
+ #GameWorld.DebugLog(" hurtID=%s,hurtType=%s,hurtValue=%s (%s + %s) updAtkHurtValue=%s"
+ # % (hurtID, hurtType, updValue, befValue, value, updAtkHurtValue), self.npcID, self.lineID)
+
+ if isNewHurt or isSort:
+ self.Sort()
+
+ return
+
+ def RefreshHurtList(self, tick, refreshInterval=3000, isDead=False):
+ ## 刷新伤血列表
+ # @return: atkPlayer, hurtID, hurtType
+
+ curNPC = self.curNPC
+ if not self.__hurtDict:
+ return
+
+ if not isDead:
+ if refreshInterval and tick - curNPC.GetDictByKey(ChConfig.Def_NPC_Dict_LastRefreshHurtTick) < refreshInterval:
+ return self.__GetAtkObjByHurtList()
+
+ curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)
+
+ hurtPlayerDict = {} # {playerID:teamID, ...}
+ refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
+ for hurtKey in self.__hurtDict.keys():
+ #获得伤血对象
+ hurtID, hurtType = hurtKey
+ if not hurtID:
+ continue
+
+ if hurtType == ChConfig.Def_NPCHurtTypePlayer:
+ teamID = 0
+ playerID = hurtID
+ if self.__UnAssistPlayerHurtValidLogic(playerID, refreshPoint, tick):
+ hurtPlayerDict[playerID] = teamID
+
+ elif hurtType == ChConfig.Def_NPCHurtTypeTeam:
+ teamID = hurtID
+ mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)
+ for teamPlayerID in mapTeamPlayerIDList:
+ if self.__UnAssistPlayerHurtValidLogic(teamPlayerID, refreshPoint, tick):
+ hurtPlayerDict[teamPlayerID] = teamID
+
+ mapID = GameWorld.GetMap().GetMapID()
+ if NPCCommon.IsMapNeedBossShunt(mapID):
+ self.__UpdBossShuntInfo(mapID, hurtPlayerDict, tick)
+
+ self.Sort()
+
+ if isDead:
+ self.__DoGiveAssistAward()
+
+ isInHurt = self.__hurtSortList != []
+ curNPC.SetDict(ChConfig.Def_NPC_Dict_InHurtProtect, isInHurt)
+ return self.__GetAtkObjByHurtList()
+
+ def __UnAssistPlayerHurtValidLogic(self, playerID, refreshPoint, tick):
+ ## 非协助玩家伤血有效性检查逻辑
+
+ valid = False
+ checkPlayerIDList = [playerID] + self.__noAssitPlayerIDDict.get(playerID, []) # 检查所有有关系的玩家ID
+ for checkPlayerID in checkPlayerIDList:
+ if self.__IsPlayerHurtValid(checkPlayerID, refreshPoint, tick):
+ valid = True
+ else:
+ self.__ClearPlayerHurt(checkPlayerID)
+
+ return valid
+
+ def __IsPlayerHurtValid(self, playerID, refreshPoint, tick):
+ ## 玩家伤血是否还有效
+
+ if playerID not in self.__hurtPlayerDict:
+ return False
+
+ hurtPlayer = self.__GetHurtPlayer(playerID)
+ hurtValue = hurtPlayer.GetHurtValue()
+ if not hurtValue:
+ return False
+
+ player = GameWorld.GetMapCopyPlayerManager().FindPlayerByID(playerID)
+ if player:
+ if playerID in self.__noAssitPlayerIDDict:
+ if not AttackCommon.CheckKillNPCByCnt(player, self.curNPC, False):
+ GameWorld.DebugLog("非协助伤血玩家没有攻击boss次数,不计!playerID=%s" % playerID, self.npcID, self.lineID)
+ return False
+
+ if player.GetInitOK() and (not player.GetVisible() or player.GetSightLevel() != self.curNPC.GetSightLevel()):
+ GameWorld.DebugLog("伤血玩家不可见,不计!playerID=%s" % playerID, self.npcID, self.lineID)
+ return False
+
+ if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:
+ deadTime = player.NomalDictGetProperty(ChConfig.Def_Player_Dict_DeadTime)
+ if time.time() - deadTime >= IpyGameDataPY.GetFuncCfg("BossHurtValue", 1):
+ GameWorld.DebugLog("伤血玩家死亡超过伤血保护时长,不计!playerID=%s" % playerID, self.npcID, self.lineID)
+ return False
+
+ if not self.__GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
+ GameWorld.DebugLog("伤血玩家不在boss范围内,不计!playerID=%s" % playerID, self.npcID, self.lineID)
+ return False
+
+ return True
+
+ else:
+
+ # 是否离线超过3分钟,下线坐标是否不在boss区域等
+ leaveTick = PlayerControl.GetPlayerLeaveServerTick(playerID)
+ leavePos = PlayerControl.GetPlayerLeaveServerPos(playerID)
+ if not leaveTick or not leavePos:
+ GameWorld.DebugLog("伤血玩家不在本地图或已长久离线,不计!playerID=%s" % playerID, self.npcID, self.lineID)
+ return False
+
+ if tick - leaveTick > ChConfig.Def_PlayerOfflineProtectTime:
+ GameWorld.DebugLog("伤血离线玩家超过保护时长,不计!playerID=%s,tick=%s,leaveTick=%s" % (playerID, tick, leaveTick), self.npcID, self.lineID)
+ return False
+
+ if not self.__GetIsInRefreshPoint(leavePos[0], leavePos[1], refreshPoint):
+ GameWorld.DebugLog("伤血离线玩家不在保护区域内,不计!playerID=%s,leavePos=%s" % (playerID, leavePos), self.npcID, self.lineID)
+ return False
+
+ return True
+
+ return False
+
+ def __ClearPlayerHurt(self, playerID):
+ ## 清除玩家伤血,不删实例
+
+ if playerID not in self.__hurtPlayerDict:
+ return
+
+ hurtPlayer = self.__GetHurtPlayer(playerID)
+ hurtValue = hurtPlayer.GetHurtValue()
+ if not hurtValue:
+ return
+ hurtPlayer.SetHurtValue(0)
+
+ # 协助玩家
+ if playerID in self.__assistPlayerIDDict:
+ tagPlayerID = self.__assistPlayerIDDict[playerID]
+ tagHurtPlayer = self.__GetHurtPlayer(tagPlayerID)
+ hurtID = tagHurtPlayer.GetValueID()
+ hurtType = tagHurtPlayer.GetValueType()
+ else:
+ hurtID = hurtPlayer.GetValueID()
+ hurtType = hurtPlayer.GetValueType()
+
+ GameWorld.DebugLog(" 清除玩家伤血: playerID=%s,hurtValue=%s,hurtID=%s,hurtType=%s"
+ % (playerID, hurtValue, hurtID, hurtType), self.npcID, self.lineID)
+
+ hurtKey = (hurtID, hurtType)
+ if hurtKey not in self.__hurtDict:
+ return
+
+ # 扣除伤血列表实例伤血
+ hurtObj = self.__GetHurtTypeObj(hurtID, hurtType)
+ befValue = hurtObj.GetHurtValue()
+ updValue = max(0, befValue - hurtValue)
+ hurtObj.SetHurtValue(updValue)
+ GameWorld.DebugLog(" 扣除伤血更新: hurtID=%s,hurtType=%s,befValue=%s,updValue=%s"
+ % (hurtID, hurtType, befValue, updValue), self.npcID, self.lineID)
+
+ if not updValue:
+ self.__hurtDict.pop(hurtKey)
+ else:
+ # 如果是非协助玩家队伍队员伤血被清,则更新伤血队伍名称
+ if playerID in self.__noAssitPlayerIDDict and hurtType == ChConfig.Def_NPCHurtTypeTeam:
+ self.__UpdHurtTeamName(hurtID)
+
+ return
+
+ def __GetAtkObjByHurtList(self):
+ '''第一个可攻击的最大伤血对象,也是实际的归属者或队伍
+ 因为玩家伤血掉线、死亡有一定时间的保留机制,故最大伤血不一定是可攻击目标(归属者)
+ 注意: 该规则必须与最终算归属的规则一致,不然可能导致归属错乱
+ @return: atkPlayer, hurtType, hurtID
+ '''
+
+ atkPlayer, atkHurtType, atkHurtID = None, 0, 0
+ curNPC = self.curNPC
+ refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
+ for hurtObj in self.__hurtSortList:
+
+ hurtID = hurtObj.GetValueID()
+ hurtType = hurtObj.GetValueType()
+
+ playerIDList = []
+ if hurtType == ChConfig.Def_NPCHurtTypePlayer:
+ assistPlayerIDList = self.__noAssitPlayerIDDict.get(hurtID, [])
+ playerIDList = [hurtID] + assistPlayerIDList
+
+ elif hurtType == ChConfig.Def_NPCHurtTypeTeam:
+ teamID = hurtID
+ mapTeamPlayerIDList = PlayerTeam.GetMapTeamPlayerIDList(teamID)
+ for teamPlayerID in mapTeamPlayerIDList:
+ if teamPlayerID not in self.__noAssitPlayerIDDict:
+ continue
+ playerIDList.append(teamPlayerID)
+ assistPlayerIDList = self.__noAssitPlayerIDDict.get(teamPlayerID, [])
+ playerIDList.extend(assistPlayerIDList)
+
+ else:
+ continue
+
+ maxHurtValue = 0
+ for playerID in playerIDList:
+
+ player = GameWorld.GetObj(playerID, IPY_GameWorld.gotPlayer)
+ if player == None:
+ continue
+
+ if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:
+ continue
+
+ if not player.GetVisible() or player.GetSightLevel() != curNPC.GetSightLevel():
+ continue
+
+ if not self.__GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
+ continue
+
+ if playerID not in self.__hurtPlayerDict:
+ 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
+
+ return atkPlayer, atkHurtType, atkHurtID
+
+ 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 __UpdBossShuntInfo(self, mapID, hurtPlayerDict, tick):
+ ## 更新本地图线路boss分流信息
+ npcID = self.npcID
+ lineID = self.lineID
+ key = (mapID, lineID)
+ shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
+
+ shuntChange = False
+ for playerID, shuntInfo in shuntPlayerDict.items():
+ bossID, teamID, relatedTick = shuntInfo
+ if bossID != npcID:
+ # 不是该boss的伤害不处理
+ continue
+
+ # 还在伤血中
+ if playerID in hurtPlayerDict:
+ newTeamID = hurtPlayerDict[playerID]
+ if newTeamID != teamID:
+ shuntPlayerDict[playerID] = [npcID, newTeamID, 0]
+ shuntChange = True
+ GameWorld.DebugLog("boss分流 -> 玩家对该boss的伤害变更队伍!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"
+ % (playerID, npcID, teamID, newTeamID), lineID)
+ elif relatedTick:
+ shuntPlayerDict[playerID] = [npcID, newTeamID, 0]
+ shuntChange = True
+ GameWorld.DebugLog("boss分流 -> 玩家对该boss的关联状态转为伤害状态!playerID=%s,npcID=%s,teamID=%s,newTeamID=%s"
+ % (playerID, npcID, teamID, newTeamID), lineID)
+
+ # 不在伤血中,更新关联tick
+ elif not relatedTick:
+ shuntPlayerDict[playerID] = [npcID, teamID, tick]
+ shuntChange = True
+ GameWorld.DebugLog("boss分流 -> 玩家不在该boss伤血中,设置为关联状态!playerID=%s,npcID=%s,teamID=%s,tick=%s"
+ % (playerID, npcID, teamID, tick), lineID)
+
+ # 伤先优先级最高,可直接覆盖更新
+ for playerID, teamID in hurtPlayerDict.items():
+ if playerID not in shuntPlayerDict:
+ shuntPlayerDict[playerID] = [npcID, teamID, 0]
+ shuntChange = True
+ GameWorld.DebugLog("boss分流 -> 新增玩家对boss伤害!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)
+
+ elif shuntPlayerDict[playerID][0] != npcID:
+ shuntPlayerDict[playerID] = [npcID, teamID, 0]
+ shuntChange = True
+ GameWorld.DebugLog("boss分流 -> 伤害转移到本boss上!playerID=%s,npcID=%s,teamID=%s" % (playerID, npcID, teamID), lineID)
+
+ if shuntChange:
+ PyGameData.g_bossShuntPlayerInfo[key] = shuntPlayerDict
+ NPCCommon.GameServer_WorldBossShuntInfo(mapID, lineID)
+ return
+
+ def __DoGiveAssistAward(self):
+ ''' 执行协助奖励逻辑
+ '''
+
+ liheItemID = 2244 # 感谢礼盒物品ID,暂山寨,感谢系统再修改
+
+ GameWorld.DebugLog("执行协助奖励逻辑", self.npcID, self.lineID)
+ copyPlayerManager = GameWorld.GetMapCopyPlayerManager()
+ for playerID, assistPlayerIDList in self.__noAssitPlayerIDDict.items():
+ if not assistPlayerIDList:
+ GameWorld.DebugLog("发布方没有发布协助,不给奖励: playerID=%s" % playerID, self.npcID, self.lineID)
+ continue
+
+ player = copyPlayerManager.FindPlayerByID(playerID)
+ if player:
+ GameWorld.DebugLog("发布方给感谢礼盒奖励: playerID=%s" % playerID, self.npcID, self.lineID)
+ ItemControler.GivePlayerItemOrMail(player, [[liheItemID, 1, 0]])
+ else:
+ GameWorld.DebugLog("发布方离线或不在本地图,不给感谢礼盒奖励: playerID=%s" % playerID, self.npcID, self.lineID)
+
+ for assistPlayerID in assistPlayerIDList:
+ assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID)
+ if not assistHurtPlayer.GetHurtValue():
+ GameWorld.DebugLog("协助方没有输出,不给奖励: assistPlayerID=%s" % assistPlayerID, self.npcID, self.lineID)
+ continue
+ assPlayer = copyPlayerManager.FindPlayerByID(assistPlayerID)
+ if not assPlayer:
+ GameWorld.DebugLog("协助方离线或不在本地图,不给活跃令奖励: assistPlayerID=%s" % assistPlayerID, self.npcID, self.lineID)
+ continue
+ GameWorld.DebugLog("协助方给活跃令奖励: assistPlayerID=%s" % assistPlayerID, self.npcID, self.lineID)
+ PlayerControl.GiveMoney(assPlayer, ShareDefine.TYPE_Price_FamilyActivity, 35)
+
+ return
+
+ def __CmpHurtValue(self, hurtObjA, hurtObjB):
+ ## 伤害排序比较函数
+ if hurtObjA.GetHurtValue() > hurtObjB.GetHurtValue():
+ return 1
+ if hurtObjA.GetHurtValue() == hurtObjB.GetHurtValue():
+ return 0
+ return -1
+
+ def Sort(self, isSync=True):
+ ## 伤血排序
+ self.__hurtSortList = sorted(self.__hurtDict.values(), cmp=self.__CmpHurtValue, reverse=True)
+
+ if not isSync:
+ return
+
+ syncPlayerIDList = self.__noAssitPlayerIDDict.keys() + self.__assistPlayerIDDict.keys()
+ if not syncPlayerIDList:
+ return
+
+ # 暂定排序后默认同步伤血列表给所有相关玩家,伤血为0的不同步前端,仅用于后端逻辑用
+ hurtValueList = []
+ for hurtObj in self.__hurtSortList:
+ hurtValue = hurtObj.GetHurtValue()
+ if not hurtValue:
+ continue
+ 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)
+
+ bossHurtInfoPack = ChPyNetSendPack.tagMCBossHurtValueRankInfo()
+ bossHurtInfoPack.ObjID = self.objID
+ bossHurtInfoPack.HurtValueList = hurtValueList
+ bossHurtInfoPack.HurtCount = len(hurtValueList)
+
+ assistHurtValueListDict = {}
+ copyPlayerManager = GameWorld.GetMapCopyPlayerManager()
+ for playerID in syncPlayerIDList:
+ player = copyPlayerManager.FindPlayerByID(playerID)
+ if not player:
+ continue
+
+ if playerID in self.__noAssitPlayerIDDict:
+ assTagPlayerID = playerID
+ elif playerID in self.__assistPlayerIDDict:
+ assTagPlayerID = self.__assistPlayerIDDict[playerID]
+ else:
+ continue
+
+ if assTagPlayerID not in assistHurtValueListDict:
+ assistPlayerIDList = self.__noAssitPlayerIDDict[assTagPlayerID]
+ assistHurtValueList = []
+ for assistPlayerID in assistPlayerIDList:
+ assHurtPlayer = self.__GetHurtPlayer(assistPlayerID)
+ assHurtValue = assHurtPlayer.GetHurtValue()
+ if not assHurtValue:
+ continue
+ assHurtValueObj = ChPyNetSendPack.tagMCBossHurtValueAssist()
+ assHurtValueObj.PlayerID = assHurtPlayer.GetValueID()
+ assHurtValueObj.PlayerName = assHurtPlayer.GetHurtName()
+ assHurtValueObj.HurtValue = assHurtValue % ShareDefine.Def_PerPointValue
+ assHurtValueObj.HurtValueEx = assHurtValue / ShareDefine.Def_PerPointValue
+ assistHurtValueList.append(assHurtValueObj)
+ assistHurtValueListDict[assTagPlayerID] = assistHurtValueList
+
+ assistHurtValueList = assistHurtValueListDict[assTagPlayerID]
+ bossHurtInfoPack.AssistHurtValueList = assistHurtValueList
+ bossHurtInfoPack.AssistHurtCount = len(assistHurtValueList)
+ NetPackCommon.SendFakePack(player, bossHurtInfoPack)
+
+ return
+
+ 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
+
+def OnPlayerLeaveMap(curPlayer):
+ ## 玩家离开地图处理
+
+ playerID = curPlayer.GetPlayerID()
+ for hurtList in PyGameData.g_npcHurtDict.values():
+ if hurtList.IsNoAssistPlayer(playerID) or hurtList.IsAssistPlayer(playerID):
+ GameWorld.DebugLog("玩家离开地图, 删除boss伤血玩家!npcID=%s" % (hurtList.npcID), playerID)
+ hurtList.DelHurtPlayer(playerID, "LeaveMap")
+ break
+
+ return
+
+def OnSetAssistTagPlayerID(curPlayer, value):
+ '''玩家更新了新的协助对象玩家ID
+ 需要 清除本地图中玩家以非协助身份正在攻击的boss
+
+ 以协助身份攻击的通过GameServer进行清除,因为玩家可能不和协助目标同一个地图
+ 比如先点了协助A玩家,还没过去的时候,又点了协助B玩家,所以需要通过GameServer清除协助目标的相关数据
+ '''
+
+ if not value:
+ # 只处理有协助目标的情况
+ return
+
+ playerID = curPlayer.GetPlayerID()
+ for hurtList in PyGameData.g_npcHurtDict.values():
+ if hurtList.IsNoAssistPlayer(playerID):
+ GameWorld.DebugLog("玩家开始协助其他人, 删除该boss伤血!npcID=%s" % (hurtList.npcID), playerID)
+ hurtList.DelHurtPlayer(playerID, "StartAssistBoss")
+ break
+
+ return
+
+def ClearPlayerHurtList(curNPC):
+ ## 清空伤血列表
+ defendHurtList = GetPlayerHurtList(curNPC)
+ if not defendHurtList:
+ return
+ defendHurtList.Clear()
+ return
+
+def DeletePlayerHurtList(curNPC):
+ ## 删除伤血列表
+ lineID = GameWorld.GetGameWorld().GetLineID()
+ objID = curNPC.GetID()
+ npcID = curNPC.GetNPCID()
+ key = (lineID, objID, npcID)
+ if key in PyGameData.g_npcHurtDict:
+ hurtList =PyGameData.g_npcHurtDict.pop(key)
+ hurtList.OnDelete()
+
+ return
+
+def GetPlayerHurtList(curNPC):
+ ## 获取伤血列表,可能为None
+ lineID = GameWorld.GetGameWorld().GetLineID()
+ objID = curNPC.GetID()
+ npcID = curNPC.GetNPCID()
+ return GetPlayerHurtListEx(lineID, objID, npcID)
+def GetPlayerHurtListEx(lineID, objID, npcID):
+ ## 获取伤血列表,可能为None
+ key = (lineID, objID, npcID)
+ defendHurtList = None
+ if key not in PyGameData.g_npcHurtDict:
+ ## 只统计最大伤血归属的boss
+ npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
+ if not npcData:
+ return defendHurtList
+ if not npcData.GetIsBoss() or NPCCommon.GetDropOwnerType(npcData) != ChConfig.DropOwnerType_MaxHurt:
+ return defendHurtList
+ defendHurtList = PlayerHurtList(lineID, objID, npcID)
+ PyGameData.g_npcHurtDict[key] = defendHurtList
+ defendHurtList = PyGameData.g_npcHurtDict[key]
+ return defendHurtList
+
+def OnNPCHurtPlayerEnterTeam(playerID, playerName, befTeamID, newTeam, tick):
+ ## 伤血玩家加入队伍
+ for hurtList in PyGameData.g_npcHurtDict.values():
+ hurtList.OnHurtPlayerEnterTeam(playerID, playerName, befTeamID, newTeam, tick)
+ return
+
+def OnNPCHurtPlayerLeaveTeam(playerID, leaveTeamID, tick):
+ ## 伤血玩家离开队伍
+ for hurtList in PyGameData.g_npcHurtDict.values():
+ hurtList.OnHurtPlayerLeaveTeam(playerID, leaveTeamID, tick)
+ return
+
+def AddHurtValue(atkPlayer, defNPC, value, isBounce):
+ '''添加伤血
+ @param isBounce: 是否反弹伤害,反弹伤害不计入非主动攻击的玩家伤血,因为规定玩家攻击另一个boss则要清除同地图上一个boss的该玩家伤害
+ 防止死亡回复活点跑图中被主动型boss攻击计入伤血导致清除同地图上一个主动攻击的boss伤血
+ '''
+
+ defendHurtList = GetPlayerHurtList(defNPC)
+ if not defendHurtList:
+ return
+ atkPlayerID = atkPlayer.GetPlayerID()
+
+ if isBounce and not defendHurtList.HaveHurtValue(atkPlayerID):
+ GameWorld.DebugLog("还没有伤害输出时反弹伤害不计入!", atkPlayerID)
+ return
+
+ objID = defNPC.GetID()
+ npcID = defNPC.GetNPCID()
+ # 删除其他boss伤血、协助
+ for hurtList in PyGameData.g_npcHurtDict.values():
+ if hurtList.npcID == npcID and hurtList.objID == objID:
+ continue
+ if not hurtList.IsNoAssistPlayer(atkPlayerID) and not hurtList.IsAssistPlayer(atkPlayerID):
+ continue
+ GameWorld.Log("玩家主动攻击了其他boss,取消原boss伤血协助等数据! befNPCID=%s,newNPCID=%s" % (hurtList.npcID, npcID))
+ hurtList.DelHurtPlayer(atkPlayerID, "AttackNewBoss")
+
+ defendHurtList.AddPlayerHurtValue(atkPlayerID, atkPlayer.GetPlayerName(), value, atkPlayer.GetTeamID())
+ return True
+
+def RefreshHurtList(curNPC, tick, refreshInterval=3000, isDead=False):
+ defendHurtList = GetPlayerHurtList(curNPC)
+ if not defendHurtList:
+ return
+ return defendHurtList.RefreshHurtList(tick, refreshInterval, isDead)
+
+def IsAssistPlayer(playerID, defNPC):
+ ## 是否协助中的玩家
+ defendHurtList = GetPlayerHurtList(defNPC)
+ if not defendHurtList:
+ return False
+ return defendHurtList.IsAssistPlayer(playerID)
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAssist.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAssist.py
new file mode 100644
index 0000000..3f0e579
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerAssist.py
@@ -0,0 +1,151 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.PlayerAssist
+#
+# @todo:协助系统
+# @author hxp
+# @date 2019-12-06
+# @version 1.0
+#
+# 详细描述: 协助系统
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-12-06 21:00"""
+#-------------------------------------------------------------------------------
+
+import GameWorld
+import IpyGameDataPY
+import PlayerControl
+import NPCHurtManager
+import IPY_GameWorld
+
+import ChConfig
+
+#// B0 10 请求协助Boss #tagCMRequestAssistBoss
+#
+#struct tagCMRequestAssistBoss
+#
+#{
+# tagHead Head;
+# DWORD ObjID;
+# DWORD NPCID;
+#};
+def OnRequestAssistBoss(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ playerID = curPlayer.GetPlayerID()
+ objID = clientData.ObjID
+ npcID = clientData.NPCID
+
+ if not curPlayer.GetFamilyID():
+ GameWorld.DebugLog("没有仙盟不能请求协助!", playerID)
+ return
+
+ curNPC = GameWorld.FindNPCByNPCID(npcID)
+ if not curNPC or curNPC.GetID() != objID:
+ GameWorld.DebugLog("协助NPC不存在无法协助!", playerID)
+ return
+
+ ipyData = IpyGameDataPY.GetIpyGameDataNotLog('BOSSInfo', npcID)
+ if not ipyData or not ipyData.GetCanAssist():
+ GameWorld.DebugLog("该NPC不能协助!npcID=%s" % npcID, playerID)
+ return
+
+ hurtList = NPCHurtManager.GetPlayerHurtList(curNPC)
+ if not hurtList.IsNoAssistPlayer(playerID):
+ GameWorld.DebugLog("不是该boss的非助战伤血玩家,无法发起协助!npcID=%s" % npcID, playerID)
+ return
+
+ if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_RequestAssist, tick):
+ GameWorld.DebugLog("请求协助CD中!npcID=%s" % npcID, playerID)
+ return
+
+ mapID = curPlayer.GetMapID()
+ lineID = 0
+ if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull: # 副本型boss,如封魔坛
+ lineID = PlayerControl.GetFBFuncLineID(curPlayer)
+ queryData = [mapID, lineID, npcID, objID]
+ QueryGameServer_PlayerAssist(playerID, "RequestAssistBoss", queryData)
+ return
+
+
+#// B0 11 请求协助组队副本 #tagCMRequestAssistTeamFB
+#
+#struct tagCMRequestAssistTeamFB
+#
+#{
+# tagHead Head;
+# WORD MapID;
+# WORD LineID;
+#};
+def OnRequestAssistTeamFB(index, clientData, tick):
+ curPlayer = GameWorld.GetPlayerManager().GetPlayerByIndex(index)
+ playerID = curPlayer.GetPlayerID()
+ mapID = clientData.MapID
+ lineID = clientData.LineID
+
+ if not curPlayer.GetFamilyID():
+ GameWorld.DebugLog("没有仙盟不能请求协助!", playerID)
+ return
+
+ if GameWorld.GetMap().GetMapFBTypeByMapID(mapID) != IPY_GameWorld.fbtTeam:
+ GameWorld.DebugLog("非组队副本不能请求协助!mapID=%s" % mapID, playerID)
+ return
+
+ if not GameWorld.SetPlayerTickTime(curPlayer, ChConfig.TYPE_Player_Tick_RequestAssist, tick):
+ GameWorld.DebugLog("请求协助CD中!mapID=%s,lineID=%s" % (mapID, lineID), playerID)
+ return
+
+ queryData = [mapID, lineID]
+ QueryGameServer_PlayerAssist(playerID, "RequestAssistTeamFB", queryData)
+ return
+
+def OnStartAssistTeamFB(playerID, mapID, lineID, tagPlayerID):
+ ## 开始协助组队副本,协助玩家进入副本调用
+ queryData = [mapID, lineID, tagPlayerID]
+ QueryGameServer_PlayerAssist(playerID, "OnStartAssistTeamFB", queryData)
+ return
+
+def QueryGameServer_PlayerAssist(playerID, queryType, queryData):
+ msgInfo = str([queryType, queryData])
+ GameWorld.GetPlayerManager().GameServer_QueryPlayerResult(playerID, 0, 0, "PlayerAssist", msgInfo, len(msgInfo))
+ GameWorld.DebugLog("协助信息发送 GameServer: playerID=%s,queryType=%s,queryData=%s" % (playerID, queryType, queryData))
+ return
+
+def QueryResult_PlayerAssist(curPlayer, resultList):
+ ## 协助信息GameServer返回处理
+ if len(resultList) != 3:
+ return
+ #queryType, queryData, result = resultList
+
+ return
+
+def GameServer_AssistBossMsg(assistData):
+ ## GameServer推送到指定boss地图的信息
+
+ GameWorld.DebugLog("GameServer同步Boss协助信息: %s" % assistData)
+
+ msgType = assistData[0]
+
+ # 开始协助
+ if msgType == "Start":
+ assistGUID, assistPlayerID, assistPlayerName, tagPlayerID, tagPlayerName, tagTeamID, lineID, objID, npcID = assistData[1:]
+ npchurtList = NPCHurtManager.GetPlayerHurtListEx(lineID, objID, npcID)
+ if not npchurtList:
+ return
+
+ npchurtList.AddAssistPlayer(assistPlayerID, assistPlayerName, tagPlayerID, tagPlayerName, tagTeamID)
+ QueryGameServer_PlayerAssist(0, "AddAssistBossPlayerOK", [assistGUID, assistPlayerID])
+
+ # 取消协助
+ elif msgType == "Cancel":
+ assistPlayerID, lineID, objID, npcID = assistData[1:]
+ npchurtList = NPCHurtManager.GetPlayerHurtListEx(lineID, objID, npcID)
+ if not npchurtList:
+ return
+ npchurtList.DelHurtPlayer(assistPlayerID, "Cancel", isMapServerDel=False)
+
+ return
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
index 4a78d00..1b8199b 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerControl.py
@@ -87,6 +87,7 @@
import FunctionNPCCommon
import CrossRealmPlayer
import CrossPlayerData
+import NPCHurtManager
import ChNetSendPack
import PlayerCoat
import PlayerState
@@ -1522,6 +1523,10 @@
NomalDictSetProperty(curPlayer, ChConfig.Def_Player_Dict_FromFBLineID, lineID)
GameWorld.DebugLog("进入副本时,最后一次离开的可返回的副本ID更新!mapID=%s,lineID=%s,Pos(%s,%s)" % (mapID, lineID, posX, posY))
+ # 离开地图,暂时只处理离开中立、组队副本
+ if curPlayer.GetMapID() in IpyGameDataPY.GetFuncEvalCfg("MapLine", 4) or GameWorld.GetMap().GetMapFBType() == IPY_GameWorld.fbtTeam:
+ NPCHurtManager.OnPlayerLeaveMap(curPlayer)
+
# 从副本中切图
if GameWorld.GetMap().GetMapFBType() != IPY_GameWorld.fbtNull:
#默认回满血
@@ -2347,8 +2352,9 @@
def __GetBossShuntLineID(curPlayer, curMapID, curLineID, tagMapID, npcID, lineIDList):
'''获取目标地图boss分流线路
根据人数分流玩家,优先分配到活着的线路
- 队伍无视任何规则,默认分配到队伍队员多的那条线
-
+ 队伍默认分配到队伍队员多的那条线
+ 协助默认分配到目标玩家线路,优先级最高
+
前端:
1.在中立地图的时候,显示当前线路BOSS的状态
2.在常规地图的时候,显示玩家击杀BOSS的CD时间
@@ -2384,10 +2390,14 @@
lineIDList.remove(activityLineID)
GameWorld.DebugLog(" 非1线的活动线路不参与分流: activityLineID=%s,lineIDList=%s" % (activityLineID, lineIDList), playerID)
+ assistTagPlayerID = GetAssistTagPlayerID(curPlayer)
for lineID in lineIDList:
key = (tagMapID, lineID)
# boss分流玩家信息{(mapID, lineID):{playerID:[bossID, teamID, relatedTick], ...}, ...}
shuntPlayerDict = PyGameData.g_bossShuntPlayerInfo.get(key, {})
+ if assistTagPlayerID and assistTagPlayerID in shuntPlayerDict:
+ GameWorld.DebugLog(" 分流到协助目标玩家线路 assistTagPlayerID=%s,lineID=%s" % (assistTagPlayerID, lineID), playerID)
+ return lineID
playerCount = 0
teamPlayerCount = 0
for shuntPlayerID, shuntInfo in shuntPlayerDict.items():
@@ -5893,13 +5903,20 @@
curPlayer.SendPropertyRefresh(ShareDefine.CDBPlayerRefresh_ForbidenTalk, value, False)
return
+## 协助目标玩家ID
+def SetAssistTagPlayerID(curPlayer, value):
+ curPlayer.SetExAttr1(value, True, False) # 不通知GameServer
+ NPCHurtManager.OnSetAssistTagPlayerID(curPlayer, value)
+ return
+def GetAssistTagPlayerID(curPlayer): return curPlayer.GetExAttr1()
+
## 队伍相关审核开关状态, joinReqCheck-入队申请是否需要审核; inviteCheck-组队邀请是否需要审核;
def SetTeamCheckStateEx(curPlayer, joinReqCheck, inviteCheck): return SetTeamCheckState(curPlayer, joinReqCheck * 10 + inviteCheck)
def SetTeamCheckState(curPlayer, checkState): return curPlayer.SetExAttr2(checkState, False, True)
def GetTeamCheckState(curPlayer): return curPlayer.GetExAttr2()
## 副本功能线路ID, 这里做db存储,防止在合并地图副本中掉线重上时前端无法加载正确的场景资源,登录加载场景时机为0102包
-def SetFBFuncLineID(curPlayer, funcLineID): return curPlayer.SetExAttr3(funcLineID, False, False)
+def SetFBFuncLineID(curPlayer, funcLineID): return curPlayer.SetExAttr3(funcLineID, False, True)
def GetFBFuncLineID(curPlayer): return curPlayer.GetExAttr3()
## 跨服状态所在地图ID: 0-非跨服状态,非0-跨服状态对应的地图ID
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
index 370b4f4..a68cb25 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerEventCounter.py
@@ -97,6 +97,7 @@
import FamilyRobBoss
import FBHelpBattle
import QuestManager
+import PlayerAssist
import PyGameData
import PlayerTJG
@@ -1291,6 +1292,12 @@
GameLogic_FamilyParty.DoAddFamilyMemberFamilyActivity(familyID, addFamilyActivity)
return
+ if key == ShareDefine.Def_Notify_WorldKey_AssistBoss:
+ assistData = eval(msgValue)
+ if GameWorld.GetMap().GetMapID() == assistData[0]:
+ PlayerAssist.GameServer_AssistBossMsg(assistData[1:])
+ return
+
if key == ShareDefine.Def_Notify_WorldKey_AddFamilyAuctionItem:
mapID, familyAuctionItemDict = eval(msgValue)
if GameWorld.GetMap().GetMapID() == mapID:
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTeam.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTeam.py
index ccd03a4..0c59fe1 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTeam.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/PlayerTeam.py
@@ -26,6 +26,7 @@
import SkillCommon
import IPY_GameWorld
import DataRecordPack
+import NPCHurtManager
#import PlayerTruck
import ShareDefine
import SkillShell
@@ -249,10 +250,10 @@
#curMapTeam.SetTeamType(recvPack.GetTeamType())
DR_Team("RefreshPlayerTeamID_Create", teamID, dataDict)
- if playerTeamID != teamID or not curTeam:
- isNewTeam = playerTeamID != teamID # 切地图/上线时teamID可能不变,但是team为None
+ if (playerTeamID != teamID or not curTeam) and curMapTeam:
+ #isNewTeam = playerTeamID != teamID # 切地图/上线时teamID可能不变,但是team为None
#GameWorld.DebugLog(" 玩家当前无队伍,处理玩家进队!isNewTeam=%s" % isNewTeam, playerID)
- __OnEnterTeam(curPlayer, curMapTeam, isNewTeam, tick, dataDict)
+ __OnEnterTeam(curPlayer, curMapTeam, playerTeamID, tick, dataDict)
else:
dataDict["MemberCount"] = 0 if not curMapTeam else curMapTeam.GetMemberCount()
DR_Team("RefreshPlayerTeamID_Update", teamID, dataDict)
@@ -264,7 +265,7 @@
# @param tick 当前时间
# @return None
# @remarks 函数详细说明.
-def __OnEnterTeam(curPlayer, curMapTeam, isNewTeam, tick, dataDict):
+def __OnEnterTeam(curPlayer, curMapTeam, playerTeamID, tick, dataDict):
teamID = curMapTeam.GetTeamID()
memCount = curMapTeam.GetMemberCount()
if memCount >= ShareDefine.Def_Team_MaxPlayerCount:
@@ -292,8 +293,8 @@
#PlayerTruck.ChangeTruckNoteInfo(curPlayer)
#以下为进入一个新的队伍额外处理
- if not isNewTeam:
- return
+ if playerTeamID != teamID:
+ NPCHurtManager.OnNPCHurtPlayerEnterTeam(playerID, curPlayer.GetPlayerName(), playerTeamID, curMapTeam, tick)
return
def __OnPlayerLeaveTeam(copyMapID, playerID, leaveTeamID, tick):
@@ -311,6 +312,8 @@
__DelPlayerIDFromTeamPlayer(playerID, False)
+ NPCHurtManager.OnNPCHurtPlayerLeaveTeam(playerID, leaveTeamID, tick)
+
dataDict = {"playerID":playerID, "copyMapID":copyMapID}
### =========================== 以下逻辑是玩家存在时才需要处理的 =================================
curPlayer = GameWorld.GetPlayerManager().FindPlayerByID(playerID)
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_PlayerAssist.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_PlayerAssist.py
new file mode 100644
index 0000000..689e48f
--- /dev/null
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/Player/RemoteQuery/GY_Query_PlayerAssist.py
@@ -0,0 +1,51 @@
+#!/usr/bin/python
+# -*- coding: GBK -*-
+#-------------------------------------------------------------------------------
+#
+##@package Player.RemoteQuery.GY_Query_PlayerAssist
+#
+# @todo:协助系统
+# @author hxp
+# @date 2019-12-06
+# @version 1.0
+#
+# 详细描述: 协助系统
+#
+#-------------------------------------------------------------------------------
+#"""Version = 2019-12-06 21:00"""
+#-------------------------------------------------------------------------------
+
+import PlayerAssist
+import GameWorld
+
+
+## 请求逻辑
+# @param query_Type 请求类型
+# @param query_ID 请求的玩家ID
+# @param packCMDList 发包命令 [ ]
+# @param tick 当前时间
+# @return resultDisc
+def DoLogic(query_Type, query_ID, packCMDList, tick):
+ return
+
+#---------------------------------------------------------------------
+## 执行结果
+# @param curPlayer 发出请求的玩家
+# @param callFunName 功能名称
+# @param funResult 查询的结果
+# @param tick 当前时间
+# @return None
+# @remarks 函数详细说明.
+def DoResult(curPlayer, callFunName, funResult, tick):
+ try:
+ funResultList = eval(funResult)
+ except:
+ GameWorld.ErrLog("GY_Query_PlayerAssist %s eval Error" % funResult, curPlayer.GetPlayerID())
+ return
+
+ GameWorld.DebugLog("GY_Query_PlayerAssist ResultList=%s" % str(funResultList), curPlayer.GetPlayerID())
+ PlayerAssist.QueryResult_PlayerAssist(curPlayer, funResultList)
+ return
+
+
+
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
index 5e5ad3d..3edcfd4 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/PyGameData.py
@@ -28,6 +28,8 @@
g_filterEquipDict = {} # 按装备条件过滤的装备ID,不分职业 {"classLV_color_star":{(itemJob,itemPlace):itemID, ...}, ...}
+g_npcHurtDict = {} # npc伤血列表信息字典 {(lineID,objID,npcID):PlayerHurtList, ...}
+
g_teamPlayerHurtValue = {} # 队伍玩家对NPC伤害输出量 {(lineID, objID, npcID):{(teamID, playerID):hurtValue, ...}, }
g_teamPlayerDict = {} # 地图队伍对应玩家ID列表,含离线玩家 {teamID:[playerID, ...], ...}
diff --git a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
index 1c964a5..a520f4d 100644
--- a/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
+++ b/ServerPython/ZoneServerGroup/map1_8G/MapServer/MapServerData/Script/ShareDefine.py
@@ -195,6 +195,9 @@
Def_Notify_WorldKey_RedPacketOutput = 'RedPacketOutput' # 红包产出信息
Def_Notify_WorldKey_HurtLog = 'HurtLog' # 战斗伤害日志
Def_Notify_WorldKey_FairyDomainLimit = "FairyDomainLimit" # 缥缈仙域限制事件
+
+Def_Notify_WorldKey_AssistBoss = "AssistBoss" # 协助boss
+
#运营活动表名定义
OperationActionName_ExpRate = "ActExpRate" # 多倍经验活动
OperationActionName_CostRebate = "ActCostRebate" # 消费返利活动
--
Gitblit v1.8.0