| | |
| | | import ShareDefine
|
| | | import PlayerTeam
|
| | | import NPCCommon
|
| | | import FBCommon
|
| | | import ChConfig
|
| | |
|
| | | import time
|
| | |
| | | self.__hurtType = ChConfig.Def_NPCHurtTypePlayer # 均默认是玩家
|
| | | self.__hurtName = ""
|
| | | self.__hurtValue = 0
|
| | | self.__isFriend = 0
|
| | | return
|
| | |
|
| | | def GetValueID(self): return self.__hurtID
|
| | |
| | | def SetHurtName(self, hurtName): self.__hurtName = hurtName
|
| | | def GetHurtValue(self): return self.__hurtValue
|
| | | def SetHurtValue(self, hurtValue): self.__hurtValue = hurtValue
|
| | | def GetIsFriend(self): return self.__isFriend
|
| | | def SetIsFriend(self, isFriend): self.__isFriend = isFriend
|
| | |
|
| | | class PlayerHurtList():
|
| | | ''' 伤血列表, 类似 IPY_GameObj.IPY_PlayerHurtList
|
| | |
| | |
|
| | | self.__hurtSortList = []
|
| | | self.__hurtDict = {} # 伤血列表实例字典,实际的NPC伤血列表实例,可能不是玩家{(hurtID, hurtType):HurtValueObj, ...}
|
| | | |
| | | self.__assistAwardItemID = 0 # 协助奖励礼盒ID
|
| | | self.__assistAwardResult = {} # {playerID:{assistPlayerID:{协助玩家信息数据字典}, ...}}
|
| | | return
|
| | |
|
| | | def Clear(self):
|
| | |
| | | def OnDelete(self):
|
| | | # 删除伤血列表,NPC死亡调用
|
| | |
|
| | | cancelPlayerIDList = self.__noAssitPlayerIDDict.keys()
|
| | | if cancelPlayerIDList:
|
| | | noAssistPlayerIDList = self.__noAssitPlayerIDDict.keys()
|
| | | if noAssistPlayerIDList:
|
| | | mapID = GameWorld.GetMap().GetMapID()
|
| | | queryData = [mapID, self.lineID, self.npcID, self.objID, "OnBossDead", cancelPlayerIDList]
|
| | | PlayerAssist.QueryGameServer_PlayerAssist(0, "OnCancelBossRequestAssist", queryData)
|
| | | queryData = [mapID, self.lineID, self.npcID, self.objID, noAssistPlayerIDList, self.__assistAwardItemID, self.__assistAwardResult]
|
| | | PlayerAssist.QueryGameServer_PlayerAssist(0, "OnBossAssistOver", queryData)
|
| | |
|
| | | return
|
| | |
|
| | |
| | | hurtPlayer.SetHurtName(playerName)
|
| | | return hurtPlayer
|
| | |
|
| | | def AddAssistPlayer(self, assistPlayerID, assistPlayerName, tagPlayerID, tagPlayerName, tagTeamID):
|
| | | def AddAssistPlayer(self, assistPlayerID, assistPlayerName, isFriend, tagPlayerID, tagPlayerName, tagTeamID):
|
| | | ## 添加助战玩家
|
| | | # @param assistPlayerID: 协助玩家ID
|
| | | # @param tagPlayerID: 目标玩家ID,即发布协助的玩家ID
|
| | |
| | | % (assistPlayerID, tagPlayerID), self.npcID, self.lineID)
|
| | | return
|
| | |
|
| | | GameWorld.DebugLog("新增协助玩家: assistPlayerID=%s,tagPlayerID=%s,tagTeamID=%s" |
| | | % (assistPlayerID, tagPlayerID, tagTeamID), self.npcID, self.lineID)
|
| | | GameWorld.DebugLog("新增协助玩家: assistPlayerID=%s,tagPlayerID=%s,tagTeamID=%s,isFriend=%s" |
| | | % (assistPlayerID, tagPlayerID, tagTeamID, isFriend), self.npcID, self.lineID)
|
| | |
|
| | | if assistPlayerID in self.__noAssitPlayerIDDict:
|
| | | GameWorld.DebugLog("原来为常规玩家,需要先删除!", self.npcID, self.lineID)
|
| | |
| | | assistPlayerIDList.append(assistPlayerID)
|
| | | self.__assistPlayerIDDict[assistPlayerID] = tagPlayerID
|
| | |
|
| | | assistHurtPlayer = self.__GetHurtPlayer(assistPlayerID, assistPlayerName)
|
| | | assistHurtPlayer.SetIsFriend(isFriend)
|
| | | GameWorld.DebugLog(" self.__noAssitPlayerIDDict=%s" % (self.__noAssitPlayerIDDict), self.npcID, self.lineID)
|
| | | GameWorld.DebugLog(" self.__assistPlayerIDDict=%s" % (self.__assistPlayerIDDict), self.npcID, self.lineID)
|
| | | return
|
| | |
| | | # 地图删除的同步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)
|
| | | queryData = [mapID, self.lineID, self.npcID, self.objID, reason]
|
| | | PlayerAssist.QueryGameServer_PlayerAssist(playerID, "OnCancelBossRequestAssist", queryData)
|
| | |
|
| | | # 协助玩家
|
| | | elif playerID in self.__assistPlayerIDDict:
|
| | |
| | | def IsAssistPlayer(self, playerID):
|
| | | ## 是否助战伤血玩家
|
| | | return playerID in self.__assistPlayerIDDict
|
| | | |
| | | def IsAssistRelation(self, playerID, tagPlayerID):
|
| | | ## 玩家双方是否存在协助关系
|
| | | |
| | | # A协助B
|
| | | if playerID in self.__assistPlayerIDDict:
|
| | | if self.__assistPlayerIDDict[playerID] == tagPlayerID:
|
| | | #GameWorld.DebugLog("%s 协助 %s" % (playerID, tagPlayerID))
|
| | | return True
|
| | | |
| | | # B协助A
|
| | | elif tagPlayerID in self.__assistPlayerIDDict:
|
| | | if self.__assistPlayerIDDict[tagPlayerID] == playerID:
|
| | | #GameWorld.DebugLog("%s 协助 %s" % (tagPlayerID, playerID))
|
| | | return True
|
| | | |
| | | # 协助同一个玩家
|
| | | for assPlayerIDList in self.__noAssitPlayerIDDict.values():
|
| | | if playerID in assPlayerIDList and tagPlayerID in assPlayerIDList:
|
| | | #GameWorld.DebugLog("协助同一玩家! %s %s" % (playerID, tagPlayerID))
|
| | | return True
|
| | | |
| | | return False
|
| | |
|
| | | def OnHurtPlayerEnterTeam(self, playerID, playerName, befTeamID, newTeam, tick):
|
| | | ''' 伤血玩家加入队伍
|
| | |
| | | # @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()
|
| | | return self.__GetAtkObjByHurtList(isDead)
|
| | |
|
| | | curNPC.SetDict(ChConfig.Def_NPC_Dict_LastRefreshHurtTick, tick)
|
| | |
|
| | |
| | |
|
| | | isInHurt = self.__hurtSortList != []
|
| | | curNPC.SetDict(ChConfig.Def_NPC_Dict_InHurtProtect, isInHurt)
|
| | | return self.__GetAtkObjByHurtList()
|
| | | return self.__GetAtkObjByHurtList(isDead)
|
| | |
|
| | | def __UnAssistPlayerHurtValidLogic(self, playerID, refreshPoint, tick):
|
| | | ## 非协助玩家伤血有效性检查逻辑
|
| | |
| | |
|
| | | return
|
| | |
|
| | | def __GetAtkObjByHurtList(self):
|
| | | def __GetAtkObjByHurtList(self, isDead):
|
| | | '''第一个可攻击的最大伤血对象,也是实际的归属者或队伍
|
| | | 因为玩家伤血掉线、死亡有一定时间的保留机制,故最大伤血不一定是可攻击目标(归属者)
|
| | | 注意: 该规则必须与最终算归属的规则一致,不然可能导致归属错乱
|
| | |
| | | atkPlayer, atkHurtType, atkHurtID = None, 0, 0
|
| | | curNPC = self.curNPC
|
| | | refreshPoint = curNPC.GetRefreshPosAt(curNPC.GetCurRefreshPointIndex())
|
| | | for hurtObj in self.__hurtSortList:
|
| | | for rank, hurtObj in enumerate(self.__hurtSortList, 1):
|
| | |
|
| | | hurtID = hurtObj.GetValueID()
|
| | | hurtType = hurtObj.GetValueType()
|
| | |
| | | else:
|
| | | continue
|
| | |
|
| | | playerDisableReason = {}
|
| | | maxHurtValue = 0
|
| | | for playerID in playerIDList:
|
| | |
|
| | |
| | | continue
|
| | |
|
| | | if player.GetHP() <= 0 or player.GetPlayerAction() == IPY_GameWorld.paDie:
|
| | | playerDisableReason[playerID] = "dead"
|
| | | continue
|
| | |
|
| | | if not player.GetVisible() or player.GetSightLevel() != curNPC.GetSightLevel():
|
| | | playerDisableReason[playerID] = "no visible or sightLevel different"
|
| | | continue
|
| | |
|
| | | if not self.__GetIsInRefreshPoint(player.GetPosX(), player.GetPosY(), refreshPoint):
|
| | | playerDisableReason[playerID] = "not in boss area"
|
| | | continue
|
| | |
|
| | | if playerID not in self.__hurtPlayerDict:
|
| | | playerDisableReason[playerID] = "no hurt"
|
| | | continue
|
| | | hurtPlayer = self.__hurtPlayerDict[playerID]
|
| | | hurtValue = hurtPlayer.GetHurtValue()
|
| | |
| | | if maxHurtValue:
|
| | | return atkPlayer, atkHurtType, atkHurtID
|
| | |
|
| | | if rank == 1 and isDead:
|
| | | GameWorld.Log("boss死亡时,第一名团队没有归属权! playerDisableReason=%s" % playerDisableReason)
|
| | | |
| | | return atkPlayer, atkHurtType, atkHurtID
|
| | |
|
| | | def __GetIsInRefreshPoint(self, curPosX, curPosY, refreshPoint):
|
| | |
| | | ''' 执行协助奖励逻辑
|
| | | '''
|
| | |
|
| | | liheItemID = 2244 # 感谢礼盒物品ID,暂山寨,感谢系统再修改
|
| | | self.__assistAwardResult = {}
|
| | |
|
| | | liheItemID, assistMoney = 0, 0
|
| | | mapAssistGiftDict = IpyGameDataPY.GetFuncEvalCfg("AssistAward", 2, {})
|
| | | mapID = FBCommon.GetRecordMapID(GameWorld.GetMap().GetMapID())
|
| | | if str(mapID) in mapAssistGiftDict:
|
| | | liheItemID, assistMoney = mapAssistGiftDict[str(mapID)]
|
| | | else:
|
| | | killBossCntLimitDict = IpyGameDataPY.GetFuncEvalCfg('KillBossCntLimit') |
| | | index = GameWorld.GetDictValueByKey(killBossCntLimitDict, self.npcID)
|
| | | if index == None:
|
| | | return
|
| | | bossAssistGiftDict = IpyGameDataPY.GetFuncEvalCfg("AssistAward", 1, {})
|
| | | if str(index) not in bossAssistGiftDict:
|
| | | GameWorld.DebugLog("该boss没有协助额外奖励!index=%s" % index, self.npcID)
|
| | | return
|
| | | liheItemID, assistMoney = bossAssistGiftDict[str(index)]
|
| | | |
| | | if not liheItemID or not assistMoney:
|
| | | GameWorld.DebugLog("该副本或boss没有协助额外奖励!mapID=%s" % (mapID), self.npcID)
|
| | | return
|
| | | self.__assistAwardItemID = liheItemID
|
| | | |
| | | fbType = GameWorld.GetMap().GetMapFBTypeByMapID(mapID)
|
| | | 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)
|
| | | 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)
|
| | | |
| | | noAssistPlayer = copyPlayerManager.FindPlayerByID(playerID)
|
| | | |
| | | assistAwardPlayerDict = {}
|
| | | # 即使发布方不在线,协助方完成后也可获得活跃令奖励,只是不一定获得礼盒感谢奖励(礼盒感谢奖励需双方都在线)
|
| | | 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:
|
| | | assistPlayer = copyPlayerManager.FindPlayerByID(assistPlayerID)
|
| | | if not assistPlayer:
|
| | | 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)
|
| | | |
| | | isFriend = assistHurtPlayer.GetIsFriend()
|
| | | assistMoneyType = ShareDefine.TYPE_Price_FamilyActivity
|
| | | addAssistMoney = PlayerAssist.AddTodayAssistMoney(assistPlayer, assistMoneyType, assistMoney, isFriend)
|
| | | GameWorld.DebugLog("协助方给活跃令奖励: assistPlayerID=%s,assistMoney=%s,isFriend=%s,addAssistMoney=%s" |
| | | % (assistPlayerID, assistMoney, isFriend, addAssistMoney), self.npcID, self.lineID)
|
| | | if fbType == IPY_GameWorld.fbtNull:
|
| | | PlayerControl.NotifyCode(assistPlayer, "AssistSuccess")
|
| | | else:
|
| | | overDict = {FBCommon.Over_isAssist:1, FBCommon.Over_money:FBCommon.GetJsonMoneyList({assistMoneyType:addAssistMoney}),
|
| | | FBCommon.Over_itemInfo:[]}
|
| | | FBCommon.NotifyFBOver(assistPlayer, mapID, PlayerControl.GetFBFuncLineID(assistPlayer), 1, overDict)
|
| | | assistPlayer.Sync_TimeTick(IPY_GameWorld.tttLeaveMap, 0, 10000, True)
|
| | | |
| | | if noAssistPlayer:
|
| | | todayGiftCount = assistPlayer.NomalDictGetProperty(ChConfig.Def_PDict_GetThanksGiftCount % liheItemID)
|
| | | assistAwardPlayerDict[assistPlayerID] = {"PlayerName":assistPlayer.GetPlayerName(), "Job":assistPlayer.GetJob(), |
| | | "LV":assistPlayer.GetLV(), "RealmLV":assistPlayer.GetOfficialRank(),
|
| | | "TodayGiftCount":todayGiftCount}
|
| | | |
| | | notifyParam = [assistPlayer.GetPlayerName(), noAssistPlayer.GetPlayerName(), mapID, self.curNPC.GetLV(), self.npcID]
|
| | | PlayerControl.FamilyNotify(assistPlayer.GetFamilyID(), "AssistBossFinish", notifyParam)
|
| | | |
| | | if not noAssistPlayer or not assistAwardPlayerDict:
|
| | | GameWorld.DebugLog("发布方离线或无有效协助玩家在线,不给感谢礼盒奖励: playerID=%s" % playerID, self.npcID, self.lineID)
|
| | | continue
|
| | | |
| | | GameWorld.DebugLog("发布方给感谢礼盒奖励: playerID=%s" % playerID, self.npcID, self.lineID)
|
| | | ItemControler.GivePlayerItemOrMail(noAssistPlayer, [[liheItemID, 1, 0]])
|
| | | self.__assistAwardResult[playerID] = assistAwardPlayerDict
|
| | | |
| | | return
|
| | |
|
| | | def __CmpHurtValue(self, hurtObjA, hurtObjB):
|
| | |
| | | bossHurtInfoPack.HurtValueList = hurtValueList
|
| | | bossHurtInfoPack.HurtCount = len(hurtValueList)
|
| | |
|
| | | curNPC = self.curNPC
|
| | | assistHurtValueListDict = {}
|
| | | copyPlayerManager = GameWorld.GetMapCopyPlayerManager()
|
| | | for playerID in syncPlayerIDList:
|
| | | player = copyPlayerManager.FindPlayerByID(playerID)
|
| | | if not player:
|
| | | continue
|
| | | |
| | | if not player.CanSeeOther(curNPC):
|
| | | continue
|
| | | if playerID in self.__noAssitPlayerIDDict:
|
| | | assTagPlayerID = playerID
|
| | | elif playerID in self.__assistPlayerIDDict:
|
| | |
| | | def OnPlayerLeaveMap(curPlayer):
|
| | | ## 玩家离开地图处理
|
| | |
|
| | | mapID = curPlayer.GetMapID()
|
| | | mapType = GameWorld.GetMap().GetMapFBType()
|
| | | changeMapID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeMapID)
|
| | | changeLineID = curPlayer.GetDictByKey(ChConfig.Def_PlayerKey_ChangeLineID)
|
| | | |
| | | playerID = curPlayer.GetPlayerID()
|
| | | for hurtList in PyGameData.g_npcHurtDict.values():
|
| | | if hurtList.IsNoAssistPlayer(playerID) or hurtList.IsAssistPlayer(playerID):
|
| | | if mapType == IPY_GameWorld.fbtNull and mapID == changeMapID and changeLineID == hurtList.lineID:
|
| | | #GameWorld.DebugLog("玩家同地图切线,当前伤血lineID为目标线路,不清伤血!changeLineID=%s" % changeLineID, playerID)
|
| | | continue
|
| | | GameWorld.DebugLog("玩家离开地图, 删除boss伤血玩家!npcID=%s" % (hurtList.npcID), playerID)
|
| | | hurtList.DelHurtPlayer(playerID, "LeaveMap")
|
| | | break
|
| | |
| | | defendHurtList.Clear()
|
| | | return
|
| | |
|
| | | def GetBossLineID(npcID):
|
| | | sealDemonIpyData = IpyGameDataPY.GetIpyGameDataNotLog("SealDemon", npcID)
|
| | | if sealDemonIpyData:
|
| | | lineID = sealDemonIpyData.GetLineID()
|
| | | else:
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | return lineID
|
| | |
|
| | | def DeletePlayerHurtList(curNPC):
|
| | | ## 删除伤血列表
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | objID = curNPC.GetID()
|
| | | npcID = curNPC.GetNPCID()
|
| | | lineID = GetBossLineID(npcID)
|
| | | key = (lineID, objID, npcID)
|
| | | if key in PyGameData.g_npcHurtDict:
|
| | | hurtList =PyGameData.g_npcHurtDict.pop(key)
|
| | |
| | |
|
| | | def GetPlayerHurtList(curNPC):
|
| | | ## 获取伤血列表,可能为None
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | objID = curNPC.GetID()
|
| | | npcID = curNPC.GetNPCID()
|
| | | lineID = GetBossLineID(npcID)
|
| | | return GetPlayerHurtListEx(lineID, objID, npcID)
|
| | | def GetPlayerHurtListEx(lineID, objID, npcID):
|
| | | ## 获取伤血列表,可能为None
|
| | |
| | | if key not in PyGameData.g_npcHurtDict:
|
| | | ## 只统计最大伤血归属的boss
|
| | | npcData = GameWorld.GetGameData().FindNPCDataByID(npcID)
|
| | | if not npcData:
|
| | | if not npcData or not ChConfig.IsGameBoss(npcData):
|
| | | return defendHurtList
|
| | | if not npcData.GetIsBoss() or NPCCommon.GetDropOwnerType(npcData) != ChConfig.DropOwnerType_MaxHurt:
|
| | | return defendHurtList
|
| | | if NPCCommon.GetDropOwnerType(npcData) != ChConfig.DropOwnerType_MaxHurt:
|
| | | mapID = GameWorld.GetMap().GetMapID()
|
| | | if mapID not in [ChConfig.Def_FBMapID_SealDemon]:
|
| | | return defendHurtList
|
| | | defendHurtList = PlayerHurtList(lineID, objID, npcID)
|
| | | PyGameData.g_npcHurtDict[key] = defendHurtList
|
| | | defendHurtList = PyGameData.g_npcHurtDict[key]
|
| | | if not defendHurtList.curNPC:
|
| | | hurtList = PyGameData.g_npcHurtDict.pop(key)
|
| | | hurtList.OnDelete()
|
| | | return
|
| | | return defendHurtList
|
| | |
|
| | | def OnNPCHurtPlayerEnterTeam(playerID, playerName, befTeamID, newTeam, tick):
|
| | |
| | | return True
|
| | |
|
| | | def RefreshHurtList(curNPC, tick, refreshInterval=3000, isDead=False):
|
| | | ## 刷新伤血列表
|
| | | # @return: atkPlayer, ownerType, ownerID
|
| | | defendHurtList = GetPlayerHurtList(curNPC)
|
| | | if not defendHurtList:
|
| | | return
|
| | |
| | | return False
|
| | | return defendHurtList.IsAssistPlayer(playerID)
|
| | |
|
| | | def IsAssistRelation(curPlayer, tagPlayer):
|
| | | ## 双方是否协助关系
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | tagPlayerID = tagPlayer.GetPlayerID()
|
| | | for hurtList in PyGameData.g_npcHurtDict.values():
|
| | | if hurtList.IsAssistRelation(playerID, tagPlayerID):
|
| | | return True
|
| | | return False
|
| | |
|
| | | def CheckPlayerCanAttackFBNPC(curPlayer, curNPC, mapID, isNotify=False):
|
| | | ## 检查玩家可否攻击有副本次数的NPC
|
| | | enterCnt = curPlayer.NomalDictGetProperty(ChConfig.Def_Player_Dict_EnterFbCntDay % mapID)
|
| | | if enterCnt < FBCommon.GetEnterFBMaxCnt(curPlayer, mapID):
|
| | | return True
|
| | | |
| | | # 没有次数的,如果是助战玩家也可攻击
|
| | | if IsAssistPlayer(curPlayer.GetPlayerID(), curNPC):
|
| | | return True
|
| | | |
| | | if isNotify:
|
| | | PlayerControl.NotifyCode(curPlayer, "AttackFBBossLimit")
|
| | | |
| | | return False
|
| | |
|