4581 【后端】【1.3.100】上古战场优化和分线调整——机器人AI、属性、伤害
| | |
| | | if objType == IPY_GameWorld.gotPlayer:
|
| | | return "P"
|
| | |
|
| | | if objType == IPY_GameWorld.gotNPC:
|
| | | if obj.GetType() == ChConfig.ntRobot:
|
| | | return "Robot"
|
| | | if obj.GetType() == ChConfig.ntHelpBattleRobot:
|
| | | return "HelpRobot"
|
| | | |
| | | objType = obj.GetGameNPCObjType()
|
| | | if objType == IPY_GameWorld.gnotPet:
|
| | | return "Pet"
|
| | |
| | | if attackerCampType != defenderCampType:
|
| | | return ChConfig.Type_Relation_Enemy, ChConfig.Def_PASysMessage_None
|
| | |
|
| | | #机器人可以打机器人
|
| | | if attacker.GetType() == ChConfig.ntRobot and defender.GetType() == ChConfig.ntRobot:
|
| | | return ChConfig.Type_Relation_Enemy, ChConfig.Def_PASysMessage_None
|
| | | |
| | | return ChConfig.Type_Relation_Friend , ChConfig.Def_PASysMessage_None
|
| | |
|
| | |
|
| | |
| | | #通知玩家
|
| | | if curTagPlayer.GetMapID() != ChConfig.Def_FBMapID_XMZZ:
|
| | | if curNormalNPC.GetType() == ChConfig.ntRobot:
|
| | | PlayerControl.NotifyCode(curTagPlayer, 'RobotKill_1', [curNormalNPC.GetObjID(), curNormalNPC.GetNPCID()])
|
| | | PlayerControl.NotifyCode(curTagPlayer, 'RobotKill_1', [curNormalNPC.GetID(), curNormalNPC.GetNPCID()])
|
| | | else:
|
| | | PlayerControl.NotifyCode(curTagPlayer, 'GeRen_chenxin_279029', [curNormalNPC.GetNPCID()])
|
| | | #玩家已经死亡
|
| | |
| | | Def_FB_NotifyFBHelpTick = 'NotifyFBHelpTick' # 广播副本帮助信息tick
|
| | | Def_FB_NPCStrengthenAverageLV = 'NPCStrengthenAverageLV' # 当前线路成长NPC平均等级
|
| | | Def_FB_NPCStrengthenMaxLV = 'NPCStrengthenMaxLV' # 当前线路成长NPC最大等级
|
| | | Def_FB_NPCStrengthenMinLV = 'NPCStrengthenMinLV' # 当前线路成长NPC最小等级
|
| | | Def_FB_NPCStrengthenPlayerCnt = 'NPCStrengthenPlayerCnt' # 当前线路成长NPC对应玩家数
|
| | | Def_FB_TeamPlayerCount = 'TeamPlayerCount' # 组队副本参与玩家数 - 非实时人数,只是进入时的那个人数
|
| | | Def_FB_DropDoCountRate = 'DropDoCountRate' # 怪物掉落执行次数万分率
|
| | |
| | | Help_isHelp = 'isHelp' #本次是否是助战
|
| | | Help_helpCount = 'helpCount' #该副本今日已助战次数
|
| | | Help_relation = 'relation' #该副本关系加成信息 [优先关系, 总加成]
|
| | | Help_robotJob = 'robotJob' #机器人职业 {"ObjID":job, ...}
|
| | |
|
| | | #副本结算信息通用key
|
| | | Over_dataMapID = 'dataMapID' #数据地图ID
|
| | |
| | | gameFB.SetGameFBDict(ChConfig.Def_FB_NPCStrengthenMaxLV, maxLV)
|
| | | GameWorld.Log("NPC成长动态等级变更: isLeave=%s,totalLV=%s,playerCnt=%s,averageLV=%s,maxLV=%s"
|
| | | % (isLeave, totalLV, playerCnt, averageLV, maxLV), playerID)
|
| | | # 上古战场特殊处理
|
| | | if mapID == ChConfig.Def_FBMapID_ElderBattlefield:
|
| | | lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
|
| | | fbLineIpyData = GetFBLineIpyData(mapID, lineID)
|
| | | lvLimitMin = 0 if not fbLineIpyData else fbLineIpyData.GetLVLimitMin()
|
| | | robotLVDiff = IpyGameDataPY.GetFuncCfg("ElderBattlefieldCfg", 5)
|
| | | robotLVMin, robotLVMax = averageLV - robotLVDiff, averageLV
|
| | | robotLVMin = max(lvLimitMin, robotLVMin)
|
| | | gameFB.SetGameFBDict(ChConfig.Def_FB_NPCStrengthenMaxLV, robotLVMax)
|
| | | gameFB.SetGameFBDict(ChConfig.Def_FB_NPCStrengthenMinLV, robotLVMin)
|
| | | GameWorld.Log(" 更新上古机器人等级范围: lineID=%s,robotLVDiff=%s,robotLV=(%s~%s)" % (lineID, robotLVDiff, robotLVMin, robotLVMax))
|
| | | return True
|
| | |
|
| | | def UpdFBLineNPCStrengthenPlayerCnt(playerID, isLeave):
|
| | |
| | | return
|
| | | curPlayer.Sync_TimeTick(IPY_GameWorld.tttTowerTake, 0, closeFB_RemainTick, True)
|
| | |
|
| | | if not FBCommon.GetHadSetFBPropertyMark():
|
| | | lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
|
| | | FBCommon.SetFBPropertyMark(lineID)
|
| | | |
| | | if not FBCommon.GetHadDelTicket(curPlayer):
|
| | | FBCommon.SetHadDelTicket(curPlayer)
|
| | | if FBCommon.AddEnterFBCount(curPlayer, ChConfig.Def_FBMapID_ElderBattlefield):
|
| | |
| | |
|
| | | skillBuffID = IpyGameDataPY.GetFuncCfg('ElderBattlefieldRobot', 3)
|
| | | BuffSkill.DelBuffBySkillID(curPlayer, skillBuffID, tick)
|
| | | FBCommon.UpdFBLineNPCStrengthenLV(curPlayer.GetPlayerID(), True)
|
| | | return
|
| | |
|
| | |
|
| | |
| | | robotCfgDict = IpyGameDataPY.GetFuncEvalCfg('ElderBattlefieldCfg', 3, {})
|
| | | lineID = GameWorld.GetGameWorld().GetPropertyID() - 1
|
| | | if lineID not in robotCfgDict:
|
| | | return
|
| | | robotMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)
|
| | | if GameWorld.GetMapCopyPlayerManager().GetPlayerCount() <= 0 or not robotMaxLV:
|
| | | #GameWorld.DebugLog("没玩家,不刷机器人! ")
|
| | | return
|
| | | rmarkList = IpyGameDataPY.GetFuncEvalCfg('ElderBattlefieldRobot', 5)
|
| | | curNPCCnt = 0
|
| | |
| | | # @remarks 用于通知阵营比分条
|
| | | def DoFBHelp(curPlayer, tick):
|
| | | gameWorld = GameWorld.GetGameWorld()
|
| | | lineID = gameWorld.GetLineID()
|
| | | playerID = curPlayer.GetPlayerID()
|
| | | score = gameWorld.GetGameWorldDictByKey(FBPlayerDict_Score % playerID)
|
| | | stageScoreList = IpyGameDataPY.GetFuncEvalCfg('ElderBattlefieldCfg', 4)
|
| | |
| | | helpDict['topPlayerID'] = topPlayerID
|
| | | #helpDict[FBCommon.Help_lineID] = GameWorld.GetGameWorld().GetLineID()
|
| | | helpDict['enemyID'] = GameWorld.GetGameFB().GetPlayerGameFBDictByKey(playerID, FBPlayerDict_EnemyID)
|
| | | helpDict[FBCommon.Help_robotJob] = PyGameData.g_fbRobotJobDict.get(lineID, {})
|
| | | GameWorld.DebugLog("DoFBHelp %s" % helpDict, playerID)
|
| | | FBCommon.Notify_FBHelp(curPlayer, helpDict)
|
| | | return
|
| | |
| | | gameFBMgr.SetPlayerLogoffTick(0)
|
| | | gameFBMgr.SetIsSafeClose(0)
|
| | |
|
| | | GameWorld.Log("FB Close! lineID = %s, openState = %s"%(gameWorld.GetLineID(), gameWorld.GetOpenState()))
|
| | | lineID = gameWorld.GetLineID()
|
| | | GameWorld.Log("FB Close! lineID = %s, openState = %s"%(lineID, gameWorld.GetOpenState()))
|
| | |
|
| | | gameWorld.SetOpenState(IPY_GameWorld.fbosClosed)
|
| | | gameMap = gameWorld.GetMap()
|
| | |
| | | #副本关闭时统一清怪
|
| | | FBCommon.ClearFBNPC()
|
| | |
|
| | | if lineID in PyGameData.g_fbRobotJobDict:
|
| | | PyGameData.g_fbRobotJobDict.pop(lineID)
|
| | | |
| | | mapID = FBCommon.GetRecordMapID(gameMap.GetMapID())
|
| | | #清理物品
|
| | | unPickItemDict = {}
|
| | |
| | | #-------------------------------------------------------------------------------
|
| | |
|
| | | import ChConfig
|
| | | import AICommon
|
| | | import NPCCommon
|
| | | import BaseAttack
|
| | | import IpyGameDataPY
|
| | | import IPY_GameWorld
|
| | | import GameWorld
|
| | | import FBCommon
|
| | | import GameObj
|
| | |
|
| | | import random
|
| | | #---------------------------------------------------------------------
|
| | |
|
| | | #---------------------------------------------------------------------
|
| | | ## 初始化
|
| | | # @param curNPC NPC实例
|
| | | # @param curNPC 当前npc
|
| | | # @return None
|
| | | # @remarks 函数详细说明.
|
| | | def DoInit(curNPC):
|
| | | curNPC.GetNPCAngry().Init(ChConfig.Def_BossAngryCount)
|
| | | curNPC.GetNPCAngry().Init(ChConfig.Def_SuperFBBossAngryCount)
|
| | | return
|
| | |
|
| | | def OnNPCReborn(curNPC):
|
| | | curNPC.SetIsNeedProcess(True)
|
| | | return
|
| | |
|
| | | ## 执行AI
|
| | | # @param curNPC 当前npc
|
| | | # @param tick 当前时间
|
| | | # @return None
|
| | | # @remarks 函数详细说明.
|
| | | def ProcessAI(curNPC, tick):
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | if curNPC.GetCurAction() == IPY_GameWorld.laNPCDie or not curNPC.IsAlive():
|
| | | return
|
| | | |
| | | #刷新自己的buff
|
| | | npcControl.RefreshBuffState(tick)
|
| | | if GameObj.GetHP(curNPC) == 0:
|
| | | # BUFF刷新中可能会导致NPC死亡
|
| | | return
|
| | | |
| | | #刷新自己仇恨度列表
|
| | | npcControl.RefreshAngryList(tick)
|
| | | curNPCAngry = npcControl.GetMaxAngryTag()
|
| | | |
| | | #仇恨度列表中的人为空
|
| | | if curNPCAngry == None:
|
| | | if curNPC.GetSpeed() != 0:
|
| | | __RobotMove(curNPC)
|
| | | return
|
| | | |
| | | #仇恨对象类型,仇恨对象ID
|
| | | curNPCAngryType = curNPCAngry.GetObjType()
|
| | | curNPCAngryID = curNPCAngry.GetObjID()
|
| | | |
| | | #执行攻击逻辑
|
| | | __NPCFight(curNPC, curNPCAngryID, curNPCAngryType, tick)
|
| | | return
|
| | |
|
| | | def __RobotMove(curNPC):
|
| | | if curNPC.GetCurAction() == IPY_GameWorld.laNPCMove:
|
| | | #GameWorld.DebugLog("移动中不处理!(%s,%s)" % (curNPC.GetPosX(), curNPC.GetPosY()))
|
| | | return
|
| | | mapID = GameWorld.GetMap().GetMapID()
|
| | | lineID = FBCommon.GetFBPropertyMark()
|
| | | posKey = "%d%02d" % (mapID, lineID)
|
| | | fbMovePosDict = IpyGameDataPY.GetFuncCfg("AI198Point", 1)
|
| | | if posKey not in fbMovePosDict:
|
| | | posKey = "%d%02d" % (mapID, 0)
|
| | | if posKey not in fbMovePosDict:
|
| | | return
|
| | | |
| | | posList = fbMovePosDict[posKey]
|
| | | Key_PosIndex = "RobotMovePosIndex" # NPC上次移动的坐标索引,存值+1
|
| | | posIndex = curNPC.GetDictByKey(Key_PosIndex) - 1
|
| | | if posIndex < 0:
|
| | | # 还没有走过点的,寻找所有点中最近的点
|
| | | posIndex = random.randint(0, len(posList) - 1)
|
| | | else:
|
| | | tagPosX, tagPosY = posList[posIndex]
|
| | | tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), tagPosX, tagPosY)
|
| | | if tagDist < 2:
|
| | | posIndex += 1
|
| | | |
| | | if posIndex < 0 or posIndex >= len(posList):
|
| | | posIndex = random.randint(0, len(posList) - 1)
|
| | | |
| | | curNPC.SetDict(Key_PosIndex, posIndex + 1)
|
| | | tagPosX, tagPosY = posList[posIndex]
|
| | | curNPC.Move(tagPosX, tagPosY)
|
| | | return
|
| | |
|
| | | #---------------------------------------------------------------------
|
| | | ##正常AI逻辑处理
|
| | | #@param curNPC NPC实例
|
| | | #@param tick 时间戳
|
| | | #@return 返回值无意义
|
| | | #@remarks 正常AI逻辑处理
|
| | | def ProcessAI(curNPC, tick):
|
| | | ## npc攻击逻辑
|
| | | # @param curNPC 当前npc
|
| | | # @param tagID curNPCAngryID
|
| | | # @param tagType curNPCAngryType |
| | | # @param tick 当前时间
|
| | | # @return None
|
| | | # @remarks 函数详细说明.
|
| | | def __NPCFight(curNPC, tagID, tagType, tick):
|
| | | #设置进入战斗状态
|
| | | NPCCommon.SetNPCInBattleState(curNPC)
|
| | | npcControl = NPCCommon.NPCControl(curNPC)
|
| | | |
| | | #开始攻击
|
| | | curTag = GameWorld.GetObj(tagID, tagType)
|
| | | |
| | | if curTag == None or GameObj.GetHP(curTag) <= 0:
|
| | | return
|
| | | |
| | | tagDist = GameWorld.GetDist(curNPC.GetPosX(), curNPC.GetPosY(), curTag.GetPosX(), curTag.GetPosY())
|
| | | |
| | | #---优先释放技能---
|
| | | if AICommon.DoAutoUseSkill(curNPC, curTag, tagDist, tick):
|
| | | return
|
| | | |
| | | #---释放普通攻击---
|
| | | |
| | | if curNPC.GetSpeed() == 0:
|
| | | # 不可移动NPC
|
| | | if tagDist > curNPC.GetAtkDist():
|
| | | return
|
| | | |
| | | if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
|
| | | #攻击间隔没有到, 返回
|
| | | return
|
| | | |
| | | #普通攻击
|
| | | BaseAttack.Attack(curNPC, curTag, None, tick)
|
| | | return
|
| | | |
| | | #超过攻击距离,移动过去
|
| | | if tagDist > curNPC.GetAtkDist():
|
| | |
|
| | | destDist = GameWorld.GetDist(curNPC.GetDestPosX() , curNPC.GetDestPosY(), curTag.GetPosX(), curTag.GetPosY())
|
| | | if destDist <= curNPC.GetAtkDist() and curNPC.GetCurAction() == IPY_GameWorld.laNPCMove:
|
| | | # 目标在移动的攻击范围内,不改变目标点
|
| | | return
|
| | | npcControl.MoveToObj_Detel(curTag)
|
| | | return
|
| | | else:
|
| | | curNPC.StopMove()
|
| | | |
| | | if tick - curNPC.GetAttackTick() < curNPC.GetAtkInterval():
|
| | | #攻击间隔没有到, 返回
|
| | | return
|
| | | |
| | | if npcControl.FixTagPos(curTag.GetPosX(), curTag.GetPosY()):
|
| | | #修正这个NPC的站立位置
|
| | | return
|
| | | |
| | | #普通攻击
|
| | | BaseAttack.Attack(curNPC, curTag, None, tick)
|
| | | return
|
| | |
|
| | | ## NPC死亡
|
| | | # @param curNPC 当前npc
|
| | | # @param hurtType 伤害者的obj类型
|
| | | # @param hurtID 伤害者的objID
|
| | | # @return None
|
| | | def OnDie(curNPC, hurtType, hurtID):
|
| | | AICommon.DoNPCUseSkillOnDie(curNPC)
|
| | | return
|
| | |
|
| | |
|
| | |
|
| | | |
| | |
| | | # 根据平均等级
|
| | | elif lvStrengthenType == 1:
|
| | | strengthenLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenAverageLV)
|
| | | # 根据按成长等级的上下限随机
|
| | | elif lvStrengthenType == 4:
|
| | | randMinLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMinLV)
|
| | | randMaxLV = gameFB.GetGameFBDictByKey(ChConfig.Def_FB_NPCStrengthenMaxLV)
|
| | | strengthenLV = random.randint(randMinLV, randMaxLV)
|
| | |
|
| | | if strengthenIpyData.GetCmpNPCBaseLV():
|
| | | strengthenLV = max(strengthenLV, curNPC.GetLV())
|
| | |
| | | curNPC.Notify_HPEx()
|
| | | curNPC.Notify_MaxHPEx()
|
| | | #GameWorld.DebugLog(" aftHP=%s,aftMaxHP=%s" % (aftHP, aftMaxHP))
|
| | | |
| | | # 机器人复活初始化给技能
|
| | | if isReborn and curNPC.GetType() == ChConfig.ntRobot:
|
| | | __OnFBRobotReborn(curNPC, strengthenLV)
|
| | | |
| | | return
|
| | |
|
| | | def __OnFBRobotReborn(curNPC, npcLV):
|
| | | tick = GameWorld.GetGameWorld().GetTick()
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | objID = curNPC.GetID()
|
| | | jobSkillDict = IpyGameDataPY.GetFuncEvalCfg("FBRobotCfg", 1)
|
| | | robotJob = random.choice(jobSkillDict.keys())
|
| | | lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})
|
| | | lineRobotJobDict[objID] = robotJob
|
| | | PyGameData.g_fbRobotJobDict[lineID] = lineRobotJobDict
|
| | | skillInfoDict = jobSkillDict[robotJob]
|
| | | skillIDList = []
|
| | | for skillInfo, needLV in skillInfoDict.items():
|
| | | if npcLV < needLV:
|
| | | continue
|
| | | if isinstance(skillInfo, int):
|
| | | skillIDList.append(skillInfo)
|
| | | else:
|
| | | skillIDList += list(skillInfo)
|
| | | GameWorld.DebugLog("给机器人NPC技能: objID=%s,robotJob=%s,npcLV=%s, %s" % (objID, robotJob, npcLV, skillIDList))
|
| | | skillManager = curNPC.GetSkillManager()
|
| | | for skillID in skillIDList:
|
| | | skillManager.LearnSkillByID(skillID)
|
| | | playerManager = GameWorld.GetMapCopyPlayerManager()
|
| | | for index in xrange(playerManager.GetPlayerCount()):
|
| | | curPlayer = playerManager.GetPlayerByIndex(index)
|
| | | if not curPlayer:
|
| | | continue
|
| | | FBLogic.DoFBHelp(curPlayer, tick)
|
| | | return
|
| | |
|
| | |
|
| | | def __DoGiveVSPlayerNPCSkill(curNPC, job, npcLV):
|
| | | skillManager = curNPC.GetSkillManager()
|
| | | jobSkillDict = IpyGameDataPY.GetFuncEvalCfg("XMZZRobotSkill", 1)
|
| | | if job not in jobSkillDict:
|
| | | return
|
| | | skillInfoDict = jobSkillDict[job]
|
| | | #{1:{(100, 101, 102, 103):1, 50000:100, 50100:200, 50400:300}, 2:{(200, 201, 202, 203):1, 55000:100, 55100:200, 55200:300}}
|
| | | skillIDList = []
|
| | | for skillInfo, needLV in skillInfoDict.items():
|
| | | if npcLV < needLV:
|
| | | continue
|
| | | if isinstance(skillInfo, int):
|
| | | skillIDList.append(skillInfo)
|
| | | else:
|
| | | skillIDList += list(skillInfo)
|
| | | GameWorld.DebugLog("给NPC技能: job=%s,npcLV=%s, %s" % (job, npcLV, skillIDList))
|
| | | for skillID in skillIDList:
|
| | | skillManager.LearnSkillByID(skillID)
|
| | | return
|
| | |
|
| | | def GetNPCStrengthenAttrDict(npcID, strengthenLV=0, strengthenPlayerCnt=0, strengthenIpyData=None):
|
| | |
| | | AttackCommon.ClearTeamPlayerHurtValue(curNPC)
|
| | | # 清除自定义伤血列表
|
| | | #BossHurtMng.ClearHurtValueList(curNPC)
|
| | |
|
| | | if curNPC.GetType() == ChConfig.ntRobot:
|
| | | lineID = GameWorld.GetGameWorld().GetLineID()
|
| | | lineRobotJobDict = PyGameData.g_fbRobotJobDict.get(lineID, {})
|
| | | lineRobotJobDict.pop(curNPC.GetID(), 0)
|
| | | PyGameData.g_fbRobotJobDict[lineID] = lineRobotJobDict
|
| | | |
| | | # C++设置npc死亡
|
| | | curNPC.SetDead(curNPC.GetDictByKey(ChConfig.Def_NPCDead_Reason),
|
| | | curNPC.GetDictByKey(ChConfig.Def_NPCDead_KillerType),
|
| | |
| | | def GetIsBossView(self):
|
| | | # 主动视野情况,GetIsBoss 0 1 4 为普通NPC视野(有视野范围配置,但去除视野刷新),其他为BOSS类视野有刷新
|
| | | curNPC = self.__Instance
|
| | | if not ChConfig.IsGameBoss(curNPC) and not GetFaction(curNPC):
|
| | | if not ChConfig.IsGameBoss(curNPC) and not GetFaction(curNPC) and curNPC.GetType() != ChConfig.ntRobot:
|
| | | return False
|
| | |
|
| | | return True
|
| | |
| | | g_teamFBMemRelationAddDict = {} # 组队副本队员关系加成信息 {playerID:[relation, relationAdd, relationPlayerID, relationPlayerName], ...}
|
| | |
|
| | |
|
| | | g_fightpowerChangeDataRecordDict = {} #导致战力降低的各种行为记录 |
| | | g_fightpowerChangeDataRecordDict = {} #导致战力降低的各种行为记录
|
| | |
|
| | | g_fbRobotJobDict = {} #副本机器人职业 {lineID:{objID:job, ...}, ...}
|